#include "ncdap4.h" #include "dapodom.h" #include "dapalign.h" #ifdef DEBUG #include "dapdump.h" #endif #include "ncd3dispatch.h" static NCerror getcontent4(NCDAPCOMMON*, Getvara*, CDFnode* rootnode, void* data); static NCerror getcontent4r(NCDAPCOMMON*, Getvara*, CDFnode* tnode, OCdata, NCbytes*); static NCerror getcontent4prim(NCDAPCOMMON* dapcomm, Getvara*, CDFnode* tnode, DCEsegment*, OCdata currentcontent, NCbytes* memory); static int findfield(CDFnode* node, CDFnode* subnode); static int contiguousdims(Dapodometer* odom); static NCerror ncdap4convert(nc_type srctype, nc_type dsttype, char* memory, char* value, size_t); static void makewholesegment4(DCEsegment* seg, NClist* dimset); /* See the comment preceding nc3d_getvarx to understand how constraints are handled. */ int NCD4_get_vara(int ncid, int varid, const size_t* startp, const size_t* countp, const ptrdiff_t* stridep, void* data, nc_type externaltype0) { unsigned int i; NCerror ncstat = NC_NOERR; OCerror ocstat = OC_NOERR; NC* drno; NCDAPCOMMON* dapcomm; CDFnode* cdfvar; /* cdf node mapping to var*/ NClist* varnodes; Getvara* varainfo = NULL; CDFnode* xtarget = NULL; CDFnode* target = NULL; DCEprojection* varaprojection = NULL; NCcachenode* cachenode = NULL; nc_type externaltype = externaltype0; size_t localcount[NC_MAX_VAR_DIMS]; NClist* ncdimsall; size_t ncrank; NClist* vars = NULL; DCEconstraint* fetchconstraint = NULL; DCEprojection* fetchprojection = NULL; DCEprojection* walkprojection = NULL; int state; #define FETCHWHOLE 1 /* fetch whole data set */ #define FETCHPART 2 /* fetch constrained variable */ #define CACHED 4 /* whole variable is already in the cache */ LOG((2, "nc_get_vara: ncid 0x%x varid %d", ncid, varid)); ncstat = NC_check_id(ncid, (NC**)&drno); if(ncstat != NC_NOERR) goto fail; dapcomm = (NCDAPCOMMON*)drno->dispatchdata; /* Find cdfnode corresponding to the var.*/ varnodes = dapcomm->cdf.varnodes; cdfvar = NULL; for(i=0;incid == varid) { cdfvar = node; break; } } ASSERT((cdfvar != NULL)); /* Get the dimension info */ ncdimsall = cdfvar->array.dimset0; ncrank = nclistlength(ncdimsall); #ifdef DEBUG { int i; fprintf(stderr,"getvarx: %s",cdfvar->ncfullname); for(i=0;idim.declsize; } countp = localcount; } if(stridep == NULL) stridep = NC_stride_one; /* Validate the dimension sizes */ for(i=0;i dim->dim.declsize || startp[i]+countp[i] > dim->dim.declsize) { ncstat = NC_EINVALCOORDS; goto fail; } } #ifdef DEBUG { NClist* dims = cdfvar->array.dimset0; fprintf(stderr,"getvarx: %s/%d",cdfvar->ncfullname,(int)nclistlength(dims)); if(nclistlength(dims) > 0) {int i; for(i=0;i "); for(i=0;iexternaltype; /* Validate any implied type conversion*/ if(cdfvar->nctype == NC_Primitive && cdfvar->etype != externaltype && externaltype == NC_CHAR) { /* The only disallowed conversion is to/from char and non-byte numeric types*/ switch (cdfvar->etype) { case NC_STRING: case NC_URL: case NC_CHAR: case NC_BYTE: case NC_UBYTE: break; default: THROWCHK(NC_ECHAR); goto fail; } } ncstat = makegetvar34(dapcomm,cdfvar,data,externaltype,&varainfo); if(ncstat) {THROWCHK(NC_ENOMEM); goto fail;} state = 0; if(FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE)) { state = FETCHWHOLE; cachenode = dapcomm->cdf.cache->prefetch; ASSERT((cachenode != NULL)); #ifdef DEBUG fprintf(stderr,"Unconstrained: reusing prefetch\n"); #endif #ifdef IGNORE } else if(iscached(dapcomm,cdfvar,&cachenode)) { #else } else if(iscached(dapcomm,cdfvar,&cachenode)) { #endif /* If it is cached, then it is a whole variable but may still need to apply constraints */ #ifdef DEBUG fprintf(stderr,"Reusing cache\n"); #endif ASSERT(cachenode->wholevariable); /* by construction */ state = CACHED; } else {/* load using constraints */ state = FETCHPART; } ASSERT(state != 0); ncstat = buildvaraprojection3(varainfo, startp,countp,nc_ptrdiffvector1, &varaprojection); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto fail;} /* In all cases, we need to construct the single projection as the merge of the url projections and the vara projection. */ /* Convert the start/stop/stride info into a projection */ ncstat = buildvaraprojection3(varainfo, startp,countp,stridep, &varaprojection); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto fail;} fetchprojection = NULL; walkprojection = NULL; if(state == FETCHPART) { /* Create a merge of the url projections and the vara projection */ ncstat = daprestrictprojection(dapcomm->oc.dapconstraint->projections, varaprojection,&fetchprojection); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto fail;} /* Clone the projection for use with the walk */ walkprojection = (DCEprojection*)dceclone((DCEnode*)fetchprojection); /* We might still end up with a whole variable */ if(dceiswholeprojection(fetchprojection)) state = FETCHWHOLE; /* Build the complete constraint to use in the fetch */ fetchconstraint = (DCEconstraint*)dcecreate(CES_CONSTRAINT); /* merged constraint just uses the url constraint selection */ fetchconstraint->selections = dceclonelist(dapcomm->oc.dapconstraint->selections); fetchconstraint->projections = nclistnew(); nclistpush(fetchconstraint->projections,(ncelem)fetchprojection); #ifdef DEBUG fprintf(stderr,"getvarx: fetchconstraint: %s\n",dumpconstraint(fetchconstraint)); #endif /* buildcachenode3 will create a new cachenode and will also fetch the corresponding datadds */ vars = nclistnew(); nclistpush(vars,(ncelem)varainfo->target); ncstat = buildcachenode34(dapcomm,fetchconstraint,vars,&cachenode,0); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto fail;} } else if(state == FETCHWHOLE) { /* buildcachenode3 will create a new cachenode and will also fetch the corresponding datadds */ vars = nclistnew(); nclistpush(vars,(ncelem)varainfo->target); /* Build the complete constraint to use in the fetch */ fetchconstraint = (DCEconstraint*)dcecreate(CES_CONSTRAINT); /* merged constraint just uses the url constraint selection */ fetchconstraint->selections = dceclonelist(dapcomm->oc.dapconstraint->selections); /* Use no projections */ fetchconstraint->projections = nclistnew(); ncstat = buildcachenode34(dapcomm,fetchconstraint,vars,&cachenode,0); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto fail;} } ASSERT(cachenode != NULL); #ifdef DEBUG fprintf(stderr,"cache.datadds=%s\n",dumptree(cachenode->datadds)); #endif /* attach DATADDS to DDS */ unattach34(dapcomm->cdf.ddsroot); ncstat = attachsubset34(cachenode->datadds,dapcomm->cdf.ddsroot); if(ncstat) goto fail; /* Now, walk to the relevant instance */ switch (state) { case FETCHWHOLE: case CACHED: /* Create a merge of the url projections and the vara projection */ ncstat = daprestrictprojection(dapcomm->oc.dapconstraint->projections, varaprojection,&walkprojection); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto fail;} break; case FETCHPART: /* Derive the proper walk projection from the fetchprojection (actually the clone created above) */ ncstat = dapshiftprojection(walkprojection);/*arg will be modified */ if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto fail;} break; default: PANIC("illegal getvarx state"); } #ifdef DEBUG fprintf(stderr,"getvarx: walkprojection: %s\n",dumpprojection(walkprojection)); #endif /* Fix up varainfo to use the cache */ varainfo->cache = cachenode; varainfo->varaprojection = walkprojection; walkprojection = NULL; /* Get the var correlate from the datadds */ target = varainfo->target; /* xtarget is in the datadds space */ xtarget = target->attachment; if(xtarget == NULL) {THROWCHK(ncstat=NC_ENODATA); goto fail;} /* Switch to datadds tree space*/ varainfo->target = xtarget; ncstat = getcontent4(dapcomm,varainfo,cachenode->datadds,data); if(ncstat != OC_NOERR) {THROWCHK(ncstat); goto fail;} goto ok; fail: if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); ok: nclistfree(vars); dcefree((DCEnode*)fetchconstraint); dcefree((DCEnode*)varaprojection); freegetvara(varainfo); return THROW(ncstat); } static NCerror getcontent4(NCDAPCOMMON* dapcomm, Getvara* xgetvar, CDFnode* xroot, void* data) { NCerror ncstat = NC_NOERR; OCerror ocstat = OC_NOERR; NCbytes* memory; size_t alloc; int fieldindex; CDFnode* tnode = xgetvar->target; OCconnection conn = dapcomm->oc.conn; OCdata rootcontent = OCNULL; OCdata fieldcontent = OCNULL; OCdata dimcontent = OCNULL; OCdata seqcontent = OCNULL; OCdata gridcontent = OCNULL; Dapodometer* odom = NULL; OCobject ocroot = OCNULL; int caching = FLAGSET(dapcomm->controls,NCF_CACHE); int unconstrainable = FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE); nc_type externaltype = xgetvar->dsttype; /* is var from a toplevel grid? */ int virtual = tnode->virtual; /* is var a toplevel Sequence? */ int seqvar = daptopseq(tnode); if(seqvar) { alloc = sizeof(nc_vlen_t); } if(tnode->nctype == NC_Primitive) { /* compute the # elements */ size_t nelems = dimproduct3(tnode->array.dimset0); /* Pull the field size from the externaltype. */ alloc = (nctypesizeof(externaltype)*nelems); } else { ASSERT((tnode->attachment != NULL)); /* Pull the field size from the node type size. */ alloc = (size_t)(tnode->attachment->typesize.field.size); } #ifdef READCHECK fprintf(stderr,"getcontent4: |%s| = %lu\n",tnode->name,alloc); #endif memory = ncbytesnew(); ncbytessetcontents(memory,data,alloc); /* Get the root content*/ ocroot = xroot->tree->ocroot; rootcontent = oc_data_new(conn); ocstat = oc_data_root(conn,ocroot,rootcontent); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;} /* Move to the field for this var; handle grid vars separately */ if(virtual) { int gridindex; /* Get index of the grid node wrt to the root node */ gridindex = findfield(xroot,tnode->container); if(gridindex < 0) {ncstat = NC_ENOTVAR; goto fail;} gridcontent = oc_data_new(conn); ocstat = oc_data_ith(conn,rootcontent,gridindex,gridcontent); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;} /* Now move to the relevant grid field */ fieldindex = findfield(tnode->container,tnode); if(fieldindex < 0) {ncstat = NC_ENOTVAR; goto fail;} fieldcontent = oc_data_new(conn); ocstat = oc_data_ith(conn,gridcontent,fieldindex,fieldcontent); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;} } else if(seqvar) { /* Move to the seq data */ int seqindex = findfield(xroot,tnode); if(seqindex < 0) {ncstat = NC_ENOTVAR; goto fail;} seqcontent = oc_data_new(conn); ocstat = oc_data_ith(conn,rootcontent,seqindex,seqcontent); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;} } else { fieldindex = findfield(xroot,tnode); if(fieldindex < 0) {ncstat = NC_ENOTVAR; goto fail;} if(tnode->virtual) { int structindex; /* Get index of the struct node wrt to the root node */ structindex = findfield(xroot,tnode->container); if(structindex < 0) {ncstat = NC_ENOTVAR; goto fail;} /* Get index of the structure field wrt to the virtual struct */ fieldindex = findfield(tnode->container,tnode); if(fieldindex < 0) {ncstat = NC_ENOTVAR; goto fail;} /* Actual field is structindex + fieldindex */ fieldindex += structindex; fieldcontent = oc_data_new(conn); ocstat = oc_data_ith(conn,fieldcontent,fieldindex,fieldcontent); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;} } else { fieldcontent = oc_data_new(conn); ocstat = oc_data_ith(conn,rootcontent,fieldindex,fieldcontent); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;} } } if(seqvar) { ASSERT((seqcontent != OCNULL)); ncstat=getcontent4r(dapcomm,xgetvar,tnode,seqcontent,memory); } else if(tnode->nctype == NC_Primitive) { /* Stride the dimensions and get the instances */ DCEsegment* segment = NULL; ASSERT((nclistlength(xgetvar->varaprojection->var->segments)==1)); segment = (DCEsegment*)nclistget(xgetvar->varaprojection->var->segments,0); ASSERT((fieldcontent != OCNULL)); ncstat = getcontent4prim(dapcomm,xgetvar,tnode,segment,fieldcontent,memory); } else if(nclistlength(tnode->array.dimset0) > 0) { /* Stride the dimensions and get the instances */ DCEsegment* segment = NULL; ASSERT((nclistlength(xgetvar->varaprojection->var->segments)==1)); segment = (DCEsegment*)nclistget(xgetvar->varaprojection->var->segments,0); if(caching || unconstrainable) { odom = newdapodometer(segment->slices,0,segment->rank); } else { /*Since vara was projected out, build a simple odometer*/ odom = newsimpledapodometer(segment,segment->rank); } while(dapodometermore(odom)) { /* Compute which instance to move to*/ unsigned int dimoffset = dapodometercount(odom); dimcontent = oc_data_new(conn); ocstat = oc_data_ith(conn,fieldcontent,dimoffset,dimcontent); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;} ncstat = getcontent4r(dapcomm,xgetvar,tnode,dimcontent,memory); dapodometerincr(odom); } freedapodometer(odom); } else { ncstat=getcontent4r(dapcomm,xgetvar,tnode,fieldcontent,memory); } /*ok:*/ fail: oc_data_free(conn,gridcontent); oc_data_free(conn,seqcontent); oc_data_free(conn,dimcontent); oc_data_free(conn,fieldcontent); oc_data_free(conn,rootcontent); ncbytesfree(memory);/* leaves contents untouched */ if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); return THROW(ncstat); } /* Recursive walker part of getcontent */ static NCerror getcontent4r(NCDAPCOMMON* dapcomm, Getvara* xgetvar, CDFnode* tnode, /* type definition */ OCdata currentcontent, NCbytes* memory) { unsigned int i; OCerror ocstat = OC_NOERR; NCerror ncstat = NC_NOERR; OCmode mode; OCconnection conn = dapcomm->oc.conn; OCdata reccontent = OCNULL; OCdata fieldcontent = OCNULL; OCdata dimcontent = OCNULL; Dapodometer* odom = NULL; NCbytes* vlenmemory = NULL; nc_vlen_t vlenref = {0,NULL}; int caching = FLAGSET(dapcomm->controls,NCF_CACHE); int unconstrainable = FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE); oc_data_mode(conn,currentcontent,&mode); #ifdef READCHECK { int rank = nclistlength(tnode->array.dimset0); fprintf(stderr,"getcontent4r: rank=%lu mode=%d nctype=%s\n", (unsigned long)rank,mode,nctypetostring(tnode->nctype)); } #endif if(tnode->nctype == NC_Primitive) { DCEsegment seg; /* temporary */ seg.name = tnode->ocname; seg.cdfnode = tnode; makewholesegment4(&seg,tnode->array.dimset0); ncstat = getcontent4prim(dapcomm,xgetvar,tnode,&seg,currentcontent,memory); goto done; } if(tnode->virtual) { fprintf(stderr,"VIRTUAL ENCOUNTER\n"); abort(); } switch (mode) { case OCARRAYMODE: { unsigned int rank = nclistlength(tnode->array.dimset0); DCEsegment seg; /* temporary */ ASSERT((tnode->nctype == NC_Structure)); seg.name = tnode->ocname; seg.cdfnode = tnode; makewholesegment4(&seg,tnode->array.dimset0); /* The goal here is to walk the indices (if any) and extract each instance */ ASSERT((rank > 0)); if(caching || unconstrainable) { odom = newdapodometer(seg.slices,0,rank); } else { /*Since vara was projected out, build a simple odometer*/ odom = newsimpledapodometer(&seg,rank); } dimcontent = oc_data_new(conn); while(dapodometermore(odom)) { /* Compute which instance to move to*/ unsigned int dimoffset = dapodometercount(odom); ocstat = oc_data_ith(conn,currentcontent,dimoffset,dimcontent); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;} ncstat = getcontent4r(dapcomm,xgetvar,tnode,dimcontent,memory); } } break; case OCFIELDMODE: /* Walk each field in turn */ /* Align the buffer to struct boundary*/ alignbuffer3(memory,tnode->typesize.instance.alignment); fieldcontent = oc_data_new(conn); for(i=0;isubnodes);i++) { CDFnode* subnode = (CDFnode*)nclistget(tnode->subnodes,i); ocstat = oc_data_ith(conn,currentcontent,i,fieldcontent); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;} ncstat = getcontent4r(dapcomm,xgetvar,subnode,fieldcontent,memory); } break; case OCSEQUENCEMODE: /* Collect the set of records as a separate memory structure */ vlenmemory = ncbytesnew(); ncbytessetalloc(vlenmemory,4096); #ifdef READCHECK fprintf(stderr,"getcontent4r: record: vlenmemory=%lx\n", (unsigned long)ncbytescontents(vlenmemory)); #endif reccontent = oc_data_new(conn); for(i=0;;i++) { ocstat = oc_data_ith(conn,currentcontent,i,reccontent); if(ocstat == OC_EINVALCOORDS) {ocstat=OC_NOERR; break;} /* no more records */ if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;} ncstat = getcontent4r(dapcomm,xgetvar,tnode,reccontent,vlenmemory); } vlenref.len = i; vlenref.p = ncbytesextract(vlenmemory); #ifdef READCHECK fprintf(stderr,"getcontent4r: record: vlen.p=%lx\n", (unsigned long)vlenref.p); #endif /* Now put an nc_vlen_t into our buffer */ alignbuffer3(memory,tnode->typesize.field.alignment); ncbytesappendn(memory,(char*)&vlenref,sizeof(vlenref)); #ifdef READCHECK fprintf(stderr,"getcontent4r: record: memory=%lx |memory|=%lu\n", (unsigned long)ncbytescontents(memory),(unsigned long)ncbyteslength(memory)); #endif break; default: ncstat = NC_EINVAL; {THROWCHK(ncstat); goto fail;} } done: fail: ncbytesfree(vlenmemory); oc_data_free(conn,dimcontent); oc_data_free(conn,fieldcontent); oc_data_free(conn,reccontent); if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); return THROW(ncstat); } static NCerror getcontent4prim(NCDAPCOMMON* dapcomm, Getvara* xgetvar, CDFnode* tnode, DCEsegment* segment, OCdata currentcontent, NCbytes* memory) { OCerror ocstat = OC_NOERR; NCerror ncstat = NC_NOERR; unsigned int rank; OCconnection conn = dapcomm->oc.conn; Dapodometer* odom = NULL; unsigned int memoffset; DCEslice* slices = segment->slices; int caching = FLAGSET(dapcomm->controls,NCF_CACHE); int unconstrainable = FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE); size_t internaltypesize, externaltypesize; nc_type internaltype = segment->cdfnode->etype; nc_type externaltype = xgetvar->dsttype; int bit8type; /* is this an 8 bit type? */ if(externaltype == NC_NAT) externaltype = internaltype; internaltypesize = nctypesizeof(internaltype); externaltypesize = nctypesizeof(externaltype); switch (internaltype) { case NC_CHAR: case NC_BYTE: case NC_UBYTE: bit8type = 1; break; default: bit8type = 0; break; } rank = nclistlength(tnode->array.dimset0); ASSERT((rank == segment->rank)); #ifdef READCHECK fprintf(stderr,"getcontent4prim: tnode=%s/%d segment=%s internaltype=%s externaltype=%s memory=%lx internaltypesize=%lu externaltypesize=%lu\n", tnode->name,rank,dumpsegment(segment), nctypetostring(internaltype),nctypetostring(externaltype), (unsigned long)ncbytescontents(memory), (unsigned long)internaltypesize, (unsigned long)externaltypesize); #endif alignbuffer3(memory,ncctypealignment(externaltype)); /* Align to the proper boundary */ memoffset = ncbyteslength(memory); #ifdef READCHECK fprintf(stderr,"getcontent4prim: alignment=%d memory.after=%lx\n", ncctypealignment(externaltype),(unsigned long)ncbytescontents(memory)); #endif if(rank == 0) { /* singleton data item*/ char value[32]; /* big enough to hold any single primitive value*/ void* memdata; ASSERT((internaltypesize <= sizeof(value))); if(!ncbytessetlength(memory,memoffset+externaltypesize)) return NC_ENOMEM; #ifdef READCHECK fprintf(stderr,"getcontent4prim: scalar: memory=%lx |memory|=%lu\n", (unsigned long)ncbytescontents(memory),(unsigned long)ncbyteslength(memory)); #endif memdata = ncbytescontents(memory)+memoffset; #ifdef READCHECK fprintf(stderr,"getcontent4prim: scalar: memdata=%lx\n",(unsigned long)memdata); #endif ocstat = oc_data_get(conn,currentcontent,value,sizeof(value),0,1); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;} ncstat = ncdap4convert(internaltype,externaltype,memdata,value,1); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto fail;} } else { /* rank > 0 */ size_t requested, arraysize; char* memdata; int contiguous; if(caching || unconstrainable) { odom = newdapodometer(slices,0,rank); } else { odom = newsimpledapodometer(segment,rank); } /* Compute the actual # of values requested by the caller */ requested = dapodometerpoints(odom); if(bit8type && externaltype == NC_STRING) { /* special case */ arraysize = nctypesizeof(NC_STRING); /* allocate a single string */ } else arraysize = externaltypesize*requested; if(!ncbytessetlength(memory,memoffset+arraysize)) return NC_ENOMEM; memdata = ncbytescontents(memory)+memoffset; #ifdef TEST { size_t dimcount; oc_data_count(conn,currentcontent,&dimcount); printf("read: %s: memoffset=%lu externaltypesize=%lu dimcount=%lu requested=%lu arraysize=%lu\n", tnode->name,(unsigned long)memoffset,(unsigned long)externaltypesize, (unsigned long)dimcount,(unsigned long)requested,arraysize); fflush(stdout); } #endif /* Optimize off the use of the odometer by checking the slicing to locate the largest possible suffix of dimensions that represent a contiguous chunk; However do not do this if external type conversion is needed. */ contiguous = contiguousdims(odom); if(contiguous < odom->rank && internaltype == externaltype) { /* Compute the chunk size */ size_t chunkcount; ASSERT((odom->rank != 1 || contiguous == 0)); chunkcount = dapodometerspace(odom,contiguous); if(contiguous == 0) { /* The whole vara slice is usable: read the whole chunk at one shot. */ /* copy the data locally before conversion */ ocstat = oc_data_get(conn,currentcontent,memdata, arraysize,0,chunkcount); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;} } else { /* odom->rank > 1 && contiguous > 0 */ size_t memchunk = (externaltypesize * chunkcount); /* Use the odometer to find each contiguous chunk. */ odom->rank = contiguous; /* move in chunksize chunks */ while(dapodometermore(odom)) { size_t nchunks = dapodometercount(odom); size_t chunkoffset = nchunks * chunkcount; ocstat = oc_data_get(conn,currentcontent,memdata, arraysize,chunkoffset,chunkcount); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;} memdata += memchunk; arraysize -= memchunk; dapodometerincr(odom); } } } else if(bit8type && externaltype == NC_STRING) { /* special case conversion */ char* s = (char*)malloc(requested+1); /* bytes will go into a single string */ char** sp = (char**)memdata; ocstat = oc_data_get(conn,currentcontent,s,requested,0,requested); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;} *sp = s; memdata += externaltypesize; } else { /*Oh well,use the odometer to walk to the appropriate fields*/ char value[32]; /* to hold any value*/ while(dapodometermore(odom)) { size_t dimoffset = dapodometercount(odom); ocstat = oc_data_get(conn,currentcontent,value,sizeof(value),dimoffset,1); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;} ocstat = ncdap4convert(internaltype,externaltype,memdata,value,1); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;} memdata += externaltypesize; dapodometerincr(odom); } } } /*ok:*/ fail: freedapodometer(odom); if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); return THROW(ncstat); } static int findfield(CDFnode* node, CDFnode* subnode) { size_t i; for(i=0;isubnodes);i++) { CDFnode* test = (CDFnode*)nclistget(node->subnodes,i); if(test == subnode) return i; } return -1; } /* Find the largest prefix of n dimensions such that: n .. odom.rank are complete: they have start of 0, stride of 1 and count == dimensions size. */ static int contiguousdims(Dapodometer* odom) { unsigned int i; int mark = 0; if(odom->rank <= 1) return 0; for(i=0;irank;i++) { ASSERT((odom->slices[i].declsize != 0)); if(odom->slices[i].stride != 1 || odom->slices[i].first > 0 || odom->slices[i].length != odom->slices[i].declsize) mark=i; } return mark+1; } static NCerror ncdap4convert(nc_type srctype, nc_type dsttype, char* memory, char* value, size_t count) { NCerror ncstat = NC_NOERR; size_t i; #define CASE(nc1,nc2) (nc1*256+nc2) switch (CASE(srctype,dsttype)) { /* the NC_STRING/URL case is only used by ncdap4 */ case CASE(NC_STRING,NC_STRING): case CASE(NC_STRING,NC_URL): case CASE(NC_URL,NC_STRING): case CASE(NC_URL,NC_URL): for(i=0;itarget; NClist* path = NULL; #ifdef DEBUG fprintf(stderr,"vara: %s\n",getvaraprint(getvar)); #endif if(!getvar->projected) return NC_NOERR; path = nclistnew(); collectnodepath3(target,path,WITHOUTDATASET); if(nclistlength(path) == 0) return NC_NOERR; ncbytesclear(buf); for(dimdex=0,i=0;i0) ncbytescat(buf,"."); /* we are past the first projection*/ ncbytescat(buf,node->name); #ifdef IGNORE if(node->nctype == NC_Sequence) { ASSERT((node->usesequence == 1)); dimdex++; } else if(nclistlength(node->array.dimset0) > 0) { makevarprojection3(getvar->slices,dimdex,nclistlength(node->array.dimset0),buf); dimdex += nclistlength(node->array.dimset0); } #endif } #ifdef DEBUG fprintf(stderr,"projection=|%s|",ncbytescontents(buf)); fflush(stderr); #endif nclistfree(path); return NC_NOERR; } static void makevarprojection3(NCslice* slices, int dimdex, int ndims, NCbytes* buf) { int i; char tmp[1024]; NCslice* slice = slices+dimdex; for(i=0;ifirst, (unsigned long)slice->stride, (unsigned long)(slice->stop - 1)); ncbytescat(buf,tmp); } } #endif static void makewholesegment4(DCEsegment* seg, NClist* dimset) { int i; unsigned int rank; rank = nclistlength(dimset); seg->rank = rank; for(i=0;islices[i],dim->dim.declsize); } seg->slicesdefined = 1; seg->slicesdeclized = 1; }