static NCerror moveto(NCDAPCOMMON* nccomm, Getvara* xgetvar, CDFnode* xrootnode, void* memory) { OCerror ocstat = OC_NOERR; NCerror ncstat = NC_NOERR; OClink conn = nccomm->oc.conn; OCdatanode xrootcontent; OCddsnode ocroot; NClist* path = nclistnew(); struct NCMEMORY memstate; memstate.next = (memstate.memory = memory); /* Get the root content*/ ocroot = xrootnode->tree->ocroot; ocstat = oc_data_getroot(conn,ocroot,&xrootcontent); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto done;} /* Remember: xgetvar->target is in DATADDS tree */ collectnodepath3(xgetvar->target,path,WITHDATASET); ncstat = movetor(nccomm,xrootcontent, path,0,xgetvar,0,&memstate, xgetvar->varaprojection->var->segments); done: nclistfree(path); oc_data_free(conn,xrootcontent); if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); return THROW(ncstat); }
static NCerror movetofield(NCDAPCOMMON* nccomm, OCdatanode currentcontent, NClist* path, int depth, /* depth is position in segment list*/ Getvara* xgetvar, size_t dimindex, /* dimindex is position in xgetvar->slices*/ struct NCMEMORY* memory, NClist* segments) { OCerror ocstat = OC_NOERR; NCerror ncstat = NC_NOERR; size_t fieldindex,gridindex; OClink conn = nccomm->oc.conn; CDFnode* xnode = (CDFnode*)nclistget(path,depth); OCdatanode reccontent = NULL; OCdatanode dimcontent = NULL; OCdatanode fieldcontent = NULL; CDFnode* xnext; int newdepth; /* currentcontent points to the grid/dataset/structure/record instance */ xnext = (CDFnode*)nclistget(path,depth+1); ASSERT((xnext != NULL)); fieldindex = findfield(xnode,xnext); /* If the next node is a nc_virtual node, then we need to effectively ignore it and use the appropriate subnode. If the next node is a re-struct'd node, then use it as is. */ if(xnext->nc_virtual) { CDFnode* xgrid = xnext; xnext = (CDFnode*)nclistget(path,depth+2); /* real node */ gridindex = fieldindex; fieldindex = findfield(xgrid,xnext); fieldindex += gridindex; newdepth = depth+2; } else { newdepth = depth+1; } /* Move to appropriate field */ ocstat = oc_data_ithfield(conn,currentcontent,fieldindex,&fieldcontent); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto done;} ncstat = movetor(nccomm,fieldcontent, path,newdepth,xgetvar,dimindex,memory, segments); done: 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 movetor(NCDAPCOMMON* nccomm, OCdatanode currentcontent, NClist* path, int depth, /* depth is position in segment list*/ Getvara* xgetvar, size_t dimindex, /* dimindex is position in xgetvar->slices*/ struct NCMEMORY* memory, NClist* segments) { OCerror ocstat = OC_NOERR; NCerror ncstat = NC_NOERR; OClink conn = nccomm->oc.conn; CDFnode* xnode = (CDFnode*)nclistget(path,depth); OCdatanode reccontent = NULL; OCdatanode dimcontent = NULL; OCdatanode fieldcontent = NULL; Dapodometer* odom = NULL; int hasstringdim = 0; DCEsegment* segment; OCDT mode; /* Note that we use depth-1 because the path contains the DATASET but the segment list does not */ segment = (DCEsegment*)nclistget(segments,depth-1); /*may be NULL*/ if(xnode->etype == NC_STRING || xnode->etype == NC_URL) hasstringdim = 1; /* Get the mode */ mode = oc_data_mode(conn,currentcontent); #ifdef DEBUG2 fprintf(stderr,"moveto: nctype=%d depth=%d dimindex=%d mode=%s", xnode->nctype, depth,dimindex,oc_data_modestring(mode)); fprintf(stderr," segment=%s hasstringdim=%d\n", dcetostring((DCEnode*)segment),hasstringdim); #endif switch (xnode->nctype) { #if 0 #define OCDT_FIELD ((OCDT)(1)) /* field of a container */ #define OCDT_ELEMENT ((OCDT)(2)) /* element of a structure array */ #define OCDT_RECORD ((OCDT)(4)) /* record of a sequence */ #define OCDT_ARRAY ((OCDT)(8)) /* is structure array */ #define OCDT_SEQUENCE ((OCDT)(16)) /* is sequence */ #define OCDT_ATOMIC ((OCDT)(32)) /* is atomic leaf */ #endif default: goto done; case NC_Grid: case NC_Dataset: case NC_Structure: /* Separate out the case where structure is dimensioned */ if(oc_data_indexable(conn,currentcontent)) { /* => dimensioned structure */ /* The current segment should reflect the proper parts of the nc_get_vara argument */ /* Create odometer for this structure's part of the projection */ odom = dapodom_fromsegment(segment,0,segment->rank); while(dapodom_more(odom)) { /* Compute which instance to move to*/ ocstat = oc_data_ithelement(conn,currentcontent, odom->index,&dimcontent); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto done;} ASSERT(oc_data_indexed(conn,dimcontent)); ncstat = movetor(nccomm,dimcontent, path,depth,/*keep same depth*/ xgetvar,dimindex+segment->rank, memory,segments); dapodom_next(odom); } dapodom_free(odom); } else {/* scalar instance */ ncstat = movetofield(nccomm,currentcontent,path,depth,xgetvar,dimindex,memory,segments); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto done;} } break; case NC_Sequence: if(fIsSet(mode,OCDT_SEQUENCE)) { ASSERT((xnode->attachment != NULL)); ASSERT((segment != NULL)); ASSERT((segment->rank == 1)); /* Build an odometer for walking the sequence, however, watch out for the case when the user set a limit and that limit is not actually reached in this request. */ /* By construction, this sequence represents the first (and only) dimension of this segment */ odom = dapodom_fromsegment(segment,0,1); while(dapodom_more(odom)) { size_t recordindex = dapodom_count(odom); ocstat = oc_data_ithrecord(conn,currentcontent, recordindex,&reccontent); if(ocstat != OC_NOERR) { if(ocstat == OC_EINDEX) ocstat = OC_EINVALCOORDS; THROWCHK(ocstat); goto done; } ncstat = movetor(nccomm,reccontent, path,depth, xgetvar,dimindex+1, memory,segments); if(ncstat != OC_NOERR) {THROWCHK(ncstat); goto done;} dapodom_next(odom); } } else if(fIsSet(mode,OCDT_RECORD)) { /* Treat like structure */ /* currentcontent points to the record instance */ ncstat = movetofield(nccomm,currentcontent,path,depth,xgetvar,dimindex,memory,segments); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto done;} } break; case NC_Atomic: if(hasstringdim) ncstat = extractstring(nccomm, xgetvar, xnode, segment, dimindex, conn, currentcontent, memory); else ncstat = extract(nccomm, xgetvar, xnode, segment, dimindex, conn, currentcontent, memory); break; } done: 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 movetor(NCDAPCOMMON* nccomm, OCdata currentcontent, NClist* path, int depth, /* depth is position in segment list*/ Getvara* xgetvar, int dimindex, /* dimindex is position in xgetvar->slices*/ struct NCMEMORY* memory, NClist* segments) { int i; OCerror ocstat = OC_NOERR; NCerror ncstat = NC_NOERR; size_t fieldindex,gridindex,rank; OCconnection conn = nccomm->oc.conn; CDFnode* xnode = (CDFnode*)nclistget(path,depth); OCdata reccontent = OCNULL; OCdata dimcontent = OCNULL; OCdata fieldcontent = OCNULL; Dapodometer* odom = OCNULL; OCmode currentmode = OCNULLMODE; CDFnode* xnext; int hasstringdim = 0; size_t dimoffset; DCEsegment* segment; int newdepth; int caching = FLAGSET(nccomm->controls,NCF_CACHE); int unconstrainable = FLAGSET(nccomm->controls,NCF_UNCONSTRAINABLE); /* Note that we use depth-1 because the path contains the DATASET but the segment list does not */ segment = (DCEsegment*)nclistget(segments,depth-1); /*may be NULL*/ if(xnode->etype == NC_STRING || xnode->etype == NC_URL) hasstringdim = 1; ocstat = oc_data_mode(conn,currentcontent,¤tmode); #ifdef DEBUG2 fprintf(stderr,"moveto: nctype=%d currentmode=%d depth=%d dimindex=%d", xnode->nctype, currentmode, depth,dimindex); fprintf(stderr," segment=%s hasstringdim=%d\n", dcetostring((DCEnode*)segment),hasstringdim); #endif /* Switch on the combination of nctype and mode */ #define CASE(nc1,nc2) (nc1*1024+nc2) /* This must be consistent with the oc mode transition function */ switch (CASE(xnode->nctype,currentmode)) { default: PANIC2("Illegal combination: nctype=%d mode=%d", (int)xnode->nctype,(int)currentmode); break; case CASE(NC_Sequence,OCFIELDMODE): case CASE(NC_Dataset,OCFIELDMODE): case CASE(NC_Grid,OCFIELDMODE): case CASE(NC_Structure,OCFIELDMODE): /* currentcontent points to the grid/dataset/structure instance */ xnext = (CDFnode*)nclistget(path,depth+1); ASSERT((xnext != NULL)); fieldindex = findfield(xnode,xnext); /* If the next node is a virtual node, then we need to effectively ignore it and use the appropriate subnode. If the next node is a structuregrid node, then use it as is. */ if(xnext->virtual) { CDFnode* xgrid = xnext; xnext = (CDFnode*)nclistget(path,depth+2); /* real node */ gridindex = fieldindex; fieldindex = findfield(xgrid,xnext); fieldindex += gridindex; newdepth = depth+2; } else { newdepth = depth+1; } fieldcontent = oc_data_new(conn); ocstat = oc_data_ith(conn,currentcontent,fieldindex,fieldcontent); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;} ncstat = movetor(nccomm,fieldcontent, path,newdepth,xgetvar,dimindex,memory, segments); break; case CASE(NC_Sequence,OCARRAYMODE): /* will actually always be scalar, but will have rank == 1 to account for the sequence dim */ case CASE(NC_Grid,OCARRAYMODE): /* will actually always be scalar */ case CASE(NC_Structure,OCARRAYMODE): /* figure out which slices refer to this node: dimindex upto dimindex+rank; */ ASSERT((segment != NULL)); rank = segment->rank; if(xnode->nctype == NC_Sequence) rank--; /* ignore the sequence dim */ if(rank == 0) { odom = newdapodometer1(1); } else if(caching || unconstrainable) { odom = newdapodometer(segment->slices,0,rank); } else { /*Since vara was projected out, build a simple odometer*/ odom = newsimpledapodometer(segment,rank); } while(dapodometermore(odom)) { OCmode mode; /* Compute which instance to move to*/ dimoffset = dapodometercount(odom); dimcontent = oc_data_new(conn); ocstat = oc_data_ith(conn,currentcontent,dimoffset,dimcontent); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;} ocstat = oc_data_mode(conn,dimcontent,&mode); ASSERT((mode == OCFIELDMODE || (mode == OCSEQUENCEMODE && xnode->nctype == NC_Sequence))); ncstat = movetor(nccomm,dimcontent, path,depth, xgetvar,dimindex+rank, memory,segments); dapodometerincr(odom); } freedapodometer(odom); break; case CASE(NC_Sequence,OCSEQUENCEMODE): { DCEslice* uslice; ASSERT((segment != NULL)); /* Get and check the corresponding sequence dimension from DDS */ ASSERT((xnode->attachment != NULL)); /* use uslice to walk the sequence; however, watch out for the case when the user set a limit and that limit is not actually reached in this request. */ /* By construction, this sequence represents the first (and only) dimension of this segment */ uslice = &segment->slices[0]; reccontent = oc_data_new(conn); for(i=uslice->first;i<uslice->stop;i+=uslice->stride) { OCmode eos; ocstat = oc_data_ith(conn,currentcontent,i,reccontent); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;} ocstat = oc_data_mode(conn,reccontent,&eos); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;} if(eos == OCNULLMODE) { /* We asked for too much */ ncstat = THROW(NC_EINVALCOORDS); goto fail; } ncstat = movetor(nccomm,reccontent, path,depth, xgetvar,dimindex+1, memory,segments); if(ncstat != OC_NOERR) {THROWCHK(ncstat); goto fail;} } } break; case CASE(NC_Primitive,OCPRIMITIVEMODE): if(hasstringdim) ncstat = extractstring(nccomm, xgetvar, xnode, segment, conn, currentcontent, memory); else ncstat = extract(nccomm, xgetvar, xnode, segment, conn, currentcontent, memory); break; }