Dapodometer* newsimpledapodometer(DCEsegment* segment, unsigned int rank) { int i; Dapodometer* odom = (Dapodometer*)calloc(1,sizeof(Dapodometer)); MEMCHECK(odom,NULL); if(rank == 0) { return newdapodometer1(1); } odom->rank = rank; assert(odom->rank <= NC_MAX_VAR_DIMS); assert(segment->slicesdefined && segment->slicesdeclized); for(i=0;i<odom->rank;i++) { DCEslice* odslice = &odom->slices[i]; DCEslice* segslice = &segment->slices[i]; odslice->first = 0; odslice->stride = 1; odslice->declsize = segslice->count; odslice->length = odslice->declsize; odslice->stop = odslice->declsize; odslice->count = odslice->declsize; odom->index[i] = 0; } return odom; }
Dapodometer* newdapodometer(DCEslice* slices, unsigned int first, unsigned int rank) { int i; Dapodometer* odom = (Dapodometer*)calloc(1,sizeof(Dapodometer)); MEMCHECK(odom,NULL); if(rank == 0) { return newdapodometer1(1); } odom->rank = rank; ASSERT(odom->rank <= NC_MAX_VAR_DIMS); for(i=0;i<odom->rank;i++) { DCEslice* slice = slices+(first+i); odom->slices[i] = *slice; odom->index[i] = odom->slices[i].first; } return odom; }
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; }