00001
00002
00003
00004
00005
00006 #include "nc.h"
00007 #include <stdlib.h>
00008 #include <string.h>
00009 #include <assert.h>
00010 #include "ncx.h"
00011 #include "rnd.h"
00012
00013
00014
00015
00016
00017
00018
00019 void
00020 free_NC_var(NC_var *varp)
00021 {
00022 if(varp == NULL)
00023 return;
00024 free_NC_attrarrayV(&varp->attrs);
00025 free_NC_string(varp->name);
00026 free(varp);
00027 }
00028
00029
00030
00031
00032
00033
00034 NC_var *
00035 new_x_NC_var(
00036 NC_string *strp,
00037 size_t ndims)
00038 {
00039 NC_var *varp;
00040 const size_t o1 = M_RNDUP(ndims * sizeof(int));
00041 const size_t o2 = M_RNDUP(ndims * sizeof(size_t));
00042 const size_t sz = M_RNDUP(sizeof(NC_var)) +
00043 o1 + o2 + ndims * sizeof(size_t);
00044
00045 varp = (NC_var *) malloc(sz);
00046 if(varp == NULL )
00047 return NULL;
00048 (void) memset(varp, 0, sz);
00049
00050 varp->name = strp;
00051 varp->ndims = ndims;
00052
00053 if(ndims != 0)
00054 {
00055
00056
00057
00058
00059
00060 varp->dimids = (int *)((char *)varp + M_RNDUP(sizeof(NC_var)));
00061 varp->shape = (size_t *)((char *)varp->dimids + o1);
00062 varp->dsizes = (size_t *)((char *)varp->shape + o2);
00063 }
00064
00065 varp->xsz = 0;
00066 varp->len = 0;
00067 varp->begin = 0;
00068
00069 return varp;
00070 }
00071
00072
00073
00074
00075
00076
00077 static NC_var *
00078 new_NC_var(const char *name, nc_type type,
00079 size_t ndims, const int *dimids)
00080 {
00081 NC_string *strp;
00082 NC_var *varp;
00083
00084 strp = new_NC_string(strlen(name), name);
00085 if(strp == NULL)
00086 return NULL;
00087
00088 varp = new_x_NC_var(strp, ndims);
00089 if(varp == NULL )
00090 {
00091 free_NC_string(strp);
00092 return NULL;
00093 }
00094
00095 varp->type = type;
00096
00097 if( ndims != 0 && dimids != NULL)
00098 (void) memcpy(varp->dimids, dimids, ndims * sizeof(int));
00099
00100 return(varp);
00101 }
00102
00103
00104 static NC_var *
00105 dup_NC_var(const NC_var *rvarp)
00106 {
00107 NC_var *varp = new_NC_var(rvarp->name->cp, rvarp->type,
00108 rvarp->ndims, rvarp->dimids);
00109 if(varp == NULL)
00110 return NULL;
00111
00112
00113 if(dup_NC_attrarrayV(&varp->attrs, &rvarp->attrs) != NC_NOERR)
00114 {
00115 free_NC_var(varp);
00116 return NULL;
00117 }
00118
00119 (void) memcpy(varp->shape, rvarp->shape,
00120 rvarp->ndims * sizeof(size_t));
00121 (void) memcpy(varp->dsizes, rvarp->dsizes,
00122 rvarp->ndims * sizeof(size_t));
00123 varp->xsz = rvarp->xsz;
00124 varp->len = rvarp->len;
00125 varp->begin = rvarp->begin;
00126
00127 return varp;
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 void
00139 free_NC_vararrayV0(NC_vararray *ncap)
00140 {
00141 assert(ncap != NULL);
00142
00143 if(ncap->nelems == 0)
00144 return;
00145
00146 assert(ncap->value != NULL);
00147
00148 {
00149 NC_var **vpp = ncap->value;
00150 NC_var *const *const end = &vpp[ncap->nelems];
00151 for( ; vpp < end; vpp++)
00152 {
00153 free_NC_var(*vpp);
00154 *vpp = NULL;
00155 }
00156 }
00157 ncap->nelems = 0;
00158 }
00159
00160
00161
00162
00163
00164
00165
00166 void
00167 free_NC_vararrayV(NC_vararray *ncap)
00168 {
00169 assert(ncap != NULL);
00170
00171 if(ncap->nalloc == 0)
00172 return;
00173
00174 assert(ncap->value != NULL);
00175
00176 free_NC_vararrayV0(ncap);
00177
00178 free(ncap->value);
00179 ncap->value = NULL;
00180 ncap->nalloc = 0;
00181 }
00182
00183
00184 int
00185 dup_NC_vararrayV(NC_vararray *ncap, const NC_vararray *ref)
00186 {
00187 int status = NC_NOERR;
00188
00189 assert(ref != NULL);
00190 assert(ncap != NULL);
00191
00192 if(ref->nelems != 0)
00193 {
00194 const size_t sz = ref->nelems * sizeof(NC_var *);
00195 ncap->value = (NC_var **) malloc(sz);
00196 if(ncap->value == NULL)
00197 return NC_ENOMEM;
00198 (void) memset(ncap->value, 0, sz);
00199 ncap->nalloc = ref->nelems;
00200 }
00201
00202 ncap->nelems = 0;
00203 {
00204 NC_var **vpp = ncap->value;
00205 const NC_var **drpp = (const NC_var **)ref->value;
00206 NC_var *const *const end = &vpp[ref->nelems];
00207 for( ; vpp < end; drpp++, vpp++, ncap->nelems++)
00208 {
00209 *vpp = dup_NC_var(*drpp);
00210 if(*vpp == NULL)
00211 {
00212 status = NC_ENOMEM;
00213 break;
00214 }
00215 }
00216 }
00217
00218 if(status != NC_NOERR)
00219 {
00220 free_NC_vararrayV(ncap);
00221 return status;
00222 }
00223
00224 assert(ncap->nelems == ref->nelems);
00225
00226 return NC_NOERR;
00227 }
00228
00229
00230
00231
00232
00233
00234
00235 static int
00236 incr_NC_vararray(NC_vararray *ncap, NC_var *newelemp)
00237 {
00238 NC_var **vp;
00239
00240 assert(ncap != NULL);
00241
00242 if(ncap->nalloc == 0)
00243 {
00244 assert(ncap->nelems == 0);
00245 vp = (NC_var **) malloc(NC_ARRAY_GROWBY * sizeof(NC_var *));
00246 if(vp == NULL)
00247 return NC_ENOMEM;
00248 ncap->value = vp;
00249 ncap->nalloc = NC_ARRAY_GROWBY;
00250 }
00251 else if(ncap->nelems +1 > ncap->nalloc)
00252 {
00253 vp = (NC_var **) realloc(ncap->value,
00254 (ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_var *));
00255 if(vp == NULL)
00256 return NC_ENOMEM;
00257 ncap->value = vp;
00258 ncap->nalloc += NC_ARRAY_GROWBY;
00259 }
00260
00261 if(newelemp != NULL)
00262 {
00263 ncap->value[ncap->nelems] = newelemp;
00264 ncap->nelems++;
00265 }
00266 return NC_NOERR;
00267 }
00268
00269
00270 static NC_var *
00271 elem_NC_vararray(const NC_vararray *ncap, size_t elem)
00272 {
00273 assert(ncap != NULL);
00274
00275 if(ncap->nelems == 0 || (unsigned long)elem >= ncap->nelems)
00276 return NULL;
00277
00278 assert(ncap->value != NULL);
00279
00280 return ncap->value[elem];
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 int
00295 NC_findvar(const NC_vararray *ncap, const char *name, NC_var **varpp)
00296 {
00297 NC_var **loc;
00298 size_t slen;
00299 int varid;
00300
00301 assert(ncap != NULL);
00302
00303 if(ncap->nelems == 0)
00304 return -1;
00305
00306 loc = (NC_var **) ncap->value;
00307
00308 slen = strlen(name);
00309
00310 for(varid = 0; (size_t) varid < ncap->nelems; varid++, loc++)
00311 {
00312 if(strlen((*loc)->name->cp) == slen &&
00313 strncmp((*loc)->name->cp, name, slen) == 0)
00314 {
00315 if(varpp != NULL)
00316 *varpp = *loc;
00317 return(varid);
00318 }
00319 }
00320 return(-1);
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 size_t
00332 ncx_szof(nc_type type)
00333 {
00334 switch(type){
00335 case NC_BYTE:
00336 case NC_CHAR:
00337 return(1);
00338 case NC_SHORT :
00339 return(2);
00340 case NC_INT:
00341 return X_SIZEOF_INT;
00342 case NC_FLOAT:
00343 return X_SIZEOF_FLOAT;
00344 case NC_DOUBLE :
00345 return X_SIZEOF_DOUBLE;
00346 }
00347
00348 assert("ncx_szof invalid type" == 0);
00349 return 0;
00350 }
00351
00352
00353
00354
00355
00356
00357
00358 int
00359 NC_var_shape(NC_var *varp, const NC_dimarray *dims)
00360 {
00361 size_t *shp, *dsp, *op;
00362 int *ip;
00363 const NC_dim *dimp;
00364 size_t product = 1;
00365
00366 varp->xsz = ncx_szof(varp->type);
00367
00368 if(varp->ndims == 0)
00369 {
00370 goto out;
00371 }
00372
00373
00374
00375
00376
00377 for(ip = varp->dimids, op = varp->shape
00378 ; ip < &varp->dimids[varp->ndims]; ip++, op++)
00379 {
00380 if(*ip < 0 || (size_t) (*ip) >= ((dims != NULL) ? dims->nelems : 1) )
00381 return NC_EBADDIM;
00382
00383 dimp = elem_NC_dimarray(dims, (size_t)*ip);
00384 *op = dimp->size;
00385 if(*op == NC_UNLIMITED && ip != varp->dimids)
00386 return NC_EUNLIMPOS;
00387 }
00388
00389
00390
00391
00392
00393 for(shp = varp->shape + varp->ndims -1,
00394 dsp = varp->dsizes + varp->ndims -1;
00395 shp >= varp->shape;
00396 shp--, dsp--)
00397 {
00398 if(!(shp == varp->shape && IS_RECVAR(varp)))
00399 product *= *shp;
00400 *dsp = product;
00401 }
00402
00403
00404 out :
00405 varp->len = product * varp->xsz;
00406 switch(varp->type) {
00407 case NC_BYTE :
00408 case NC_CHAR :
00409 case NC_SHORT :
00410 if( varp->len%4 != 0 )
00411 {
00412 varp->len += 4 - varp->len%4;
00413
00414 }
00415 break;
00416 default:
00417
00418 break;
00419 }
00420 #if 0
00421 arrayp("\tshape", varp->ndims, varp->shape);
00422 arrayp("\tdsizes", varp->ndims, varp->dsizes);
00423 #endif
00424 return NC_NOERR;
00425 }
00426
00427
00428
00429
00430
00431
00432
00433
00434 NC_var *
00435 NC_lookupvar(NC *ncp, int varid)
00436 {
00437 NC_var *varp;
00438
00439 if(varid == NC_GLOBAL)
00440 {
00441
00442 return(NULL);
00443 }
00444
00445 varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
00446 if(varp == NULL)
00447 {
00448 return NULL;
00449 }
00450
00451 assert(varp != NULL);
00452
00453 return(varp);
00454 }
00455
00456
00457
00458
00459 int
00460 nc_def_var( int ncid, const char *name, nc_type type,
00461 int ndims, const int *dimids, int *varidp)
00462 {
00463 int status;
00464 NC *ncp;
00465 int varid;
00466 NC_var *varp;
00467
00468 status = NC_check_id(ncid, &ncp);
00469 if(status != NC_NOERR)
00470 return status;
00471
00472 if(!NC_indef(ncp))
00473 {
00474 return NC_ENOTINDEFINE;
00475 }
00476
00477 status = NC_check_name(name);
00478 if(status != NC_NOERR)
00479 return status;
00480
00481 status = nc_cktype(type);
00482 if(status != NC_NOERR)
00483 return status;
00484
00485
00486 if((unsigned long) ndims > X_INT_MAX)
00487 {
00488 return NC_EINVAL;
00489 }
00490
00491 if(ncp->vars.nelems >= NC_MAX_VARS)
00492 {
00493 return NC_EMAXVARS;
00494 }
00495
00496 varid = NC_findvar(&ncp->vars, name, &varp);
00497 if(varid != -1)
00498 {
00499 return NC_ENAMEINUSE;
00500 }
00501
00502 varp = new_NC_var(name, type, ndims, dimids);
00503 if(varp == NULL)
00504 return NC_ENOMEM;
00505
00506 status = NC_var_shape(varp, &ncp->dims);
00507 if(status != NC_NOERR)
00508 {
00509 free_NC_var(varp);
00510 return status;
00511 }
00512
00513 status = incr_NC_vararray(&ncp->vars, varp);
00514 if(status != NC_NOERR)
00515 {
00516 free_NC_var(varp);
00517 return status;
00518 }
00519
00520 if(varidp != NULL)
00521 *varidp = (int)ncp->vars.nelems -1;
00522 return NC_NOERR;
00523 }
00524
00525
00526 int
00527 nc_inq_varid(int ncid, const char *name, int *varid_ptr)
00528 {
00529 int status;
00530 NC *ncp;
00531 NC_var *varp;
00532 int varid;
00533
00534 status = NC_check_id(ncid, &ncp);
00535 if(status != NC_NOERR)
00536 return status;
00537
00538 varid = NC_findvar(&ncp->vars, name, &varp);
00539 if(varid == -1)
00540 {
00541 return NC_ENOTVAR;
00542 }
00543
00544 *varid_ptr = varid;
00545 return NC_NOERR;
00546 }
00547
00548
00549 int
00550 nc_inq_var(int ncid,
00551 int varid,
00552 char *name,
00553 nc_type *typep,
00554 int *ndimsp,
00555 int *dimids,
00556 int *nattsp)
00557 {
00558 int status;
00559 NC *ncp;
00560 NC_var *varp;
00561 size_t ii;
00562
00563 status = NC_check_id(ncid, &ncp);
00564 if(status != NC_NOERR)
00565 return status;
00566
00567 varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
00568 if(varp == NULL)
00569 return NC_ENOTVAR;
00570
00571 if(name != NULL)
00572 {
00573 (void) strncpy(name, varp->name->cp, varp->name->nchars);
00574 name[varp->name->nchars] = 0;
00575 }
00576
00577 if(typep != 0)
00578 *typep = varp->type;
00579 if(ndimsp != 0)
00580 {
00581 *ndimsp = (int) varp->ndims;
00582 }
00583 if(dimids != 0)
00584 {
00585 for(ii = 0; ii < varp->ndims; ii++)
00586 {
00587 dimids[ii] = varp->dimids[ii];
00588 }
00589 }
00590 if(nattsp != 0)
00591 {
00592 *nattsp = (int) varp->attrs.nelems;
00593 }
00594
00595 return NC_NOERR;
00596 }
00597
00598
00599 int
00600 nc_inq_varname(int ncid, int varid, char *name)
00601 {
00602 int status;
00603 NC *ncp;
00604 NC_var *varp;
00605
00606 status = NC_check_id(ncid, &ncp);
00607 if(status != NC_NOERR)
00608 return status;
00609
00610 varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
00611 if(varp == NULL)
00612 return NC_ENOTVAR;
00613
00614 if(name != NULL)
00615 {
00616 (void) strncpy(name, varp->name->cp, varp->name->nchars);
00617 name[varp->name->nchars] = 0;
00618 }
00619
00620 return NC_NOERR;
00621 }
00622
00623 int
00624 nc_inq_vartype(int ncid, int varid, nc_type *typep)
00625 {
00626 int status;
00627 NC *ncp;
00628 NC_var *varp;
00629
00630 status = NC_check_id(ncid, &ncp);
00631 if(status != NC_NOERR)
00632 return status;
00633
00634 varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
00635 if(varp == NULL)
00636 return NC_ENOTVAR;
00637
00638 if(typep != 0)
00639 *typep = varp->type;
00640
00641 return NC_NOERR;
00642 }
00643
00644 int
00645 nc_inq_varndims(int ncid, int varid, int *ndimsp)
00646 {
00647 int status;
00648 NC *ncp;
00649 NC_var *varp;
00650
00651 status = NC_check_id(ncid, &ncp);
00652 if(status != NC_NOERR)
00653 return status;
00654
00655 varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
00656 if(varp == NULL)
00657 return NC_ENOTVAR;
00658
00659 if(ndimsp != 0)
00660 {
00661 *ndimsp = (int) varp->ndims;
00662 }
00663
00664 return NC_NOERR;
00665 }
00666
00667
00668 int
00669 nc_inq_vardimid(int ncid, int varid, int *dimids)
00670 {
00671 int status;
00672 NC *ncp;
00673 NC_var *varp;
00674 size_t ii;
00675
00676 status = NC_check_id(ncid, &ncp);
00677 if(status != NC_NOERR)
00678 return status;
00679
00680 varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
00681 if(varp == NULL)
00682 return NC_ENOTVAR;
00683
00684 if(dimids != 0)
00685 {
00686 for(ii = 0; ii < varp->ndims; ii++)
00687 {
00688 dimids[ii] = varp->dimids[ii];
00689 }
00690 }
00691
00692 return NC_NOERR;
00693 }
00694
00695
00696 int
00697 nc_inq_varnatts(int ncid, int varid, int *nattsp)
00698 {
00699 int status;
00700 NC *ncp;
00701 NC_var *varp;
00702
00703 if(varid == NC_GLOBAL)
00704 return nc_inq_natts(ncid, nattsp);
00705
00706 status = NC_check_id(ncid, &ncp);
00707 if(status != NC_NOERR)
00708 return status;
00709
00710 varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
00711 if(varp == NULL)
00712 return NC_ENOTVAR;
00713
00714 if(nattsp != 0)
00715 {
00716 *nattsp = (int) varp->attrs.nelems;
00717 }
00718
00719 return NC_NOERR;
00720 }
00721
00722 int
00723 nc_rename_var(int ncid, int varid, const char *newname)
00724 {
00725 int status;
00726 NC *ncp;
00727 NC_var *varp;
00728 NC_string *old, *newStr;
00729 int other;
00730
00731 status = NC_check_id(ncid, &ncp);
00732 if(status != NC_NOERR)
00733 return status;
00734
00735 if(NC_readonly(ncp))
00736 {
00737 return NC_EPERM;
00738 }
00739
00740 status = NC_check_name(newname);
00741 if(status != NC_NOERR)
00742 return status;
00743
00744
00745 other = NC_findvar(&ncp->vars, newname, &varp);
00746 if(other != -1)
00747 {
00748 return NC_ENAMEINUSE;
00749 }
00750
00751 varp = NC_lookupvar(ncp, varid);
00752 if(varp == NULL)
00753 {
00754
00755 return NC_ENOTVAR;
00756 }
00757
00758 old = varp->name;
00759 if(NC_indef(ncp))
00760 {
00761 newStr = new_NC_string(strlen(newname),newname);
00762 if(newStr == NULL)
00763 return(-1);
00764 varp->name = newStr;
00765 free_NC_string(old);
00766 return NC_NOERR;
00767 }
00768
00769
00770 status = set_NC_string(varp->name, newname);
00771 if(status != NC_NOERR)
00772 return status;
00773
00774 set_NC_hdirty(ncp);
00775
00776 if(NC_doHsync(ncp))
00777 {
00778 status = NC_sync(ncp);
00779 if(status != NC_NOERR)
00780 return status;
00781 }
00782
00783 return NC_NOERR;
00784 }