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 #include "rnd.h"
00014
00015
00016
00017
00018
00019
00020
00021 void
00022 free_NC_attr(NC_attr *attrp)
00023 {
00024
00025 if(attrp == NULL)
00026 return;
00027 free_NC_string(attrp->name);
00028 free(attrp);
00029 }
00030
00031
00032
00033
00034
00035
00036 static size_t
00037 ncx_len_NC_attrV(nc_type type, size_t nelems)
00038 {
00039 switch(type) {
00040 case NC_BYTE:
00041 case NC_CHAR:
00042 return ncx_len_char(nelems);
00043 case NC_SHORT:
00044 return ncx_len_short(nelems);
00045 case NC_INT:
00046 return ncx_len_int(nelems);
00047 case NC_FLOAT:
00048 return ncx_len_float(nelems);
00049 case NC_DOUBLE:
00050 return ncx_len_double(nelems);
00051 }
00052
00053 assert("ncx_len_NC_attr bad type" == 0);
00054 return 0;
00055 }
00056
00057
00058 NC_attr *
00059 new_x_NC_attr(
00060 NC_string *strp,
00061 nc_type type,
00062 size_t nelems)
00063 {
00064 NC_attr *attrp;
00065 const size_t xsz = ncx_len_NC_attrV(type, nelems);
00066 size_t sz = M_RNDUP(sizeof(NC_attr));
00067
00068 assert(!(xsz == 0 && nelems != 0));
00069
00070 sz += xsz;
00071
00072 attrp = (NC_attr *) malloc(sz);
00073 if(attrp == NULL )
00074 return NULL;
00075
00076 attrp->xsz = xsz;
00077
00078 attrp->name = strp;
00079 attrp->type = type;
00080 attrp->nelems = nelems;
00081 if(xsz != 0)
00082 attrp->xvalue = (char *)attrp + M_RNDUP(sizeof(NC_attr));
00083 else
00084 attrp->xvalue = NULL;
00085
00086 return(attrp);
00087 }
00088
00089
00090
00091
00092
00093
00094 static NC_attr *
00095 new_NC_attr(
00096 const char *name,
00097 nc_type type,
00098 size_t nelems)
00099 {
00100 NC_string *strp;
00101 NC_attr *attrp;
00102
00103 assert(name != NULL && *name != 0);
00104
00105 strp = new_NC_string(strlen(name), name);
00106 if(strp == NULL)
00107 return NULL;
00108
00109 attrp = new_x_NC_attr(strp, type, nelems);
00110 if(attrp == NULL)
00111 {
00112 free_NC_string(strp);
00113 return NULL;
00114 }
00115
00116 return(attrp);
00117 }
00118
00119
00120 static NC_attr *
00121 dup_NC_attr(const NC_attr *rattrp)
00122 {
00123 NC_attr *attrp = new_NC_attr(rattrp->name->cp,
00124 rattrp->type, rattrp->nelems);
00125 if(attrp == NULL)
00126 return NULL;
00127 (void) memcpy(attrp->xvalue, rattrp->xvalue, rattrp->xsz);
00128 return attrp;
00129 }
00130
00131
00132
00133
00134
00135
00136
00137 void
00138 free_NC_attrarrayV0(NC_attrarray *ncap)
00139 {
00140 assert(ncap != NULL);
00141
00142 if(ncap->nelems == 0)
00143 return;
00144
00145 assert(ncap->value != NULL);
00146
00147 {
00148 NC_attr **app = ncap->value;
00149 NC_attr *const *const end = &app[ncap->nelems];
00150 for( ; app < end; app++)
00151 {
00152 free_NC_attr(*app);
00153 *app = NULL;
00154 }
00155 }
00156 ncap->nelems = 0;
00157 }
00158
00159
00160
00161
00162
00163
00164
00165 void
00166 free_NC_attrarrayV(NC_attrarray *ncap)
00167 {
00168 assert(ncap != NULL);
00169
00170 if(ncap->nalloc == 0)
00171 return;
00172
00173 assert(ncap->value != NULL);
00174
00175 free_NC_attrarrayV0(ncap);
00176
00177 free(ncap->value);
00178 ncap->value = NULL;
00179 ncap->nalloc = 0;
00180 }
00181
00182
00183 int
00184 dup_NC_attrarrayV(NC_attrarray *ncap, const NC_attrarray *ref)
00185 {
00186 int status = NC_NOERR;
00187
00188 assert(ref != NULL);
00189 assert(ncap != NULL);
00190
00191 if(ref->nelems != 0)
00192 {
00193 const size_t sz = ref->nelems * sizeof(NC_attr *);
00194 ncap->value = (NC_attr **) malloc(sz);
00195 if(ncap->value == NULL)
00196 return NC_ENOMEM;
00197
00198 (void) memset(ncap->value, 0, sz);
00199 ncap->nalloc = ref->nelems;
00200 }
00201
00202 ncap->nelems = 0;
00203 {
00204 NC_attr **app = ncap->value;
00205 const NC_attr **drpp = (const NC_attr **)ref->value;
00206 NC_attr *const *const end = &app[ref->nelems];
00207 for( ; app < end; drpp++, app++, ncap->nelems++)
00208 {
00209 *app = dup_NC_attr(*drpp);
00210 if(*app == NULL)
00211 {
00212 status = NC_ENOMEM;
00213 break;
00214 }
00215 }
00216 }
00217
00218 if(status != NC_NOERR)
00219 {
00220 free_NC_attrarrayV(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_attrarray(NC_attrarray *ncap, NC_attr *newelemp)
00237 {
00238 NC_attr **vp;
00239
00240 assert(ncap != NULL);
00241
00242 if(ncap->nalloc == 0)
00243 {
00244 assert(ncap->nelems == 0);
00245 vp = (NC_attr **) malloc(NC_ARRAY_GROWBY * sizeof(NC_attr *));
00246 if(vp == NULL)
00247 return NC_ENOMEM;
00248
00249 ncap->value = vp;
00250 ncap->nalloc = NC_ARRAY_GROWBY;
00251 }
00252 else if(ncap->nelems +1 > ncap->nalloc)
00253 {
00254 vp = (NC_attr **) realloc(ncap->value,
00255 (ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_attr *));
00256 if(vp == NULL)
00257 return NC_ENOMEM;
00258
00259 ncap->value = vp;
00260 ncap->nalloc += NC_ARRAY_GROWBY;
00261 }
00262
00263 if(newelemp != NULL)
00264 {
00265 ncap->value[ncap->nelems] = newelemp;
00266 ncap->nelems++;
00267 }
00268 return NC_NOERR;
00269 }
00270
00271
00272 NC_attr *
00273 elem_NC_attrarray(const NC_attrarray *ncap, size_t elem)
00274 {
00275 assert(ncap != NULL);
00276
00277 if(ncap->nelems == 0 || (unsigned long) elem >= ncap->nelems)
00278 return NULL;
00279
00280 assert(ncap->value != NULL);
00281
00282 return ncap->value[elem];
00283 }
00284
00285
00286
00287
00288
00289
00290
00291 static NC_attrarray *
00292 NC_attrarray0( NC *ncp, int varid)
00293 {
00294 NC_attrarray *ap;
00295
00296 if(varid == NC_GLOBAL)
00297 {
00298 ap = &ncp->attrs;
00299 }
00300 else if(varid >= 0 && (size_t) varid < ncp->vars.nelems)
00301 {
00302 NC_var **vpp;
00303 vpp = (NC_var **)ncp->vars.value;
00304 vpp += varid;
00305 ap = &(*vpp)->attrs;
00306 } else {
00307 ap = NULL;
00308 }
00309 return(ap);
00310 }
00311
00312
00313
00314
00315
00316
00317 NC_attr **
00318 NC_findattr(const NC_attrarray *ncap, const char *name)
00319 {
00320 NC_attr **attrpp;
00321 size_t attrid;
00322 size_t slen;
00323
00324 assert(ncap != NULL);
00325
00326 if(ncap->nelems == 0)
00327 return NULL;
00328
00329 attrpp = (NC_attr **) ncap->value;
00330
00331 slen = strlen(name);
00332
00333 for(attrid = 0; attrid < ncap->nelems; attrid++, attrpp++)
00334 {
00335 if(strlen((*attrpp)->name->cp) == slen &&
00336 strncmp((*attrpp)->name->cp, name, slen) == 0)
00337 {
00338 return(attrpp);
00339 }
00340 }
00341 return(NULL);
00342 }
00343
00344
00345
00346
00347
00348 static int
00349 NC_lookupattr(int ncid,
00350 int varid,
00351 const char *name,
00352 NC_attr **attrpp)
00353 {
00354 int status;
00355 NC *ncp;
00356 NC_attrarray *ncap;
00357 NC_attr **tmp;
00358
00359 status = NC_check_id(ncid, &ncp);
00360 if(status != NC_NOERR)
00361 return status;
00362
00363 ncap = NC_attrarray0(ncp, varid);
00364 if(ncap == NULL)
00365 return NC_ENOTVAR;
00366
00367 tmp = NC_findattr(ncap, name);
00368 if(tmp == NULL)
00369 return NC_ENOTATT;
00370
00371 if(attrpp != NULL)
00372 *attrpp = *tmp;
00373
00374 return ENOERR;
00375 }
00376
00377
00378
00379 int
00380 nc_inq_attname(int ncid, int varid, int attnum, char *name)
00381 {
00382 int status;
00383 NC *ncp;
00384 NC_attrarray *ncap;
00385 NC_attr *attrp;
00386
00387 status = NC_check_id(ncid, &ncp);
00388 if(status != NC_NOERR)
00389 return status;
00390
00391 ncap = NC_attrarray0(ncp, varid);
00392 if(ncap == NULL)
00393 return NC_ENOTVAR;
00394
00395 attrp = elem_NC_attrarray(ncap, (size_t)attnum);
00396 if(attrp == NULL)
00397 return NC_ENOTATT;
00398
00399 (void) strncpy(name, attrp->name->cp, attrp->name->nchars);
00400 name[attrp->name->nchars] = 0;
00401
00402 return NC_NOERR;
00403 }
00404
00405
00406 int
00407 nc_inq_attid(int ncid, int varid, const char *name, int *attnump)
00408 {
00409 int status;
00410 NC *ncp;
00411 NC_attrarray *ncap;
00412 NC_attr **attrpp;
00413
00414 status = NC_check_id(ncid, &ncp);
00415 if(status != NC_NOERR)
00416 return status;
00417
00418 ncap = NC_attrarray0(ncp, varid);
00419 if(ncap == NULL)
00420 return NC_ENOTVAR;
00421
00422
00423 attrpp = NC_findattr(ncap, name);
00424 if(attrpp == NULL)
00425 return NC_ENOTATT;
00426
00427 if(attnump != NULL)
00428 *attnump = (int)(attrpp - ncap->value);
00429
00430 return NC_NOERR;
00431 }
00432
00433 int
00434 nc_inq_atttype(int ncid, int varid, const char *name, nc_type *datatypep)
00435 {
00436 int status;
00437 NC_attr *attrp;
00438
00439 status = NC_lookupattr(ncid, varid, name, &attrp);
00440 if(status != NC_NOERR)
00441 return status;
00442
00443 if(datatypep != NULL)
00444 *datatypep = attrp->type;
00445
00446 return NC_NOERR;
00447 }
00448
00449 int
00450 nc_inq_attlen(int ncid, int varid, const char *name, size_t *lenp)
00451 {
00452 int status;
00453 NC_attr *attrp;
00454
00455 status = NC_lookupattr(ncid, varid, name, &attrp);
00456 if(status != NC_NOERR)
00457 return status;
00458
00459 if(lenp != NULL)
00460 *lenp = attrp->nelems;
00461
00462 return NC_NOERR;
00463 }
00464
00465 int
00466 nc_inq_att(int ncid,
00467 int varid,
00468 const char *name,
00469 nc_type *datatypep,
00470 size_t *lenp)
00471 {
00472 int status;
00473 NC_attr *attrp;
00474
00475 status = NC_lookupattr(ncid, varid, name, &attrp);
00476 if(status != NC_NOERR)
00477 return status;
00478
00479 if(datatypep != NULL)
00480 *datatypep = attrp->type;
00481 if(lenp != NULL)
00482 *lenp = attrp->nelems;
00483
00484 return NC_NOERR;
00485 }
00486
00487
00488 int
00489 nc_rename_att( int ncid, int varid, const char *name, const char *newname)
00490 {
00491 int status;
00492 NC *ncp;
00493 NC_attrarray *ncap;
00494 NC_attr **tmp;
00495 NC_attr *attrp;
00496 NC_string *newStr, *old;
00497
00498
00499 status = NC_check_id(ncid, &ncp);
00500 if(status != NC_NOERR)
00501 return status;
00502
00503 if(NC_readonly(ncp))
00504 return NC_EPERM;
00505
00506 ncap = NC_attrarray0(ncp, varid);
00507 if(ncap == NULL)
00508 return NC_ENOTVAR;
00509
00510 status = NC_check_name(name);
00511 if(status != NC_NOERR)
00512 return status;
00513
00514 tmp = NC_findattr(ncap, name);
00515 if(tmp == NULL)
00516 return NC_ENOTATT;
00517 attrp = *tmp;
00518
00519
00520 if(NC_findattr(ncap, newname) != NULL)
00521 {
00522
00523 return NC_ENAMEINUSE;
00524 }
00525
00526 old = attrp->name;
00527 if(NC_indef(ncp))
00528 {
00529 newStr = new_NC_string(strlen(newname), newname);
00530 if( newStr == NULL)
00531 return NC_ENOMEM;
00532 attrp->name = newStr;
00533 free_NC_string(old);
00534 return NC_NOERR;
00535 }
00536
00537 status = set_NC_string(old, newname);
00538 if( status != NC_NOERR)
00539 return status;
00540
00541 set_NC_hdirty(ncp);
00542
00543 if(NC_doHsync(ncp))
00544 {
00545 status = NC_sync(ncp);
00546 if(status != NC_NOERR)
00547 return status;
00548 }
00549
00550 return NC_NOERR;
00551 }
00552
00553
00554 int
00555 nc_copy_att(int ncid_in, int varid_in, const char *name, int ncid_out, int ovarid)
00556 {
00557 int status;
00558 NC_attr *iattrp;
00559 NC *ncp;
00560 NC_attrarray *ncap;
00561 NC_attr **attrpp;
00562 NC_attr *old = NULL;
00563 NC_attr *attrp;
00564
00565 status = NC_lookupattr(ncid_in, varid_in, name, &iattrp);
00566 if(status != NC_NOERR)
00567 return status;
00568
00569 status = NC_check_id(ncid_out, &ncp);
00570 if(status != NC_NOERR)
00571 return status;
00572
00573 if(NC_readonly(ncp))
00574 return NC_EPERM;
00575
00576 ncap = NC_attrarray0(ncp, ovarid);
00577 if(ncap == NULL)
00578 return NC_ENOTVAR;
00579
00580 attrpp = NC_findattr(ncap, name);
00581 if(attrpp != NULL)
00582 {
00583 if(!NC_indef(ncp) )
00584 {
00585 attrp = *attrpp;
00586
00587 if(iattrp->xsz > attrp->xsz)
00588 return NC_ENOTINDEFINE;
00589
00590
00591 attrp->xsz = iattrp->xsz;
00592 attrp->type = iattrp->type;
00593 attrp->nelems = iattrp->nelems;
00594
00595 (void) memcpy(attrp->xvalue, iattrp->xvalue,
00596 iattrp->xsz);
00597
00598 set_NC_hdirty(ncp);
00599
00600 if(NC_doHsync(ncp))
00601 {
00602 status = NC_sync(ncp);
00603 if(status != NC_NOERR)
00604 return status;
00605 }
00606
00607 return NC_NOERR;
00608 }
00609
00610 old = *attrpp;
00611 }
00612 else
00613 {
00614 if(!NC_indef(ncp))
00615 return NC_ENOTINDEFINE;
00616
00617 if(ncap->nelems >= NC_MAX_ATTRS)
00618 return NC_EMAXATTS;
00619 }
00620
00621 attrp = new_NC_attr(name, iattrp->type, iattrp->nelems);
00622 if(attrp == NULL)
00623 return NC_ENOMEM;
00624
00625 (void) memcpy(attrp->xvalue, iattrp->xvalue,
00626 iattrp->xsz);
00627
00628 if(attrpp != NULL)
00629 {
00630 assert(old != NULL);
00631 *attrpp = attrp;
00632 free_NC_attr(old);
00633 }
00634 else
00635 {
00636 status = incr_NC_attrarray(ncap, attrp);
00637 if(status != NC_NOERR)
00638 {
00639 free_NC_attr(attrp);
00640 return status;
00641 }
00642 }
00643
00644 return NC_NOERR;
00645 }
00646
00647
00648 int
00649 nc_del_att(int ncid, int varid, const char *name)
00650 {
00651 int status;
00652 NC *ncp;
00653 NC_attrarray *ncap;
00654 NC_attr **attrpp;
00655 NC_attr *old = NULL;
00656 int attrid;
00657 size_t slen;
00658
00659 status = NC_check_id(ncid, &ncp);
00660 if(status != NC_NOERR)
00661 return status;
00662
00663 if(!NC_indef(ncp))
00664 return NC_ENOTINDEFINE;
00665
00666 ncap = NC_attrarray0(ncp, varid);
00667 if(ncap == NULL)
00668 return NC_ENOTVAR;
00669
00670
00671 slen = strlen(name);
00672
00673 attrpp = (NC_attr **) ncap->value;
00674 for(attrid = 0; (size_t) attrid < ncap->nelems; attrid++, attrpp++)
00675 {
00676 if( slen == (*attrpp)->name->nchars &&
00677 strncmp(name, (*attrpp)->name->cp, slen) == 0)
00678 {
00679 old = *attrpp;
00680 break;
00681 }
00682 }
00683 if( (size_t) attrid == ncap->nelems )
00684 return NC_ENOTATT;
00685
00686
00687
00688 for(attrid++; (size_t) attrid < ncap->nelems; attrid++)
00689 {
00690 *attrpp = *(attrpp + 1);
00691 attrpp++;
00692 }
00693 *attrpp = NULL;
00694
00695 ncap->nelems--;
00696
00697 free_NC_attr(old);
00698
00699 return NC_NOERR;
00700 }
00701
00702
00703 static int
00704 ncx_pad_putn_Iuchar(void **xpp, size_t nelems, const uchar *tp, nc_type type)
00705 {
00706 switch(type) {
00707 case NC_CHAR:
00708 return NC_ECHAR;
00709 case NC_BYTE:
00710 return ncx_pad_putn_schar_uchar(xpp, nelems, tp);
00711 case NC_SHORT:
00712 return ncx_pad_putn_short_uchar(xpp, nelems, tp);
00713 case NC_INT:
00714 return ncx_putn_int_uchar(xpp, nelems, tp);
00715 case NC_FLOAT:
00716 return ncx_putn_float_uchar(xpp, nelems, tp);
00717 case NC_DOUBLE:
00718 return ncx_putn_double_uchar(xpp, nelems, tp);
00719 }
00720 assert("ncx_pad_putn_Iuchar invalid type" == 0);
00721 return NC_EBADTYPE;
00722 }
00723
00724 static int
00725 ncx_pad_getn_Iuchar(const void **xpp, size_t nelems, uchar *tp, nc_type type)
00726 {
00727 switch(type) {
00728 case NC_CHAR:
00729 return NC_ECHAR;
00730 case NC_BYTE:
00731 return ncx_pad_getn_schar_uchar(xpp, nelems, tp);
00732 case NC_SHORT:
00733 return ncx_pad_getn_short_uchar(xpp, nelems, tp);
00734 case NC_INT:
00735 return ncx_getn_int_uchar(xpp, nelems, tp);
00736 case NC_FLOAT:
00737 return ncx_getn_float_uchar(xpp, nelems, tp);
00738 case NC_DOUBLE:
00739 return ncx_getn_double_uchar(xpp, nelems, tp);
00740 }
00741 assert("ncx_pad_getn_Iuchar invalid type" == 0);
00742 return NC_EBADTYPE;
00743 }
00744
00745
00746 static int
00747 ncx_pad_putn_Ischar(void **xpp, size_t nelems, const schar *tp, nc_type type)
00748 {
00749 switch(type) {
00750 case NC_CHAR:
00751 return NC_ECHAR;
00752 case NC_BYTE:
00753 return ncx_pad_putn_schar_schar(xpp, nelems, tp);
00754 case NC_SHORT:
00755 return ncx_pad_putn_short_schar(xpp, nelems, tp);
00756 case NC_INT:
00757 return ncx_putn_int_schar(xpp, nelems, tp);
00758 case NC_FLOAT:
00759 return ncx_putn_float_schar(xpp, nelems, tp);
00760 case NC_DOUBLE:
00761 return ncx_putn_double_schar(xpp, nelems, tp);
00762 }
00763 assert("ncx_pad_putn_Ischar invalid type" == 0);
00764 return NC_EBADTYPE;
00765 }
00766
00767 static int
00768 ncx_pad_getn_Ischar(const void **xpp, size_t nelems, schar *tp, nc_type type)
00769 {
00770 switch(type) {
00771 case NC_CHAR:
00772 return NC_ECHAR;
00773 case NC_BYTE:
00774 return ncx_pad_getn_schar_schar(xpp, nelems, tp);
00775 case NC_SHORT:
00776 return ncx_pad_getn_short_schar(xpp, nelems, tp);
00777 case NC_INT:
00778 return ncx_getn_int_schar(xpp, nelems, tp);
00779 case NC_FLOAT:
00780 return ncx_getn_float_schar(xpp, nelems, tp);
00781 case NC_DOUBLE:
00782 return ncx_getn_double_schar(xpp, nelems, tp);
00783 }
00784 assert("ncx_pad_getn_Ischar invalid type" == 0);
00785 return NC_EBADTYPE;
00786 }
00787
00788
00789 static int
00790 ncx_pad_putn_Ishort(void **xpp, size_t nelems, const short *tp, nc_type type)
00791 {
00792 switch(type) {
00793 case NC_CHAR:
00794 return NC_ECHAR;
00795 case NC_BYTE:
00796 return ncx_pad_putn_schar_short(xpp, nelems, tp);
00797 case NC_SHORT:
00798 return ncx_pad_putn_short_short(xpp, nelems, tp);
00799 case NC_INT:
00800 return ncx_putn_int_short(xpp, nelems, tp);
00801 case NC_FLOAT:
00802 return ncx_putn_float_short(xpp, nelems, tp);
00803 case NC_DOUBLE:
00804 return ncx_putn_double_short(xpp, nelems, tp);
00805 }
00806 assert("ncx_pad_putn_Ishort invalid type" == 0);
00807 return NC_EBADTYPE;
00808 }
00809
00810 static int
00811 ncx_pad_getn_Ishort(const void **xpp, size_t nelems, short *tp, nc_type type)
00812 {
00813 switch(type) {
00814 case NC_CHAR:
00815 return NC_ECHAR;
00816 case NC_BYTE:
00817 return ncx_pad_getn_schar_short(xpp, nelems, tp);
00818 case NC_SHORT:
00819 return ncx_pad_getn_short_short(xpp, nelems, tp);
00820 case NC_INT:
00821 return ncx_getn_int_short(xpp, nelems, tp);
00822 case NC_FLOAT:
00823 return ncx_getn_float_short(xpp, nelems, tp);
00824 case NC_DOUBLE:
00825 return ncx_getn_double_short(xpp, nelems, tp);
00826 }
00827 assert("ncx_pad_getn_Ishort invalid type" == 0);
00828 return NC_EBADTYPE;
00829 }
00830
00831
00832 static int
00833 ncx_pad_putn_Iint(void **xpp, size_t nelems, const int *tp, nc_type type)
00834 {
00835 switch(type) {
00836 case NC_CHAR:
00837 return NC_ECHAR;
00838 case NC_BYTE:
00839 return ncx_pad_putn_schar_int(xpp, nelems, tp);
00840 case NC_SHORT:
00841 return ncx_pad_putn_short_int(xpp, nelems, tp);
00842 case NC_INT:
00843 return ncx_putn_int_int(xpp, nelems, tp);
00844 case NC_FLOAT:
00845 return ncx_putn_float_int(xpp, nelems, tp);
00846 case NC_DOUBLE:
00847 return ncx_putn_double_int(xpp, nelems, tp);
00848 }
00849 assert("ncx_pad_putn_Iint invalid type" == 0);
00850 return NC_EBADTYPE;
00851 }
00852
00853 static int
00854 ncx_pad_getn_Iint(const void **xpp, size_t nelems, int *tp, nc_type type)
00855 {
00856 switch(type) {
00857 case NC_CHAR:
00858 return NC_ECHAR;
00859 case NC_BYTE:
00860 return ncx_pad_getn_schar_int(xpp, nelems, tp);
00861 case NC_SHORT:
00862 return ncx_pad_getn_short_int(xpp, nelems, tp);
00863 case NC_INT:
00864 return ncx_getn_int_int(xpp, nelems, tp);
00865 case NC_FLOAT:
00866 return ncx_getn_float_int(xpp, nelems, tp);
00867 case NC_DOUBLE:
00868 return ncx_getn_double_int(xpp, nelems, tp);
00869 }
00870 assert("ncx_pad_getn_Iint invalid type" == 0);
00871 return NC_EBADTYPE;
00872 }
00873
00874
00875 static int
00876 ncx_pad_putn_Ilong(void **xpp, size_t nelems, const long *tp, nc_type type)
00877 {
00878 switch(type) {
00879 case NC_CHAR:
00880 return NC_ECHAR;
00881 case NC_BYTE:
00882 return ncx_pad_putn_schar_long(xpp, nelems, tp);
00883 case NC_SHORT:
00884 return ncx_pad_putn_short_long(xpp, nelems, tp);
00885 case NC_INT:
00886 return ncx_putn_int_long(xpp, nelems, tp);
00887 case NC_FLOAT:
00888 return ncx_putn_float_long(xpp, nelems, tp);
00889 case NC_DOUBLE:
00890 return ncx_putn_double_long(xpp, nelems, tp);
00891 }
00892 assert("ncx_pad_putn_Ilong invalid type" == 0);
00893 return NC_EBADTYPE;
00894 }
00895
00896 static int
00897 ncx_pad_getn_Ilong(const void **xpp, size_t nelems, long *tp, nc_type type)
00898 {
00899 switch(type) {
00900 case NC_CHAR:
00901 return NC_ECHAR;
00902 case NC_BYTE:
00903 return ncx_pad_getn_schar_long(xpp, nelems, tp);
00904 case NC_SHORT:
00905 return ncx_pad_getn_short_long(xpp, nelems, tp);
00906 case NC_INT:
00907 return ncx_getn_int_long(xpp, nelems, tp);
00908 case NC_FLOAT:
00909 return ncx_getn_float_long(xpp, nelems, tp);
00910 case NC_DOUBLE:
00911 return ncx_getn_double_long(xpp, nelems, tp);
00912 }
00913 assert("ncx_pad_getn_Ilong invalid type" == 0);
00914 return NC_EBADTYPE;
00915 }
00916
00917
00918 static int
00919 ncx_pad_putn_Ifloat(void **xpp, size_t nelems, const float *tp, nc_type type)
00920 {
00921 switch(type) {
00922 case NC_CHAR:
00923 return NC_ECHAR;
00924 case NC_BYTE:
00925 return ncx_pad_putn_schar_float(xpp, nelems, tp);
00926 case NC_SHORT:
00927 return ncx_pad_putn_short_float(xpp, nelems, tp);
00928 case NC_INT:
00929 return ncx_putn_int_float(xpp, nelems, tp);
00930 case NC_FLOAT:
00931 return ncx_putn_float_float(xpp, nelems, tp);
00932 case NC_DOUBLE:
00933 return ncx_putn_double_float(xpp, nelems, tp);
00934 }
00935 assert("ncx_pad_putn_Ifloat invalid type" == 0);
00936 return NC_EBADTYPE;
00937 }
00938
00939 static int
00940 ncx_pad_getn_Ifloat(const void **xpp, size_t nelems, float *tp, nc_type type)
00941 {
00942 switch(type) {
00943 case NC_CHAR:
00944 return NC_ECHAR;
00945 case NC_BYTE:
00946 return ncx_pad_getn_schar_float(xpp, nelems, tp);
00947 case NC_SHORT:
00948 return ncx_pad_getn_short_float(xpp, nelems, tp);
00949 case NC_INT:
00950 return ncx_getn_int_float(xpp, nelems, tp);
00951 case NC_FLOAT:
00952 return ncx_getn_float_float(xpp, nelems, tp);
00953 case NC_DOUBLE:
00954 return ncx_getn_double_float(xpp, nelems, tp);
00955 }
00956 assert("ncx_pad_getn_Ifloat invalid type" == 0);
00957 return NC_EBADTYPE;
00958 }
00959
00960
00961 static int
00962 ncx_pad_putn_Idouble(void **xpp, size_t nelems, const double *tp, nc_type type)
00963 {
00964 switch(type) {
00965 case NC_CHAR:
00966 return NC_ECHAR;
00967 case NC_BYTE:
00968 return ncx_pad_putn_schar_double(xpp, nelems, tp);
00969 case NC_SHORT:
00970 return ncx_pad_putn_short_double(xpp, nelems, tp);
00971 case NC_INT:
00972 return ncx_putn_int_double(xpp, nelems, tp);
00973 case NC_FLOAT:
00974 return ncx_putn_float_double(xpp, nelems, tp);
00975 case NC_DOUBLE:
00976 return ncx_putn_double_double(xpp, nelems, tp);
00977 }
00978 assert("ncx_pad_putn_Idouble invalid type" == 0);
00979 return NC_EBADTYPE;
00980 }
00981
00982 static int
00983 ncx_pad_getn_Idouble(const void **xpp, size_t nelems, double *tp, nc_type type)
00984 {
00985 switch(type) {
00986 case NC_CHAR:
00987 return NC_ECHAR;
00988 case NC_BYTE:
00989 return ncx_pad_getn_schar_double(xpp, nelems, tp);
00990 case NC_SHORT:
00991 return ncx_pad_getn_short_double(xpp, nelems, tp);
00992 case NC_INT:
00993 return ncx_getn_int_double(xpp, nelems, tp);
00994 case NC_FLOAT:
00995 return ncx_getn_float_double(xpp, nelems, tp);
00996 case NC_DOUBLE:
00997 return ncx_getn_double_double(xpp, nelems, tp);
00998 }
00999 assert("ncx_pad_getn_Idouble invalid type" == 0);
01000 return NC_EBADTYPE;
01001 }
01002
01003
01004
01005 int
01006 nc_put_att_text(int ncid, int varid, const char *name,
01007 size_t nelems, const char *value)
01008 {
01009 int status;
01010 NC *ncp;
01011 NC_attrarray *ncap;
01012 NC_attr **attrpp;
01013 NC_attr *old = NULL;
01014 NC_attr *attrp;
01015
01016 status = NC_check_id(ncid, &ncp);
01017 if(status != NC_NOERR)
01018 return status;
01019
01020 if(NC_readonly(ncp))
01021 return NC_EPERM;
01022
01023 ncap = NC_attrarray0(ncp, varid);
01024 if(ncap == NULL)
01025 return NC_ENOTVAR;
01026
01027 status = NC_check_name(name);
01028 if(status != NC_NOERR)
01029 return status;
01030
01031
01032 if((unsigned long) nelems > X_INT_MAX)
01033 return NC_EINVAL;
01034
01035 if(nelems != 0 && value == NULL)
01036 return NC_EINVAL;
01037
01038 attrpp = NC_findattr(ncap, name);
01039 if(attrpp != NULL)
01040 {
01041 if(!NC_indef(ncp) )
01042 {
01043 const size_t xsz = ncx_len_NC_attrV(NC_CHAR, nelems);
01044 attrp = *attrpp;
01045
01046 if(xsz > attrp->xsz)
01047 return NC_ENOTINDEFINE;
01048
01049
01050 attrp->xsz = xsz;
01051 attrp->type = NC_CHAR;
01052 attrp->nelems = nelems;
01053
01054 if(nelems != 0)
01055 {
01056 void *xp = attrp->xvalue;
01057 status = ncx_pad_putn_text(&xp, nelems, value);
01058 if(status != NC_NOERR)
01059 return status;
01060 }
01061
01062 set_NC_hdirty(ncp);
01063
01064 if(NC_doHsync(ncp))
01065 {
01066 status = NC_sync(ncp);
01067 if(status != NC_NOERR)
01068 return status;
01069 }
01070
01071 return NC_NOERR;
01072 }
01073
01074 old = *attrpp;
01075 }
01076 else
01077 {
01078 if(!NC_indef(ncp))
01079 return NC_ENOTINDEFINE;
01080
01081 if(ncap->nelems >= NC_MAX_ATTRS)
01082 return NC_EMAXATTS;
01083 }
01084
01085 attrp = new_NC_attr(name, NC_CHAR, nelems);
01086 if(attrp == NULL)
01087 return NC_ENOMEM;
01088
01089 if(nelems != 0)
01090 {
01091 void *xp = attrp->xvalue;
01092 status = ncx_pad_putn_text(&xp, nelems, value);
01093 if(status != NC_NOERR)
01094 return status;
01095 }
01096
01097 if(attrpp != NULL)
01098 {
01099 assert(old != NULL);
01100 *attrpp = attrp;
01101 free_NC_attr(old);
01102 }
01103 else
01104 {
01105 status = incr_NC_attrarray(ncap, attrp);
01106 if(status != NC_NOERR)
01107 {
01108 free_NC_attr(attrp);
01109 return status;
01110 }
01111 }
01112
01113 return NC_NOERR;
01114 }
01115
01116
01117 int
01118 nc_get_att_text(int ncid, int varid, const char *name, char *str)
01119 {
01120 int status;
01121 NC_attr *attrp;
01122
01123 status = NC_lookupattr(ncid, varid, name, &attrp);
01124 if(status != NC_NOERR)
01125 return status;
01126
01127 if(attrp->nelems == 0)
01128 return NC_NOERR;
01129
01130 if(attrp->type != NC_CHAR)
01131 return NC_ECHAR;
01132
01133
01134 {
01135 const void *xp = attrp->xvalue;
01136 return ncx_pad_getn_text(&xp, attrp->nelems, str);
01137 }
01138 }
01139
01140
01141
01142
01143 int
01144 nc_put_att_schar(int ncid, int varid, const char *name,
01145 nc_type type, size_t nelems, const signed char *value)
01146 {
01147 int status;
01148 NC *ncp;
01149 NC_attrarray *ncap;
01150 NC_attr **attrpp;
01151 NC_attr *old = NULL;
01152 NC_attr *attrp;
01153
01154 status = NC_check_id(ncid, &ncp);
01155 if(status != NC_NOERR)
01156 return status;
01157
01158 if(NC_readonly(ncp))
01159 return NC_EPERM;
01160
01161 ncap = NC_attrarray0(ncp, varid);
01162 if(ncap == NULL)
01163 return NC_ENOTVAR;
01164
01165 status = nc_cktype(type);
01166 if(status != NC_NOERR)
01167 return status;
01168
01169 if(type == NC_CHAR)
01170 return NC_ECHAR;
01171
01172
01173 if((unsigned long) nelems > X_INT_MAX)
01174 return NC_EINVAL;
01175
01176 if(nelems != 0 && value == NULL)
01177 return NC_EINVAL;
01178
01179 attrpp = NC_findattr(ncap, name);
01180 if(attrpp != NULL)
01181 {
01182 if(!NC_indef(ncp) )
01183 {
01184 const size_t xsz = ncx_len_NC_attrV(type, nelems);
01185 attrp = *attrpp;
01186
01187 if(xsz > attrp->xsz)
01188 return NC_ENOTINDEFINE;
01189
01190
01191 attrp->xsz = xsz;
01192 attrp->type = type;
01193 attrp->nelems = nelems;
01194
01195 if(nelems != 0)
01196 {
01197 void *xp = attrp->xvalue;
01198 status = ncx_pad_putn_Ischar(&xp, nelems,
01199 value, type);
01200 }
01201
01202 set_NC_hdirty(ncp);
01203
01204 if(NC_doHsync(ncp))
01205 {
01206 const int lstatus = NC_sync(ncp);
01207
01208
01209
01210
01211 if(lstatus != ENOERR)
01212 return lstatus;
01213 }
01214
01215 return status;
01216 }
01217
01218 old = *attrpp;
01219 }
01220 else
01221 {
01222 if(!NC_indef(ncp))
01223 return NC_ENOTINDEFINE;
01224
01225 if(ncap->nelems >= NC_MAX_ATTRS)
01226 return NC_EMAXATTS;
01227 }
01228
01229 status = NC_check_name(name);
01230 if(status != NC_NOERR)
01231 return status;
01232
01233 attrp = new_NC_attr(name, type, nelems);
01234 if(attrp == NULL)
01235 return NC_ENOMEM;
01236
01237 if(nelems != 0)
01238 {
01239 void *xp = attrp->xvalue;
01240 status = ncx_pad_putn_Ischar(&xp, nelems,
01241 value, type);
01242 }
01243
01244 if(attrpp != NULL)
01245 {
01246 assert(old != NULL);
01247 *attrpp = attrp;
01248 free_NC_attr(old);
01249 }
01250 else
01251 {
01252 const int lstatus = incr_NC_attrarray(ncap, attrp);
01253
01254
01255
01256
01257 if(lstatus != NC_NOERR)
01258 {
01259 free_NC_attr(attrp);
01260 return lstatus;
01261 }
01262 }
01263
01264 return status;
01265 }
01266
01267 int
01268 nc_get_att_schar(int ncid, int varid, const char *name, signed char *tp)
01269 {
01270 int status;
01271 NC_attr *attrp;
01272
01273 status = NC_lookupattr(ncid, varid, name, &attrp);
01274 if(status != NC_NOERR)
01275 return status;
01276
01277 if(attrp->nelems == 0)
01278 return NC_NOERR;
01279
01280 if(attrp->type == NC_CHAR)
01281 return NC_ECHAR;
01282
01283 {
01284 const void *xp = attrp->xvalue;
01285 return ncx_pad_getn_Ischar(&xp, attrp->nelems, tp, attrp->type);
01286 }
01287 }
01288
01289
01290 int
01291 nc_put_att_uchar(int ncid, int varid, const char *name,
01292 nc_type type, size_t nelems, const unsigned char *value)
01293 {
01294 int status;
01295 NC *ncp;
01296 NC_attrarray *ncap;
01297 NC_attr **attrpp;
01298 NC_attr *old = NULL;
01299 NC_attr *attrp;
01300
01301 status = NC_check_id(ncid, &ncp);
01302 if(status != NC_NOERR)
01303 return status;
01304
01305 if(NC_readonly(ncp))
01306 return NC_EPERM;
01307
01308 ncap = NC_attrarray0(ncp, varid);
01309 if(ncap == NULL)
01310 return NC_ENOTVAR;
01311
01312 status = nc_cktype(type);
01313 if(status != NC_NOERR)
01314 return status;
01315
01316 if(type == NC_CHAR)
01317 return NC_ECHAR;
01318
01319
01320 if((unsigned long) nelems > X_INT_MAX)
01321 return NC_EINVAL;
01322
01323 if(nelems != 0 && value == NULL)
01324 return NC_EINVAL;
01325
01326 attrpp = NC_findattr(ncap, name);
01327 if(attrpp != NULL)
01328 {
01329 if(!NC_indef(ncp) )
01330 {
01331 const size_t xsz = ncx_len_NC_attrV(type, nelems);
01332 attrp = *attrpp;
01333
01334 if(xsz > attrp->xsz)
01335 return NC_ENOTINDEFINE;
01336
01337
01338 attrp->xsz = xsz;
01339 attrp->type = type;
01340 attrp->nelems = nelems;
01341
01342 if(nelems != 0)
01343 {
01344 void *xp = attrp->xvalue;
01345 status = ncx_pad_putn_Iuchar(&xp, nelems,
01346 value, type);
01347 }
01348
01349 set_NC_hdirty(ncp);
01350
01351 if(NC_doHsync(ncp))
01352 {
01353 const int lstatus = NC_sync(ncp);
01354
01355
01356
01357
01358 if(lstatus != ENOERR)
01359 return lstatus;
01360 }
01361
01362 return status;
01363 }
01364
01365 old = *attrpp;
01366 }
01367 else
01368 {
01369 if(!NC_indef(ncp))
01370 return NC_ENOTINDEFINE;
01371
01372 if(ncap->nelems >= NC_MAX_ATTRS)
01373 return NC_EMAXATTS;
01374 }
01375
01376 status = NC_check_name(name);
01377 if(status != NC_NOERR)
01378 return status;
01379
01380 attrp = new_NC_attr(name, type, nelems);
01381 if(attrp == NULL)
01382 return NC_ENOMEM;
01383
01384 if(nelems != 0)
01385 {
01386 void *xp = attrp->xvalue;
01387 status = ncx_pad_putn_Iuchar(&xp, nelems,
01388 value, type);
01389 }
01390
01391 if(attrpp != NULL)
01392 {
01393 assert(old != NULL);
01394 *attrpp = attrp;
01395 free_NC_attr(old);
01396 }
01397 else
01398 {
01399 const int lstatus = incr_NC_attrarray(ncap, attrp);
01400
01401
01402
01403
01404 if(lstatus != NC_NOERR)
01405 {
01406 free_NC_attr(attrp);
01407 return lstatus;
01408 }
01409 }
01410
01411 return status;
01412 }
01413
01414 int
01415 nc_get_att_uchar(int ncid, int varid, const char *name, unsigned char *tp)
01416 {
01417 int status;
01418 NC_attr *attrp;
01419
01420 status = NC_lookupattr(ncid, varid, name, &attrp);
01421 if(status != NC_NOERR)
01422 return status;
01423
01424 if(attrp->nelems == 0)
01425 return NC_NOERR;
01426
01427 if(attrp->type == NC_CHAR)
01428 return NC_ECHAR;
01429
01430 {
01431 const void *xp = attrp->xvalue;
01432 return ncx_pad_getn_Iuchar(&xp, attrp->nelems, tp, attrp->type);
01433 }
01434 }
01435
01436
01437 int
01438 nc_put_att_short(int ncid, int varid, const char *name,
01439 nc_type type, size_t nelems, const short *value)
01440 {
01441 int status;
01442 NC *ncp;
01443 NC_attrarray *ncap;
01444 NC_attr **attrpp;
01445 NC_attr *old = NULL;
01446 NC_attr *attrp;
01447
01448 status = NC_check_id(ncid, &ncp);
01449 if(status != NC_NOERR)
01450 return status;
01451
01452 if(NC_readonly(ncp))
01453 return NC_EPERM;
01454
01455 ncap = NC_attrarray0(ncp, varid);
01456 if(ncap == NULL)
01457 return NC_ENOTVAR;
01458
01459 status = nc_cktype(type);
01460 if(status != NC_NOERR)
01461 return status;
01462
01463 if(type == NC_CHAR)
01464 return NC_ECHAR;
01465
01466
01467 if((unsigned long) nelems > X_INT_MAX)
01468 return NC_EINVAL;
01469
01470 if(nelems != 0 && value == NULL)
01471 return NC_EINVAL;
01472
01473 attrpp = NC_findattr(ncap, name);
01474 if(attrpp != NULL)
01475 {
01476 if(!NC_indef(ncp) )
01477 {
01478 const size_t xsz = ncx_len_NC_attrV(type, nelems);
01479 attrp = *attrpp;
01480
01481 if(xsz > attrp->xsz)
01482 return NC_ENOTINDEFINE;
01483
01484
01485 attrp->xsz = xsz;
01486 attrp->type = type;
01487 attrp->nelems = nelems;
01488
01489 if(nelems != 0)
01490 {
01491 void *xp = attrp->xvalue;
01492 status = ncx_pad_putn_Ishort(&xp, nelems,
01493 value, type);
01494 }
01495
01496 set_NC_hdirty(ncp);
01497
01498 if(NC_doHsync(ncp))
01499 {
01500 const int lstatus = NC_sync(ncp);
01501
01502
01503
01504
01505 if(lstatus != ENOERR)
01506 return lstatus;
01507 }
01508
01509 return status;
01510 }
01511
01512 old = *attrpp;
01513 }
01514 else
01515 {
01516 if(!NC_indef(ncp))
01517 return NC_ENOTINDEFINE;
01518
01519 if(ncap->nelems >= NC_MAX_ATTRS)
01520 return NC_EMAXATTS;
01521 }
01522
01523 status = NC_check_name(name);
01524 if(status != NC_NOERR)
01525 return status;
01526
01527 attrp = new_NC_attr(name, type, nelems);
01528 if(attrp == NULL)
01529 return NC_ENOMEM;
01530
01531 if(nelems != 0)
01532 {
01533 void *xp = attrp->xvalue;
01534 status = ncx_pad_putn_Ishort(&xp, nelems,
01535 value, type);
01536 }
01537
01538 if(attrpp != NULL)
01539 {
01540 assert(old != NULL);
01541 *attrpp = attrp;
01542 free_NC_attr(old);
01543 }
01544 else
01545 {
01546 const int lstatus = incr_NC_attrarray(ncap, attrp);
01547
01548
01549
01550
01551 if(lstatus != NC_NOERR)
01552 {
01553 free_NC_attr(attrp);
01554 return lstatus;
01555 }
01556 }
01557
01558 return status;
01559 }
01560
01561 int
01562 nc_get_att_short(int ncid, int varid, const char *name, short *tp)
01563 {
01564 int status;
01565 NC_attr *attrp;
01566
01567 status = NC_lookupattr(ncid, varid, name, &attrp);
01568 if(status != NC_NOERR)
01569 return status;
01570
01571 if(attrp->nelems == 0)
01572 return NC_NOERR;
01573
01574 if(attrp->type == NC_CHAR)
01575 return NC_ECHAR;
01576
01577 {
01578 const void *xp = attrp->xvalue;
01579 return ncx_pad_getn_Ishort(&xp, attrp->nelems, tp, attrp->type);
01580 }
01581 }
01582
01583
01584 int
01585 nc_put_att_int(int ncid, int varid, const char *name,
01586 nc_type type, size_t nelems, const int *value)
01587 {
01588 int status;
01589 NC *ncp;
01590 NC_attrarray *ncap;
01591 NC_attr **attrpp;
01592 NC_attr *old = NULL;
01593 NC_attr *attrp;
01594
01595 status = NC_check_id(ncid, &ncp);
01596 if(status != NC_NOERR)
01597 return status;
01598
01599 if(NC_readonly(ncp))
01600 return NC_EPERM;
01601
01602 ncap = NC_attrarray0(ncp, varid);
01603 if(ncap == NULL)
01604 return NC_ENOTVAR;
01605
01606 status = nc_cktype(type);
01607 if(status != NC_NOERR)
01608 return status;
01609
01610 if(type == NC_CHAR)
01611 return NC_ECHAR;
01612
01613
01614 if((unsigned long) nelems > X_INT_MAX)
01615 return NC_EINVAL;
01616
01617 if(nelems != 0 && value == NULL)
01618 return NC_EINVAL;
01619
01620 attrpp = NC_findattr(ncap, name);
01621 if(attrpp != NULL)
01622 {
01623 if(!NC_indef(ncp) )
01624 {
01625 const size_t xsz = ncx_len_NC_attrV(type, nelems);
01626 attrp = *attrpp;
01627
01628 if(xsz > attrp->xsz)
01629 return NC_ENOTINDEFINE;
01630
01631
01632 attrp->xsz = xsz;
01633 attrp->type = type;
01634 attrp->nelems = nelems;
01635
01636 if(nelems != 0)
01637 {
01638 void *xp = attrp->xvalue;
01639 status = ncx_pad_putn_Iint(&xp, nelems,
01640 value, type);
01641 }
01642
01643 set_NC_hdirty(ncp);
01644
01645 if(NC_doHsync(ncp))
01646 {
01647 const int lstatus = NC_sync(ncp);
01648
01649
01650
01651
01652 if(lstatus != ENOERR)
01653 return lstatus;
01654 }
01655
01656 return status;
01657 }
01658
01659 old = *attrpp;
01660 }
01661 else
01662 {
01663 if(!NC_indef(ncp))
01664 return NC_ENOTINDEFINE;
01665
01666 if(ncap->nelems >= NC_MAX_ATTRS)
01667 return NC_EMAXATTS;
01668 }
01669
01670 status = NC_check_name(name);
01671 if(status != NC_NOERR)
01672 return status;
01673
01674 attrp = new_NC_attr(name, type, nelems);
01675 if(attrp == NULL)
01676 return NC_ENOMEM;
01677
01678 if(nelems != 0)
01679 {
01680 void *xp = attrp->xvalue;
01681 status = ncx_pad_putn_Iint(&xp, nelems,
01682 value, type);
01683 }
01684
01685 if(attrpp != NULL)
01686 {
01687 assert(old != NULL);
01688 *attrpp = attrp;
01689 free_NC_attr(old);
01690 }
01691 else
01692 {
01693 const int lstatus = incr_NC_attrarray(ncap, attrp);
01694
01695
01696
01697
01698 if(lstatus != NC_NOERR)
01699 {
01700 free_NC_attr(attrp);
01701 return lstatus;
01702 }
01703 }
01704
01705 return status;
01706 }
01707
01708 int
01709 nc_get_att_int(int ncid, int varid, const char *name, int *tp)
01710 {
01711 int status;
01712 NC_attr *attrp;
01713
01714 status = NC_lookupattr(ncid, varid, name, &attrp);
01715 if(status != NC_NOERR)
01716 return status;
01717
01718 if(attrp->nelems == 0)
01719 return NC_NOERR;
01720
01721 if(attrp->type == NC_CHAR)
01722 return NC_ECHAR;
01723
01724 {
01725 const void *xp = attrp->xvalue;
01726 return ncx_pad_getn_Iint(&xp, attrp->nelems, tp, attrp->type);
01727 }
01728 }
01729
01730
01731 int
01732 nc_put_att_long(int ncid, int varid, const char *name,
01733 nc_type type, size_t nelems, const long *value)
01734 {
01735 int status;
01736 NC *ncp;
01737 NC_attrarray *ncap;
01738 NC_attr **attrpp;
01739 NC_attr *old = NULL;
01740 NC_attr *attrp;
01741
01742 status = NC_check_id(ncid, &ncp);
01743 if(status != NC_NOERR)
01744 return status;
01745
01746 if(NC_readonly(ncp))
01747 return NC_EPERM;
01748
01749 ncap = NC_attrarray0(ncp, varid);
01750 if(ncap == NULL)
01751 return NC_ENOTVAR;
01752
01753 status = nc_cktype(type);
01754 if(status != NC_NOERR)
01755 return status;
01756
01757 if(type == NC_CHAR)
01758 return NC_ECHAR;
01759
01760
01761 if((unsigned long) nelems > X_INT_MAX)
01762 return NC_EINVAL;
01763
01764 if(nelems != 0 && value == NULL)
01765 return NC_EINVAL;
01766
01767 attrpp = NC_findattr(ncap, name);
01768 if(attrpp != NULL)
01769 {
01770 if(!NC_indef(ncp) )
01771 {
01772 const size_t xsz = ncx_len_NC_attrV(type, nelems);
01773 attrp = *attrpp;
01774
01775 if(xsz > attrp->xsz)
01776 return NC_ENOTINDEFINE;
01777
01778
01779 attrp->xsz = xsz;
01780 attrp->type = type;
01781 attrp->nelems = nelems;
01782
01783 if(nelems != 0)
01784 {
01785 void *xp = attrp->xvalue;
01786 status = ncx_pad_putn_Ilong(&xp, nelems,
01787 value, type);
01788 }
01789
01790 set_NC_hdirty(ncp);
01791
01792 if(NC_doHsync(ncp))
01793 {
01794 const int lstatus = NC_sync(ncp);
01795
01796
01797
01798
01799 if(lstatus != ENOERR)
01800 return lstatus;
01801 }
01802
01803 return status;
01804 }
01805
01806 old = *attrpp;
01807 }
01808 else
01809 {
01810 if(!NC_indef(ncp))
01811 return NC_ENOTINDEFINE;
01812
01813 if(ncap->nelems >= NC_MAX_ATTRS)
01814 return NC_EMAXATTS;
01815 }
01816
01817 status = NC_check_name(name);
01818 if(status != NC_NOERR)
01819 return status;
01820
01821 attrp = new_NC_attr(name, type, nelems);
01822 if(attrp == NULL)
01823 return NC_ENOMEM;
01824
01825 if(nelems != 0)
01826 {
01827 void *xp = attrp->xvalue;
01828 status = ncx_pad_putn_Ilong(&xp, nelems,
01829 value, type);
01830 }
01831
01832 if(attrpp != NULL)
01833 {
01834 assert(old != NULL);
01835 *attrpp = attrp;
01836 free_NC_attr(old);
01837 }
01838 else
01839 {
01840 const int lstatus = incr_NC_attrarray(ncap, attrp);
01841
01842
01843
01844
01845 if(lstatus != NC_NOERR)
01846 {
01847 free_NC_attr(attrp);
01848 return lstatus;
01849 }
01850 }
01851
01852 return status;
01853 }
01854
01855 int
01856 nc_get_att_long(int ncid, int varid, const char *name, long *tp)
01857 {
01858 int status;
01859 NC_attr *attrp;
01860
01861 status = NC_lookupattr(ncid, varid, name, &attrp);
01862 if(status != NC_NOERR)
01863 return status;
01864
01865 if(attrp->nelems == 0)
01866 return NC_NOERR;
01867
01868 if(attrp->type == NC_CHAR)
01869 return NC_ECHAR;
01870
01871 {
01872 const void *xp = attrp->xvalue;
01873 return ncx_pad_getn_Ilong(&xp, attrp->nelems, tp, attrp->type);
01874 }
01875 }
01876
01877
01878 int
01879 nc_put_att_float(int ncid, int varid, const char *name,
01880 nc_type type, size_t nelems, const float *value)
01881 {
01882 int status;
01883 NC *ncp;
01884 NC_attrarray *ncap;
01885 NC_attr **attrpp;
01886 NC_attr *old = NULL;
01887 NC_attr *attrp;
01888
01889 status = NC_check_id(ncid, &ncp);
01890 if(status != NC_NOERR)
01891 return status;
01892
01893 if(NC_readonly(ncp))
01894 return NC_EPERM;
01895
01896 ncap = NC_attrarray0(ncp, varid);
01897 if(ncap == NULL)
01898 return NC_ENOTVAR;
01899
01900 status = nc_cktype(type);
01901 if(status != NC_NOERR)
01902 return status;
01903
01904 if(type == NC_CHAR)
01905 return NC_ECHAR;
01906
01907
01908 if((unsigned long) nelems > X_INT_MAX)
01909 return NC_EINVAL;
01910
01911 if(nelems != 0 && value == NULL)
01912 return NC_EINVAL;
01913
01914 attrpp = NC_findattr(ncap, name);
01915 if(attrpp != NULL)
01916 {
01917 if(!NC_indef(ncp) )
01918 {
01919 const size_t xsz = ncx_len_NC_attrV(type, nelems);
01920 attrp = *attrpp;
01921
01922 if(xsz > attrp->xsz)
01923 return NC_ENOTINDEFINE;
01924
01925
01926 attrp->xsz = xsz;
01927 attrp->type = type;
01928 attrp->nelems = nelems;
01929
01930 if(nelems != 0)
01931 {
01932 void *xp = attrp->xvalue;
01933 status = ncx_pad_putn_Ifloat(&xp, nelems,
01934 value, type);
01935 }
01936
01937 set_NC_hdirty(ncp);
01938
01939 if(NC_doHsync(ncp))
01940 {
01941 const int lstatus = NC_sync(ncp);
01942
01943
01944
01945
01946 if(lstatus != ENOERR)
01947 return lstatus;
01948 }
01949
01950 return status;
01951 }
01952
01953 old = *attrpp;
01954 }
01955 else
01956 {
01957 if(!NC_indef(ncp))
01958 return NC_ENOTINDEFINE;
01959
01960 if(ncap->nelems >= NC_MAX_ATTRS)
01961 return NC_EMAXATTS;
01962 }
01963
01964 status = NC_check_name(name);
01965 if(status != NC_NOERR)
01966 return status;
01967
01968 attrp = new_NC_attr(name, type, nelems);
01969 if(attrp == NULL)
01970 return NC_ENOMEM;
01971
01972 if(nelems != 0)
01973 {
01974 void *xp = attrp->xvalue;
01975 status = ncx_pad_putn_Ifloat(&xp, nelems,
01976 value, type);
01977 }
01978
01979 if(attrpp != NULL)
01980 {
01981 assert(old != NULL);
01982 *attrpp = attrp;
01983 free_NC_attr(old);
01984 }
01985 else
01986 {
01987 const int lstatus = incr_NC_attrarray(ncap, attrp);
01988
01989
01990
01991
01992 if(lstatus != NC_NOERR)
01993 {
01994 free_NC_attr(attrp);
01995 return lstatus;
01996 }
01997 }
01998
01999 return status;
02000 }
02001
02002 int
02003 nc_get_att_float(int ncid, int varid, const char *name, float *tp)
02004 {
02005 int status;
02006 NC_attr *attrp;
02007
02008 status = NC_lookupattr(ncid, varid, name, &attrp);
02009 if(status != NC_NOERR)
02010 return status;
02011
02012 if(attrp->nelems == 0)
02013 return NC_NOERR;
02014
02015 if(attrp->type == NC_CHAR)
02016 return NC_ECHAR;
02017
02018 {
02019 const void *xp = attrp->xvalue;
02020 return ncx_pad_getn_Ifloat(&xp, attrp->nelems, tp, attrp->type);
02021 }
02022 }
02023
02024
02025 int
02026 nc_put_att_double(int ncid, int varid, const char *name,
02027 nc_type type, size_t nelems, const double *value)
02028 {
02029 int status;
02030 NC *ncp;
02031 NC_attrarray *ncap;
02032 NC_attr **attrpp;
02033 NC_attr *old = NULL;
02034 NC_attr *attrp;
02035
02036 status = NC_check_id(ncid, &ncp);
02037 if(status != NC_NOERR)
02038 return status;
02039
02040 if(NC_readonly(ncp))
02041 return NC_EPERM;
02042
02043 ncap = NC_attrarray0(ncp, varid);
02044 if(ncap == NULL)
02045 return NC_ENOTVAR;
02046
02047 status = nc_cktype(type);
02048 if(status != NC_NOERR)
02049 return status;
02050
02051 if(type == NC_CHAR)
02052 return NC_ECHAR;
02053
02054
02055 if((unsigned long) nelems > X_INT_MAX)
02056 return NC_EINVAL;
02057
02058 if(nelems != 0 && value == NULL)
02059 return NC_EINVAL;
02060
02061 attrpp = NC_findattr(ncap, name);
02062 if(attrpp != NULL)
02063 {
02064 if(!NC_indef(ncp) )
02065 {
02066 const size_t xsz = ncx_len_NC_attrV(type, nelems);
02067 attrp = *attrpp;
02068
02069 if(xsz > attrp->xsz)
02070 return NC_ENOTINDEFINE;
02071
02072
02073 attrp->xsz = xsz;
02074 attrp->type = type;
02075 attrp->nelems = nelems;
02076
02077 if(nelems != 0)
02078 {
02079 void *xp = attrp->xvalue;
02080 status = ncx_pad_putn_Idouble(&xp, nelems,
02081 value, type);
02082 }
02083
02084 set_NC_hdirty(ncp);
02085
02086 if(NC_doHsync(ncp))
02087 {
02088 const int lstatus = NC_sync(ncp);
02089
02090
02091
02092
02093 if(lstatus != ENOERR)
02094 return lstatus;
02095 }
02096
02097 return status;
02098 }
02099
02100 old = *attrpp;
02101 }
02102 else
02103 {
02104 if(!NC_indef(ncp))
02105 return NC_ENOTINDEFINE;
02106
02107 if(ncap->nelems >= NC_MAX_ATTRS)
02108 return NC_EMAXATTS;
02109 }
02110
02111 status = NC_check_name(name);
02112 if(status != NC_NOERR)
02113 return status;
02114
02115 attrp = new_NC_attr(name, type, nelems);
02116 if(attrp == NULL)
02117 return NC_ENOMEM;
02118
02119 if(nelems != 0)
02120 {
02121 void *xp = attrp->xvalue;
02122 status = ncx_pad_putn_Idouble(&xp, nelems,
02123 value, type);
02124 }
02125
02126 if(attrpp != NULL)
02127 {
02128 assert(old != NULL);
02129 *attrpp = attrp;
02130 free_NC_attr(old);
02131 }
02132 else
02133 {
02134 const int lstatus = incr_NC_attrarray(ncap, attrp);
02135
02136
02137
02138
02139 if(lstatus != NC_NOERR)
02140 {
02141 free_NC_attr(attrp);
02142 return lstatus;
02143 }
02144 }
02145
02146 return status;
02147 }
02148
02149 int
02150 nc_get_att_double(int ncid, int varid, const char *name, double *tp)
02151 {
02152 int status;
02153 NC_attr *attrp;
02154
02155 status = NC_lookupattr(ncid, varid, name, &attrp);
02156 if(status != NC_NOERR)
02157 return status;
02158
02159 if(attrp->nelems == 0)
02160 return NC_NOERR;
02161
02162 if(attrp->type == NC_CHAR)
02163 return NC_ECHAR;
02164
02165 {
02166 const void *xp = attrp->xvalue;
02167 return ncx_pad_getn_Idouble(&xp, attrp->nelems, tp, attrp->type);
02168 }
02169 }
02170
02171
02172
02173
02174 int
02175 nc_put_att(
02176 int ncid,
02177 int varid,
02178 const char *name,
02179 nc_type type,
02180 size_t nelems,
02181 const void *value)
02182 {
02183 switch (type) {
02184 case NC_BYTE:
02185 return nc_put_att_schar(ncid, varid, name, type, nelems,
02186 (schar *)value);
02187 case NC_CHAR:
02188 return nc_put_att_text(ncid, varid, name, nelems,
02189 (char *)value);
02190 case NC_SHORT:
02191 return nc_put_att_short(ncid, varid, name, type, nelems,
02192 (short *)value);
02193 case NC_INT:
02194 #if (SIZEOF_INT >= X_SIZEOF_INT)
02195 return nc_put_att_int(ncid, varid, name, type, nelems,
02196 (int *)value);
02197 #elif SIZEOF_LONG == X_SIZEOF_INT
02198 return nc_put_att_long(ncid, varid, name, type, nelems,
02199 (long *)value);
02200 #endif
02201 case NC_FLOAT:
02202 return nc_put_att_float(ncid, varid, name, type, nelems,
02203 (float *)value);
02204 case NC_DOUBLE:
02205 return nc_put_att_double(ncid, varid, name, type, nelems,
02206 (double *)value);
02207 }
02208 return NC_EBADTYPE;
02209 }
02210
02211
02212
02213 int
02214 nc_get_att(int ncid, int varid, const char *name, void *value)
02215 {
02216 int status;
02217 NC_attr *attrp;
02218
02219 status = NC_lookupattr(ncid, varid, name, &attrp);
02220 if(status != NC_NOERR)
02221 return status;
02222
02223 switch (attrp->type) {
02224 case NC_BYTE:
02225 return nc_get_att_schar(ncid, varid, name,
02226 (schar *)value);
02227 case NC_CHAR:
02228 return nc_get_att_text(ncid, varid, name,
02229 (char *)value);
02230 case NC_SHORT:
02231 return nc_get_att_short(ncid, varid, name,
02232 (short *)value);
02233 case NC_INT:
02234 #if (SIZEOF_INT >= X_SIZEOF_INT)
02235 return nc_get_att_int(ncid, varid, name,
02236 (int *)value);
02237 #elif SIZEOF_LONG == X_SIZEOF_INT
02238 return nc_get_att_long(ncid, varid, name,
02239 (long *)value);
02240 #endif
02241 case NC_FLOAT:
02242 return nc_get_att_float(ncid, varid, name,
02243 (float *)value);
02244 case NC_DOUBLE:
02245 return nc_get_att_double(ncid, varid, name,
02246 (double *)value);
02247 }
02248 return NC_EBADTYPE;
02249 }