00001
00002
00003
00004
00005
00006
00007 #include "nc.h"
00008 #include <stdlib.h>
00009 #include <string.h>
00010 #include <assert.h>
00011 #include "ncx.h"
00012 #include "fbits.h"
00013
00014
00015
00016
00017
00018
00019 void
00020 free_NC_dim(NC_dim *dimp)
00021 {
00022 if(dimp == NULL)
00023 return;
00024 free_NC_string(dimp->name);
00025 free(dimp);
00026 }
00027
00028
00029 NC_dim *
00030 new_x_NC_dim(NC_string *name)
00031 {
00032 NC_dim *dimp;
00033
00034 dimp = (NC_dim *) malloc(sizeof(NC_dim));
00035 if(dimp == NULL)
00036 return NULL;
00037
00038 dimp->name = name;
00039 dimp->size = 0;
00040
00041 return(dimp);
00042 }
00043
00044
00045
00046
00047
00048
00049 static NC_dim *
00050 new_NC_dim(const char *name, size_t size)
00051 {
00052 NC_string *strp;
00053 NC_dim *dimp;
00054
00055 strp = new_NC_string(strlen(name), name);
00056 if(strp == NULL)
00057 return NULL;
00058
00059 dimp = new_x_NC_dim(strp);
00060 if(dimp == NULL)
00061 {
00062 free_NC_string(strp);
00063 return NULL;
00064 }
00065
00066 dimp->size = size;
00067
00068 return(dimp);
00069 }
00070
00071
00072 static NC_dim *
00073 dup_NC_dim(const NC_dim *dimp)
00074 {
00075 return new_NC_dim(dimp->name->cp, dimp->size);
00076 }
00077
00078
00079
00080
00081
00082
00083
00084
00085 int
00086 find_NC_Udim(const NC_dimarray *ncap, NC_dim **dimpp)
00087 {
00088 assert(ncap != NULL);
00089
00090 if(ncap->nelems == 0)
00091 return -1;
00092
00093 {
00094 int dimid = 0;
00095 NC_dim **loc = ncap->value;
00096
00097 for(; (size_t) dimid < ncap->nelems
00098 && (*loc)->size != NC_UNLIMITED; dimid++, loc++)
00099 {
00100
00101 }
00102 if(dimid >= ncap->nelems)
00103 return(-1);
00104
00105 if(dimpp != NULL)
00106 *dimpp = *loc;
00107 return dimid;
00108 }
00109 }
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 static int
00120 NC_finddim(const NC_dimarray *ncap, const char *name, NC_dim **dimpp)
00121 {
00122
00123 assert(ncap != NULL);
00124
00125 if(ncap->nelems == 0)
00126 return -1;
00127
00128 {
00129 size_t slen = strlen(name);
00130 int dimid = 0;
00131 NC_dim **loc = (NC_dim **) ncap->value;
00132
00133 for(; (size_t) dimid < ncap->nelems
00134 && (strlen((*loc)->name->cp) != slen
00135 || strncmp((*loc)->name->cp, name, slen) != 0);
00136 dimid++, loc++)
00137 {
00138
00139 }
00140 if(dimid >= ncap->nelems)
00141 return(-1);
00142
00143 if(dimpp != NULL)
00144 *dimpp = *loc;
00145 return(dimid);
00146 }
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 void
00158 free_NC_dimarrayV0(NC_dimarray *ncap)
00159 {
00160 assert(ncap != NULL);
00161
00162 if(ncap->nelems == 0)
00163 return;
00164
00165 assert(ncap->value != NULL);
00166
00167 {
00168 NC_dim **dpp = ncap->value;
00169 NC_dim *const *const end = &dpp[ncap->nelems];
00170 for( ; dpp < end; dpp++)
00171 {
00172 free_NC_dim(*dpp);
00173 *dpp = NULL;
00174 }
00175 }
00176 ncap->nelems = 0;
00177 }
00178
00179
00180
00181
00182
00183
00184
00185 void
00186 free_NC_dimarrayV(NC_dimarray *ncap)
00187 {
00188 assert(ncap != NULL);
00189
00190 if(ncap->nalloc == 0)
00191 return;
00192
00193 assert(ncap->value != NULL);
00194
00195 free_NC_dimarrayV0(ncap);
00196
00197 free(ncap->value);
00198 ncap->value = NULL;
00199 ncap->nalloc = 0;
00200 }
00201
00202
00203 int
00204 dup_NC_dimarrayV(NC_dimarray *ncap, const NC_dimarray *ref)
00205 {
00206 int status = NC_NOERR;
00207
00208 assert(ref != NULL);
00209 assert(ncap != NULL);
00210
00211 if(ref->nelems != 0)
00212 {
00213 const size_t sz = ref->nelems * sizeof(NC_dim *);
00214 ncap->value = (NC_dim **) malloc(sz);
00215 if(ncap->value == NULL)
00216 return NC_ENOMEM;
00217 (void) memset(ncap->value, 0, sz);
00218 ncap->nalloc = ref->nelems;
00219 }
00220
00221 ncap->nelems = 0;
00222 {
00223 NC_dim **dpp = ncap->value;
00224 const NC_dim **drpp = (const NC_dim **)ref->value;
00225 NC_dim *const *const end = &dpp[ref->nelems];
00226 for( ; dpp < end; drpp++, dpp++, ncap->nelems++)
00227 {
00228 *dpp = dup_NC_dim(*drpp);
00229 if(*dpp == NULL)
00230 {
00231 status = NC_ENOMEM;
00232 break;
00233 }
00234 }
00235 }
00236
00237 if(status != NC_NOERR)
00238 {
00239 free_NC_dimarrayV(ncap);
00240 return status;
00241 }
00242
00243 assert(ncap->nelems == ref->nelems);
00244
00245 return NC_NOERR;
00246 }
00247
00248
00249
00250
00251
00252
00253
00254 static int
00255 incr_NC_dimarray(NC_dimarray *ncap, NC_dim *newelemp)
00256 {
00257 NC_dim **vp;
00258
00259 assert(ncap != NULL);
00260
00261 if(ncap->nalloc == 0)
00262 {
00263 assert(ncap->nelems == 0);
00264 vp = (NC_dim **) malloc(NC_ARRAY_GROWBY * sizeof(NC_dim *));
00265 if(vp == NULL)
00266 return NC_ENOMEM;
00267 ncap->value = vp;
00268 ncap->nalloc = NC_ARRAY_GROWBY;
00269 }
00270 else if(ncap->nelems +1 > ncap->nalloc)
00271 {
00272 vp = (NC_dim **) realloc(ncap->value,
00273 (ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_dim *));
00274 if(vp == NULL)
00275 return NC_ENOMEM;
00276 ncap->value = vp;
00277 ncap->nalloc += NC_ARRAY_GROWBY;
00278 }
00279
00280 if(newelemp != NULL)
00281 {
00282 ncap->value[ncap->nelems] = newelemp;
00283 ncap->nelems++;
00284 }
00285 return NC_NOERR;
00286 }
00287
00288
00289 NC_dim *
00290 elem_NC_dimarray(const NC_dimarray *ncap, size_t elem)
00291 {
00292 assert(ncap != NULL);
00293
00294 if(ncap->nelems == 0 || (unsigned long) elem >= ncap->nelems)
00295 return NULL;
00296
00297 assert(ncap->value != NULL);
00298
00299 return ncap->value[elem];
00300 }
00301
00302
00303
00304
00305 int
00306 nc_def_dim(int ncid, const char *name, size_t size, int *dimidp)
00307 {
00308 int status;
00309 NC *ncp;
00310 int dimid;
00311 NC_dim *dimp;
00312
00313 status = NC_check_id(ncid, &ncp);
00314 if(status != NC_NOERR)
00315 return status;
00316
00317 if(!NC_indef(ncp))
00318 return NC_ENOTINDEFINE;
00319
00320 status = NC_check_name(name);
00321 if(status != NC_NOERR)
00322 return status;
00323
00324 if ((ncp->flags & NC_64BIT_OFFSET) && sizeof(off_t) > 4) {
00325
00326 if(size > X_UINT_MAX - 3)
00327 return NC_EDIMSIZE;
00328 } else {
00329
00330 if(size > X_INT_MAX - 3)
00331 return NC_EDIMSIZE;
00332 }
00333
00334 if(size == NC_UNLIMITED)
00335 {
00336 dimid = find_NC_Udim(&ncp->dims, &dimp);
00337 if(dimid != -1)
00338 {
00339 assert(dimid != -1);
00340 return NC_EUNLIMIT;
00341 }
00342 }
00343
00344 if(ncp->dims.nelems >= NC_MAX_DIMS)
00345 return NC_EMAXDIMS;
00346
00347 dimid = NC_finddim(&ncp->dims, name, &dimp);
00348 if(dimid != -1)
00349 return NC_ENAMEINUSE;
00350
00351 dimp = new_NC_dim(name, size);
00352 if(dimp == NULL)
00353 return NC_ENOMEM;
00354 status = incr_NC_dimarray(&ncp->dims, dimp);
00355 if(status != NC_NOERR)
00356 {
00357 free_NC_dim(dimp);
00358 return status;
00359 }
00360
00361 if(dimidp != NULL)
00362 *dimidp = (int)ncp->dims.nelems -1;
00363 return NC_NOERR;
00364 }
00365
00366
00367 int
00368 nc_inq_dimid(int ncid, const char *name, int *dimid_ptr)
00369 {
00370 int status;
00371 NC *ncp;
00372 int dimid;
00373
00374 status = NC_check_id(ncid, &ncp);
00375 if(status != NC_NOERR)
00376 return status;
00377
00378 dimid = NC_finddim(&ncp->dims, name, NULL);
00379
00380 if(dimid == -1)
00381 return NC_EBADDIM;
00382
00383 *dimid_ptr = dimid;
00384 return NC_NOERR;
00385 }
00386
00387
00388 int
00389 nc_inq_dim(int ncid, int dimid, char *name, size_t *sizep)
00390 {
00391 int status;
00392 NC *ncp;
00393 NC_dim *dimp;
00394
00395 status = NC_check_id(ncid, &ncp);
00396 if(status != NC_NOERR)
00397 return status;
00398
00399 dimp = elem_NC_dimarray(&ncp->dims, (size_t)dimid);
00400 if(dimp == NULL)
00401 return NC_EBADDIM;
00402
00403 if(name != NULL)
00404 {
00405 (void)strncpy(name, dimp->name->cp,
00406 dimp->name->nchars);
00407 name[dimp->name->nchars] = 0;
00408 }
00409 if(sizep != 0)
00410 {
00411 if(dimp->size == NC_UNLIMITED)
00412 *sizep = NC_get_numrecs(ncp);
00413 else
00414 *sizep = dimp->size;
00415 }
00416 return NC_NOERR;
00417 }
00418
00419
00420 int
00421 nc_inq_dimname(int ncid, int dimid, char *name)
00422 {
00423 int status;
00424 NC *ncp;
00425 NC_dim *dimp;
00426
00427 status = NC_check_id(ncid, &ncp);
00428 if(status != NC_NOERR)
00429 return status;
00430
00431 dimp = elem_NC_dimarray(&ncp->dims, (size_t)dimid);
00432 if(dimp == NULL)
00433 return NC_EBADDIM;
00434
00435 if(name != NULL)
00436 {
00437 (void)strncpy(name, dimp->name->cp,
00438 dimp->name->nchars);
00439 name[dimp->name->nchars] = 0;
00440 }
00441
00442 return NC_NOERR;
00443 }
00444
00445
00446 int
00447 nc_inq_dimlen(int ncid, int dimid, size_t *lenp)
00448 {
00449 int status;
00450 NC *ncp;
00451 NC_dim *dimp;
00452
00453 status = NC_check_id(ncid, &ncp);
00454 if(status != NC_NOERR)
00455 return status;
00456
00457 dimp = elem_NC_dimarray(&ncp->dims, (size_t)dimid);
00458 if(dimp == NULL)
00459 return NC_EBADDIM;
00460
00461 if(lenp != 0)
00462 {
00463 if(dimp->size == NC_UNLIMITED)
00464 *lenp = NC_get_numrecs(ncp);
00465 else
00466 *lenp = dimp->size;
00467 }
00468 return NC_NOERR;
00469 }
00470
00471
00472 int
00473 nc_rename_dim( int ncid, int dimid, const char *newname)
00474 {
00475 int status;
00476 NC *ncp;
00477 int existid;
00478 NC_dim *dimp;
00479
00480 status = NC_check_id(ncid, &ncp);
00481 if(status != NC_NOERR)
00482 return status;
00483
00484 if(NC_readonly(ncp))
00485 return NC_EPERM;
00486
00487 status = NC_check_name(newname);
00488 if(status != NC_NOERR)
00489 return status;
00490
00491 existid = NC_finddim(&ncp->dims, newname, &dimp);
00492 if(existid != -1)
00493 return NC_ENAMEINUSE;
00494
00495 dimp = elem_NC_dimarray(&ncp->dims, (size_t)dimid);
00496 if(dimp == NULL)
00497 return NC_EBADDIM;
00498
00499 if(NC_indef(ncp))
00500 {
00501 NC_string *old = dimp->name;
00502 NC_string *newStr = new_NC_string(strlen(newname), newname);
00503 if(newStr == NULL)
00504 return NC_ENOMEM;
00505 dimp->name = newStr;
00506 free_NC_string(old);
00507 return NC_NOERR;
00508 }
00509
00510
00511
00512 status = set_NC_string(dimp->name, newname);
00513 if(status != NC_NOERR)
00514 return status;
00515
00516 set_NC_hdirty(ncp);
00517
00518 if(NC_doHsync(ncp))
00519 {
00520 status = NC_sync(ncp);
00521 if(status != NC_NOERR)
00522 return status;
00523 }
00524
00525 return NC_NOERR;
00526 }