00001
00002
00003
00004
00005
00006 #include "nc.h"
00007 #include <stdlib.h>
00008 #include <string.h>
00009 #include <assert.h>
00010 #include "rnd.h"
00011 #include "ncx.h"
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 static const schar ncmagic[] = {'C', 'D', 'F', 0x01};
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 typedef struct v1hs {
00042 ncio *nciop;
00043 off_t offset;
00044 size_t extent;
00045 int flags;
00046 void *base;
00047 void *pos;
00048 void *end;
00049 } v1hs;
00050
00051
00052
00053
00054
00055 static int
00056 rel_v1hs(v1hs *gsp)
00057 {
00058 int status;
00059 if(gsp->offset == OFF_NONE || gsp->base == NULL)
00060 return ENOERR;
00061 status = gsp->nciop->rel(gsp->nciop, gsp->offset,
00062 gsp->flags == RGN_WRITE ? RGN_MODIFIED : 0);
00063 gsp->end = NULL;
00064 gsp->pos = NULL;
00065 gsp->base = NULL;
00066 return status;
00067 }
00068
00069
00070
00071
00072
00073
00074 static int
00075 fault_v1hs(v1hs *gsp, size_t extent)
00076 {
00077 int status;
00078
00079 if(gsp->base != NULL)
00080 {
00081 const size_t incr = (char *)gsp->pos - (char *)gsp->base;
00082 status = rel_v1hs(gsp);
00083 if(status)
00084 return status;
00085 gsp->offset += incr;
00086 }
00087
00088 if(extent > gsp->extent)
00089 gsp->extent = extent;
00090
00091 status = gsp->nciop->get(gsp->nciop,
00092 gsp->offset, gsp->extent,
00093 gsp->flags, &gsp->base);
00094 if(status)
00095 return status;
00096
00097 gsp->pos = gsp->base;
00098 gsp->end = (char *)gsp->base + gsp->extent;
00099
00100 return ENOERR;
00101 }
00102
00103
00104
00105
00106
00107 static int
00108 check_v1hs(v1hs *gsp, size_t nextread)
00109 {
00110
00111 #if 0
00112 fprintf(stderr, "nextread %lu, remaining %lu\n",
00113 (unsigned long)nextread,
00114 (unsigned long)((char *)gsp->end - (char *)gsp->pos));
00115 #endif
00116
00117 if((char *)gsp->pos + nextread <= (char *)gsp->end)
00118 return ENOERR;
00119 return fault_v1hs(gsp, nextread);
00120 }
00121
00122
00123
00124 static int
00125 v1h_put_size_t(v1hs *psp, const size_t *sp)
00126 {
00127 int status = check_v1hs(psp, X_SIZEOF_SIZE_T);
00128 if(status != ENOERR)
00129 return status;
00130 return ncx_put_size_t(&psp->pos, sp);
00131 }
00132
00133
00134 static int
00135 v1h_get_size_t(v1hs *gsp, size_t *sp)
00136 {
00137 int status = check_v1hs(gsp, X_SIZEOF_SIZE_T);
00138 if(status != ENOERR)
00139 return status;
00140 return ncx_get_size_t((const void **)(&gsp->pos), sp);
00141 }
00142
00143
00144
00145
00146 #define X_SIZEOF_NC_TYPE X_SIZEOF_INT
00147
00148 static int
00149 v1h_put_nc_type(v1hs *psp, const nc_type *typep)
00150 {
00151 const int itype = (int) *typep;
00152 int status = check_v1hs(psp, X_SIZEOF_INT);
00153 if(status != ENOERR)
00154 return status;
00155 status = ncx_put_int_int(psp->pos, &itype);
00156 psp->pos = (void *)((char *)psp->pos + X_SIZEOF_INT);
00157 return status;
00158 }
00159
00160
00161 static int
00162 v1h_get_nc_type(v1hs *gsp, nc_type *typep)
00163 {
00164 int type = 0;
00165 int status = check_v1hs(gsp, X_SIZEOF_INT);
00166 if(status != ENOERR)
00167 return status;
00168 status = ncx_get_int_int(gsp->pos, &type);
00169 gsp->pos = (void *)((char *)gsp->pos + X_SIZEOF_INT);
00170 if(status != ENOERR)
00171 return status;
00172
00173 assert(type == NC_BYTE
00174 || type == NC_CHAR
00175 || type == NC_SHORT
00176 || type == NC_INT
00177 || type == NC_FLOAT
00178 || type == NC_DOUBLE);
00179
00180
00181 *typep = (nc_type) type;
00182
00183 return ENOERR;
00184 }
00185
00186
00187
00188
00189 #define X_SIZEOF_NCTYPE X_SIZEOF_INT
00190
00191 static int
00192 v1h_put_NCtype(v1hs *psp, NCtype type)
00193 {
00194 const int itype = (int) type;
00195 int status = check_v1hs(psp, X_SIZEOF_INT);
00196 if(status != ENOERR)
00197 return status;
00198 status = ncx_put_int_int(psp->pos, &itype);
00199 psp->pos = (void *)((char *)psp->pos + X_SIZEOF_INT);
00200 return status;
00201 }
00202
00203 static int
00204 v1h_get_NCtype(v1hs *gsp, NCtype *typep)
00205 {
00206 int type = 0;
00207 int status = check_v1hs(gsp, X_SIZEOF_INT);
00208 if(status != ENOERR)
00209 return status;
00210 status = ncx_get_int_int(gsp->pos, &type);
00211 gsp->pos = (void *)((char *)gsp->pos + X_SIZEOF_INT);
00212 if(status != ENOERR)
00213 return status;
00214
00215 *typep = (NCtype) type;
00216 return ENOERR;
00217 }
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 static size_t
00228 ncx_len_NC_string(const NC_string *ncstrp)
00229 {
00230 size_t sz = X_SIZEOF_SIZE_T;
00231
00232 assert(ncstrp != NULL);
00233
00234 if(ncstrp->nchars != 0)
00235 {
00236 #if 0
00237 assert(ncstrp->nchars % X_ALIGN == 0);
00238 sz += ncstrp->nchars;
00239 #else
00240 sz += _RNDUP(ncstrp->nchars, X_ALIGN);
00241 #endif
00242 }
00243 return sz;
00244 }
00245
00246
00247 static int
00248 v1h_put_NC_string(v1hs *psp, const NC_string *ncstrp)
00249 {
00250 int status;
00251
00252 #if 0
00253 assert(ncstrp->nchars % X_ALIGN == 0);
00254 #endif
00255
00256 status = v1h_put_size_t(psp, &ncstrp->nchars);
00257 if(status != ENOERR)
00258 return status;
00259 status = check_v1hs(psp, _RNDUP(ncstrp->nchars, X_ALIGN));
00260 if(status != ENOERR)
00261 return status;
00262 status = ncx_pad_putn_text(&psp->pos, ncstrp->nchars, ncstrp->cp);
00263 if(status != ENOERR)
00264 return status;
00265
00266 return ENOERR;
00267 }
00268
00269
00270 static int
00271 v1h_get_NC_string(v1hs *gsp, NC_string **ncstrpp)
00272 {
00273 int status;
00274 size_t nchars = 0;
00275 NC_string *ncstrp;
00276
00277 status = v1h_get_size_t(gsp, &nchars);
00278 if(status != ENOERR)
00279 return status;
00280
00281 ncstrp = new_NC_string(nchars, NULL);
00282 if(ncstrp == NULL)
00283 {
00284 return NC_ENOMEM;
00285 }
00286
00287
00288 #if 0
00289
00290 assert(ncstrp->nchars % X_ALIGN == 0);
00291 status = check_v1hs(gsp, ncstrp->nchars);
00292 #else
00293
00294 status = check_v1hs(gsp, _RNDUP(ncstrp->nchars, X_ALIGN));
00295 #endif
00296 if(status != ENOERR)
00297 goto unwind_alloc;
00298
00299 status = ncx_pad_getn_text((const void **)(&gsp->pos),
00300 nchars, ncstrp->cp);
00301 if(status != ENOERR)
00302 goto unwind_alloc;
00303
00304 *ncstrpp = ncstrp;
00305
00306 return ENOERR;
00307
00308 unwind_alloc:
00309 free_NC_string(ncstrp);
00310 return status;
00311
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 static size_t
00323 ncx_len_NC_dim(const NC_dim *dimp)
00324 {
00325 size_t sz;
00326
00327 assert(dimp != NULL);
00328
00329 sz = ncx_len_NC_string(dimp->name);
00330 sz += X_SIZEOF_SIZE_T;
00331
00332 return(sz);
00333 }
00334
00335
00336 static int
00337 v1h_put_NC_dim(v1hs *psp, const NC_dim *dimp)
00338 {
00339 int status;
00340
00341 status = v1h_put_NC_string(psp, dimp->name);
00342 if(status != ENOERR)
00343 return status;
00344
00345 status = v1h_put_size_t(psp, &dimp->size);
00346 if(status != ENOERR)
00347 return status;
00348
00349 return ENOERR;
00350 }
00351
00352 static int
00353 v1h_get_NC_dim(v1hs *gsp, NC_dim **dimpp)
00354 {
00355 int status;
00356 NC_string *ncstrp;
00357 NC_dim *dimp;
00358
00359 status = v1h_get_NC_string(gsp, &ncstrp);
00360 if(status != ENOERR)
00361 return status;
00362
00363 dimp = new_x_NC_dim(ncstrp);
00364 if(dimp == NULL)
00365 {
00366 status = NC_ENOMEM;
00367 goto unwind_name;
00368 }
00369
00370 status = v1h_get_size_t(gsp, &dimp->size);
00371 if(status != ENOERR)
00372 {
00373 free_NC_dim(dimp);
00374 return status;
00375 }
00376
00377 *dimpp = dimp;
00378
00379 return ENOERR;
00380
00381 unwind_name:
00382 free_NC_string(ncstrp);
00383 return status;
00384 }
00385
00386
00387 static size_t
00388 ncx_len_NC_dimarray(const NC_dimarray *ncap)
00389 {
00390 size_t xlen = X_SIZEOF_NCTYPE;
00391 xlen += X_SIZEOF_SIZE_T;
00392 if(ncap == NULL)
00393 return xlen;
00394
00395 {
00396 const NC_dim **dpp = (const NC_dim **)ncap->value;
00397 const NC_dim *const *const end = &dpp[ncap->nelems];
00398 for( ; dpp < end; dpp++)
00399 {
00400 xlen += ncx_len_NC_dim(*dpp);
00401 }
00402 }
00403 return xlen;
00404 }
00405
00406
00407 static int
00408 v1h_put_NC_dimarray(v1hs *psp, const NC_dimarray *ncap)
00409 {
00410 int status;
00411
00412 assert(psp != NULL);
00413
00414 if(ncap == NULL
00415 #if 1
00416
00417
00418
00419
00420
00421 || ncap->nelems == 0
00422 #endif
00423 )
00424 {
00425
00426
00427
00428 const size_t nosz = 0;
00429
00430 status = v1h_put_NCtype(psp, NC_UNSPECIFIED);
00431 if(status != ENOERR)
00432 return status;
00433 status = v1h_put_size_t(psp, &nosz);
00434 if(status != ENOERR)
00435 return status;
00436 return ENOERR;
00437 }
00438
00439
00440 status = v1h_put_NCtype(psp, NC_DIMENSION);
00441 if(status != ENOERR)
00442 return status;
00443 status = v1h_put_size_t(psp, &ncap->nelems);
00444 if(status != ENOERR)
00445 return status;
00446
00447 {
00448 const NC_dim **dpp = (const NC_dim **)ncap->value;
00449 const NC_dim *const *const end = &dpp[ncap->nelems];
00450 for( ; dpp < end; dpp++)
00451 {
00452 status = v1h_put_NC_dim(psp, *dpp);
00453 if(status)
00454 return status;
00455 }
00456 }
00457 return ENOERR;
00458 }
00459
00460
00461 static int
00462 v1h_get_NC_dimarray(v1hs *gsp, NC_dimarray *ncap)
00463 {
00464 int status;
00465 NCtype type = NC_UNSPECIFIED;
00466
00467 assert(gsp != NULL && gsp->pos != NULL);
00468 assert(ncap != NULL);
00469 assert(ncap->value == NULL);
00470
00471 status = v1h_get_NCtype(gsp, &type);
00472 if(status != ENOERR)
00473 return status;
00474
00475 status = v1h_get_size_t(gsp, &ncap->nelems);
00476 if(status != ENOERR)
00477 return status;
00478
00479 if(ncap->nelems == 0)
00480 return ENOERR;
00481
00482 if(type != NC_DIMENSION)
00483 return EINVAL;
00484
00485 ncap->value = (NC_dim **) malloc(ncap->nelems * sizeof(NC_dim *));
00486 if(ncap->value == NULL)
00487 return NC_ENOMEM;
00488 ncap->nalloc = ncap->nelems;
00489
00490 {
00491 NC_dim **dpp = ncap->value;
00492 NC_dim *const *const end = &dpp[ncap->nelems];
00493 for( ; dpp < end; dpp++)
00494 {
00495 status = v1h_get_NC_dim(gsp, dpp);
00496 if(status)
00497 {
00498 ncap->nelems = dpp - ncap->value;
00499 free_NC_dimarrayV(ncap);
00500 return status;
00501 }
00502 }
00503 }
00504
00505 return ENOERR;
00506 }
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 static size_t
00519 ncx_len_NC_attr(const NC_attr *attrp)
00520 {
00521 size_t sz;
00522
00523 assert(attrp != NULL);
00524
00525 sz = ncx_len_NC_string(attrp->name);
00526 sz += X_SIZEOF_NC_TYPE;
00527 sz += X_SIZEOF_SIZE_T;
00528 sz += attrp->xsz;
00529
00530 return(sz);
00531 }
00532
00533
00534 #undef MIN
00535 #define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn))
00536
00537
00538
00539
00540
00541
00542 static int
00543 v1h_put_NC_attrV(v1hs *psp, const NC_attr *attrp)
00544 {
00545 int status;
00546 const size_t perchunk = psp->extent;
00547 size_t remaining = attrp->xsz;
00548 void *value = attrp->xvalue;
00549 size_t nbytes;
00550
00551 assert(psp->extent % X_ALIGN == 0);
00552
00553 do {
00554 nbytes = MIN(perchunk, remaining);
00555
00556 status = check_v1hs(psp, nbytes);
00557 if(status != ENOERR)
00558 return status;
00559
00560 (void) memcpy(psp->pos, value, nbytes);
00561
00562 psp->pos = (void *)((char *)psp->pos + nbytes);
00563 value = (void *)((char *)value + nbytes);
00564 remaining -= nbytes;
00565
00566 } while(remaining != 0);
00567
00568 return ENOERR;
00569 }
00570
00571 static int
00572 v1h_put_NC_attr(v1hs *psp, const NC_attr *attrp)
00573 {
00574 int status;
00575
00576 status = v1h_put_NC_string(psp, attrp->name);
00577 if(status != ENOERR)
00578 return status;
00579
00580 status = v1h_put_nc_type(psp, &attrp->type);
00581 if(status != ENOERR)
00582 return status;
00583
00584 status = v1h_put_size_t(psp, &attrp->nelems);
00585 if(status != ENOERR)
00586 return status;
00587
00588 status = v1h_put_NC_attrV(psp, attrp);
00589 if(status != ENOERR)
00590 return status;
00591
00592 return ENOERR;
00593 }
00594
00595
00596
00597
00598
00599
00600
00601 static int
00602 v1h_get_NC_attrV(v1hs *gsp, NC_attr *attrp)
00603 {
00604 int status;
00605 const size_t perchunk = gsp->extent;
00606 size_t remaining = attrp->xsz;
00607 void *value = attrp->xvalue;
00608 size_t nget;
00609
00610 assert(gsp->extent % X_ALIGN == 0);
00611
00612 do {
00613 nget = MIN(perchunk, remaining);
00614
00615 status = check_v1hs(gsp, nget);
00616 if(status != ENOERR)
00617 return status;
00618
00619 (void) memcpy(value, gsp->pos, nget);
00620
00621 gsp->pos = (void *)((char *)gsp->pos + nget);
00622 value = (void *)((char *)value + nget);
00623 remaining -= nget;
00624
00625 } while(remaining != 0);
00626
00627 return ENOERR;
00628 }
00629
00630
00631 static int
00632 v1h_get_NC_attr(v1hs *gsp, NC_attr **attrpp)
00633 {
00634 NC_string *strp;
00635 int status;
00636 nc_type type;
00637 size_t nelems;
00638 NC_attr *attrp;
00639
00640 status = v1h_get_NC_string(gsp, &strp);
00641 if(status != ENOERR)
00642 return status;
00643
00644 status = v1h_get_nc_type(gsp, &type);
00645 if(status != ENOERR)
00646 goto unwind_name;
00647
00648 status = v1h_get_size_t(gsp, &nelems);
00649 if(status != ENOERR)
00650 goto unwind_name;
00651
00652 attrp = new_x_NC_attr(strp, type, nelems);
00653 if(attrp == NULL)
00654 {
00655 status = NC_ENOMEM;
00656 goto unwind_name;
00657 }
00658
00659 status = v1h_get_NC_attrV(gsp, attrp);
00660 if(status != ENOERR)
00661 {
00662 free_NC_attr(attrp);
00663 return status;
00664 }
00665
00666 *attrpp = attrp;
00667
00668 return ENOERR;
00669
00670 unwind_name:
00671 free_NC_string(strp);
00672 return status;
00673 }
00674
00675
00676 static size_t
00677 ncx_len_NC_attrarray(const NC_attrarray *ncap)
00678 {
00679 size_t xlen = X_SIZEOF_NCTYPE;
00680 xlen += X_SIZEOF_SIZE_T;
00681 if(ncap == NULL)
00682 return xlen;
00683
00684 {
00685 const NC_attr **app = (const NC_attr **)ncap->value;
00686 const NC_attr *const *const end = &app[ncap->nelems];
00687 for( ; app < end; app++)
00688 {
00689 xlen += ncx_len_NC_attr(*app);
00690 }
00691 }
00692 return xlen;
00693 }
00694
00695
00696 static int
00697 v1h_put_NC_attrarray(v1hs *psp, const NC_attrarray *ncap)
00698 {
00699 int status;
00700
00701 assert(psp != NULL);
00702
00703 if(ncap == NULL
00704 #if 1
00705
00706
00707
00708
00709
00710 || ncap->nelems == 0
00711 #endif
00712 )
00713 {
00714
00715
00716
00717 const size_t nosz = 0;
00718
00719 status = v1h_put_NCtype(psp, NC_UNSPECIFIED);
00720 if(status != ENOERR)
00721 return status;
00722 status = v1h_put_size_t(psp, &nosz);
00723 if(status != ENOERR)
00724 return status;
00725 return ENOERR;
00726 }
00727
00728
00729 status = v1h_put_NCtype(psp, NC_ATTRIBUTE);
00730 if(status != ENOERR)
00731 return status;
00732 status = v1h_put_size_t(psp, &ncap->nelems);
00733 if(status != ENOERR)
00734 return status;
00735
00736 {
00737 const NC_attr **app = (const NC_attr **)ncap->value;
00738 const NC_attr *const *const end = &app[ncap->nelems];
00739 for( ; app < end; app++)
00740 {
00741 status = v1h_put_NC_attr(psp, *app);
00742 if(status)
00743 return status;
00744 }
00745 }
00746 return ENOERR;
00747 }
00748
00749
00750 static int
00751 v1h_get_NC_attrarray(v1hs *gsp, NC_attrarray *ncap)
00752 {
00753 int status;
00754 NCtype type = NC_UNSPECIFIED;
00755
00756 assert(gsp != NULL && gsp->pos != NULL);
00757 assert(ncap != NULL);
00758 assert(ncap->value == NULL);
00759
00760 status = v1h_get_NCtype(gsp, &type);
00761 if(status != ENOERR)
00762 return status;
00763 status = v1h_get_size_t(gsp, &ncap->nelems);
00764 if(status != ENOERR)
00765 return status;
00766
00767 if(ncap->nelems == 0)
00768 return ENOERR;
00769
00770 if(type != NC_ATTRIBUTE)
00771 return EINVAL;
00772
00773 ncap->value = (NC_attr **) malloc(ncap->nelems * sizeof(NC_attr *));
00774 if(ncap->value == NULL)
00775 return NC_ENOMEM;
00776 ncap->nalloc = ncap->nelems;
00777
00778 {
00779 NC_attr **app = ncap->value;
00780 NC_attr *const *const end = &app[ncap->nelems];
00781 for( ; app < end; app++)
00782 {
00783 status = v1h_get_NC_attr(gsp, app);
00784 if(status)
00785 {
00786 ncap->nelems = app - ncap->value;
00787 free_NC_attrarrayV(ncap);
00788 return status;
00789 }
00790 }
00791 }
00792
00793 return ENOERR;
00794 }
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804 static size_t
00805 ncx_len_NC_var(const NC_var *varp)
00806 {
00807 size_t sz;
00808
00809 assert(varp != NULL);
00810
00811 sz = ncx_len_NC_string(varp->name);
00812 sz += X_SIZEOF_SIZE_T;
00813 sz += ncx_len_int(varp->ndims);
00814 sz += ncx_len_NC_attrarray(&varp->attrs);
00815 sz += X_SIZEOF_NC_TYPE;
00816 sz += X_SIZEOF_SIZE_T;
00817 sz += X_SIZEOF_OFF_T;
00818
00819 return(sz);
00820 }
00821
00822
00823 static int
00824 v1h_put_NC_var(v1hs *psp, const NC_var *varp)
00825 {
00826 int status;
00827
00828 status = v1h_put_NC_string(psp, varp->name);
00829 if(status != ENOERR)
00830 return status;
00831
00832 status = v1h_put_size_t(psp, &varp->ndims);
00833 if(status != ENOERR)
00834 return status;
00835
00836 status = check_v1hs(psp, ncx_len_int(varp->ndims));
00837 if(status != ENOERR)
00838 return status;
00839 status = ncx_putn_int_int(&psp->pos,
00840 varp->ndims, varp->dimids);
00841 if(status != ENOERR)
00842 return status;
00843
00844 status = v1h_put_NC_attrarray(psp, &varp->attrs);
00845 if(status != ENOERR)
00846 return status;
00847
00848 status = v1h_put_nc_type(psp, &varp->type);
00849 if(status != ENOERR)
00850 return status;
00851
00852 status = v1h_put_size_t(psp, &varp->len);
00853 if(status != ENOERR)
00854 return status;
00855
00856 status = check_v1hs(psp, X_SIZEOF_OFF_T);
00857 if(status != ENOERR)
00858 return status;
00859 status = ncx_put_off_t(&psp->pos, &varp->begin);
00860 if(status != ENOERR)
00861 return status;
00862
00863 return ENOERR;
00864 }
00865
00866
00867 static int
00868 v1h_get_NC_var(v1hs *gsp, NC_var **varpp)
00869 {
00870 NC_string *strp;
00871 int status;
00872 size_t ndims;
00873 NC_var *varp;
00874
00875 status = v1h_get_NC_string(gsp, &strp);
00876 if(status != ENOERR)
00877 return status;
00878
00879 status = v1h_get_size_t(gsp, &ndims);
00880 if(status != ENOERR)
00881 goto unwind_name;
00882
00883 varp = new_x_NC_var(strp, ndims);
00884 if(varp == NULL)
00885 {
00886 status = NC_ENOMEM;
00887 goto unwind_name;
00888 }
00889
00890 status = check_v1hs(gsp, ncx_len_int(ndims));
00891 if(status != ENOERR)
00892 goto unwind_alloc;
00893 status = ncx_getn_int_int((const void **)(&gsp->pos),
00894 ndims, varp->dimids);
00895 if(status != ENOERR)
00896 goto unwind_alloc;
00897
00898 status = v1h_get_NC_attrarray(gsp, &varp->attrs);
00899 if(status != ENOERR)
00900 goto unwind_alloc;
00901
00902 status = v1h_get_nc_type(gsp, &varp->type);
00903 if(status != ENOERR)
00904 goto unwind_alloc;
00905
00906 status = v1h_get_size_t(gsp, &varp->len);
00907 if(status != ENOERR)
00908 goto unwind_alloc;
00909
00910 status = check_v1hs(gsp, X_SIZEOF_OFF_T);
00911 if(status != ENOERR)
00912 goto unwind_alloc;
00913 status = ncx_get_off_t((const void **)&gsp->pos,
00914 &varp->begin);
00915 if(status != ENOERR)
00916 goto unwind_alloc;
00917
00918 *varpp = varp;
00919 return ENOERR;
00920
00921 unwind_alloc:
00922 free_NC_var(varp);
00923 return status;
00924
00925 unwind_name:
00926 free_NC_string(strp);
00927 return status;
00928 }
00929
00930
00931 static size_t
00932 ncx_len_NC_vararray(const NC_vararray *ncap)
00933 {
00934 size_t xlen = X_SIZEOF_NCTYPE;
00935 xlen += X_SIZEOF_SIZE_T;
00936 if(ncap == NULL)
00937 return xlen;
00938
00939 {
00940 const NC_var **vpp = (const NC_var **)ncap->value;
00941 const NC_var *const *const end = &vpp[ncap->nelems];
00942 for( ; vpp < end; vpp++)
00943 {
00944 xlen += ncx_len_NC_var(*vpp);
00945 }
00946 }
00947 return xlen;
00948 }
00949
00950
00951 static int
00952 v1h_put_NC_vararray(v1hs *psp, const NC_vararray *ncap)
00953 {
00954 int status;
00955
00956 assert(psp != NULL);
00957
00958 if(ncap == NULL
00959 #if 1
00960
00961
00962
00963
00964
00965 || ncap->nelems == 0
00966 #endif
00967 )
00968 {
00969
00970
00971
00972 const size_t nosz = 0;
00973
00974 status = v1h_put_NCtype(psp, NC_UNSPECIFIED);
00975 if(status != ENOERR)
00976 return status;
00977 status = v1h_put_size_t(psp, &nosz);
00978 if(status != ENOERR)
00979 return status;
00980 return ENOERR;
00981 }
00982
00983
00984 status = v1h_put_NCtype(psp, NC_VARIABLE);
00985 if(status != ENOERR)
00986 return status;
00987 status = v1h_put_size_t(psp, &ncap->nelems);
00988 if(status != ENOERR)
00989 return status;
00990
00991 {
00992 const NC_var **vpp = (const NC_var **)ncap->value;
00993 const NC_var *const *const end = &vpp[ncap->nelems];
00994 for( ; vpp < end; vpp++)
00995 {
00996 status = v1h_put_NC_var(psp, *vpp);
00997 if(status)
00998 return status;
00999 }
01000 }
01001 return ENOERR;
01002 }
01003
01004
01005 static int
01006 v1h_get_NC_vararray(v1hs *gsp, NC_vararray *ncap)
01007 {
01008 int status;
01009 NCtype type = NC_UNSPECIFIED;
01010
01011 assert(gsp != NULL && gsp->pos != NULL);
01012 assert(ncap != NULL);
01013 assert(ncap->value == NULL);
01014
01015 status = v1h_get_NCtype(gsp, &type);
01016 if(status != ENOERR)
01017 return status;
01018
01019 status = v1h_get_size_t(gsp, &ncap->nelems);
01020 if(status != ENOERR)
01021 return status;
01022
01023 if(ncap->nelems == 0)
01024 return ENOERR;
01025
01026 if(type != NC_VARIABLE)
01027 return EINVAL;
01028
01029 ncap->value = (NC_var **) malloc(ncap->nelems * sizeof(NC_var *));
01030 if(ncap->value == NULL)
01031 return NC_ENOMEM;
01032 ncap->nalloc = ncap->nelems;
01033
01034 {
01035 NC_var **vpp = ncap->value;
01036 NC_var *const *const end = &vpp[ncap->nelems];
01037 for( ; vpp < end; vpp++)
01038 {
01039 status = v1h_get_NC_var(gsp, vpp);
01040 if(status)
01041 {
01042 ncap->nelems = vpp - ncap->value;
01043 free_NC_vararrayV(ncap);
01044 return status;
01045 }
01046 }
01047 }
01048
01049 return ENOERR;
01050 }
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065 static int
01066 NC_computeshapes(NC *ncp)
01067 {
01068 NC_var **vpp = (NC_var **)ncp->vars.value;
01069 NC_var *const *const end = &vpp[ncp->vars.nelems];
01070 NC_var *first_var = NULL;
01071 NC_var *first_rec = NULL;
01072 int status;
01073
01074 ncp->begin_var = (off_t) ncp->xsz;
01075 ncp->begin_rec = (off_t) ncp->xsz;
01076 ncp->recsize = 0;
01077
01078 if(ncp->vars.nelems == 0)
01079 return(0);
01080
01081 for( ; vpp < end; vpp++)
01082 {
01083 status = NC_var_shape(*vpp, &ncp->dims);
01084 if(status != ENOERR)
01085 return(status);
01086
01087 if(IS_RECVAR(*vpp))
01088 {
01089 if(first_rec == NULL)
01090 first_rec = *vpp;
01091 ncp->recsize += (*vpp)->len;
01092 }
01093 else if(first_var == NULL)
01094 {
01095 first_var = *vpp;
01096
01097
01098
01099
01100 ncp->begin_rec = (*vpp)->begin + (off_t)(*vpp)->len;
01101 }
01102 }
01103
01104 if(first_rec != NULL)
01105 {
01106 assert(ncp->begin_rec <= first_rec->begin);
01107 ncp->begin_rec = first_rec->begin;
01108
01109
01110
01111 if(ncp->recsize == first_rec->len)
01112 ncp->recsize = *first_rec->dsizes * first_rec->xsz;
01113 }
01114
01115 if(first_var != NULL)
01116 {
01117 ncp->begin_var = first_var->begin;
01118 }
01119 else
01120 {
01121 ncp->begin_var = ncp->begin_rec;
01122 }
01123
01124 assert(ncp->begin_var > 0);
01125 assert(ncp->xsz <= (size_t)ncp->begin_var);
01126 assert(ncp->begin_rec > 0);
01127 assert(ncp->begin_var <= ncp->begin_rec);
01128
01129 return(ENOERR);
01130 }
01131
01132
01133 size_t
01134 ncx_len_NC(const NC *ncp)
01135 {
01136 size_t xlen = sizeof(ncmagic);
01137
01138 assert(ncp != NULL);
01139
01140 xlen += X_SIZEOF_SIZE_T;
01141 xlen += ncx_len_NC_dimarray(&ncp->dims);
01142 xlen += ncx_len_NC_attrarray(&ncp->attrs);
01143 xlen += ncx_len_NC_vararray(&ncp->vars);
01144
01145 return xlen;
01146 }
01147
01148
01149 int
01150 ncx_put_NC(const NC *ncp, void **xpp, off_t offset, size_t extent)
01151 {
01152 int status = ENOERR;
01153 v1hs ps;
01154
01155 assert(ncp != NULL);
01156
01157
01158
01159 ps.nciop = ncp->nciop;
01160 ps.flags = RGN_WRITE;
01161
01162 if(xpp == NULL)
01163 {
01164
01165
01166
01167 extent = ncp->xsz;
01168 if(extent <= MIN_NC_XSZ)
01169 {
01170
01171 extent = ncp->chunk;
01172
01173
01174 if(extent > 4096)
01175 extent = 4096;
01176 }
01177 else if(extent > ncp->chunk)
01178 {
01179 extent = ncp->chunk;
01180 }
01181
01182 ps.offset = 0;
01183 ps.extent = extent;
01184 ps.base = NULL;
01185 ps.pos = ps.base;
01186
01187 status = fault_v1hs(&ps, extent);
01188 if(status)
01189 return status;
01190 }
01191 else
01192 {
01193 ps.offset = offset;
01194 ps.extent = extent;
01195 ps.base = *xpp;
01196 ps.pos = ps.base;
01197 ps.end = (char *)ps.base + ps.extent;
01198 }
01199
01200 status = ncx_putn_schar_schar(&ps.pos, sizeof(ncmagic), ncmagic);
01201 if(status != ENOERR)
01202 goto release;
01203
01204 {
01205 const size_t nrecs = NC_get_numrecs(ncp);
01206 status = ncx_put_size_t(&ps.pos, &nrecs);
01207 if(status != ENOERR)
01208 goto release;
01209 }
01210
01211 assert((char *)ps.pos < (char *)ps.end);
01212
01213 status = v1h_put_NC_dimarray(&ps, &ncp->dims);
01214 if(status != ENOERR)
01215 goto release;
01216
01217 status = v1h_put_NC_attrarray(&ps, &ncp->attrs);
01218 if(status != ENOERR)
01219 goto release;
01220
01221 status = v1h_put_NC_vararray(&ps, &ncp->vars);
01222 if(status != ENOERR)
01223 goto release;
01224
01225 release:
01226 (void) rel_v1hs(&ps);
01227
01228 return status;
01229 }
01230
01231
01232 int
01233 nc_get_NC(NC *ncp)
01234 {
01235 int status;
01236 v1hs gs;
01237
01238 assert(ncp != NULL);
01239
01240
01241
01242 gs.nciop = ncp->nciop;
01243 gs.offset = 0;
01244 gs.extent = 0;
01245 gs.flags = 0;
01246 gs.base = NULL;
01247 gs.pos = gs.base;
01248
01249 {
01250
01251
01252
01253 size_t extent = ncp->xsz;
01254 if(extent <= MIN_NC_XSZ)
01255 {
01256
01257 extent = ncp->chunk;
01258
01259
01260 if(extent > 4096)
01261 extent = 4096;
01262 }
01263 else if(extent > ncp->chunk)
01264 {
01265 extent = ncp->chunk;
01266 }
01267
01268 status = fault_v1hs(&gs, extent);
01269 if(status)
01270 return status;
01271 }
01272
01273
01274
01275 {
01276
01277 schar magic[sizeof(ncmagic)];
01278 (void) memset(magic, 0, sizeof(magic));
01279
01280 status = ncx_getn_schar_schar(
01281 (const void **)(&gs.pos), sizeof(magic), magic);
01282 if(status != ENOERR)
01283 goto unwind_get;
01284
01285 if(memcmp(magic, ncmagic, sizeof(ncmagic)) != 0)
01286 {
01287 status = NC_ENOTNC;
01288 goto unwind_get;
01289 }
01290 }
01291
01292 {
01293 size_t nrecs = 0;
01294 status = ncx_get_size_t((const void **)(&gs.pos), &nrecs);
01295 if(status != ENOERR)
01296 goto unwind_get;
01297 NC_set_numrecs(ncp, nrecs);
01298 }
01299
01300 assert((char *)gs.pos < (char *)gs.end);
01301
01302 status = v1h_get_NC_dimarray(&gs, &ncp->dims);
01303 if(status != ENOERR)
01304 goto unwind_get;
01305
01306 status = v1h_get_NC_attrarray(&gs, &ncp->attrs);
01307 if(status != ENOERR)
01308 goto unwind_get;
01309
01310 status = v1h_get_NC_vararray(&gs, &ncp->vars);
01311 if(status != ENOERR)
01312 goto unwind_get;
01313
01314 ncp->xsz = ncx_len_NC(ncp);
01315
01316 status = NC_computeshapes(ncp);
01317
01318 unwind_get:
01319 (void) rel_v1hs(&gs);
01320 return status;
01321 }