/* convert all names in selections to be fully qualified */ static NCerror qualifyselectionnames3(DCEselection* sel) { NCerror ncstat = NC_NOERR; int i; NClist* segments = NULL; NClist* fullpath = nclistnew(); ASSERT(sel->lhs->discrim == CES_VAR); collectnodepath3((CDFnode*)sel->lhs->var->annotation,fullpath,!WITHDATASET); #ifdef DEBUG fprintf(stderr,"qualify.sel: %s -> ", dumpselection(sel)); #endif /* Now add path nodes to create full path */ completesegments3(fullpath,sel->lhs->var->segments); for(i=0;i<nclistlength(sel->rhs);i++) { DCEvalue* value = (DCEvalue*)nclistget(sel->rhs,i); if(value->discrim != CES_VAR) continue; nclistclear(fullpath); collectnodepath3((CDFnode*)value->var->annotation,fullpath,!WITHDATASET); completesegments3(fullpath,value->var->segments); } nclistfree(segments); nclistfree(fullpath); return THROW(ncstat); }
static char* getdefinename(CDFnode* node) { char* spath = NULL; NClist* path = NULL; switch (node->nctype) { case NC_Primitive: /* The define name is same as the fullname with elided nodes */ path = nclistnew(); collectnodepath3(node,path,!WITHDATASET); spath = makepathstring3(path,".",PATHNC|PATHELIDE); nclistfree(path); break; case NC_Dimension: /* Return just the node's ncname */ spath = nulldup(node->ncbasename); break; default: PANIC("unexpected nctype"); } return spath; }
/* Suppress variables not in usable sequences*/ NCerror suppressunusablevars3(NCDAPCOMMON* dapcomm) { int i,j; int found = 1; NClist* path = nclistnew(); while(found) { found = 0; /* Walk backwards to aid removal semantics */ for(i=nclistlength(dapcomm->cdf.ddsroot->tree->varnodes)-1;i>=0;i--) { CDFnode* var = (CDFnode*)nclistget(dapcomm->cdf.ddsroot->tree->varnodes,i); /* See if this var is under an unusable sequence */ nclistclear(path); collectnodepath3(var,path,WITHOUTDATASET); for(j=0;j<nclistlength(path);j++) { CDFnode* node = (CDFnode*)nclistget(path,j); if(node->nctype == NC_Sequence && !node->usesequence) { #ifdef DEBUG fprintf(stderr,"suppressing var in unusable sequence: %s.%s\n",node->ncfullname,var->ncbasename); #endif found = 1; break; } } if(found) break; } if(found) nclistremove(dapcomm->cdf.ddsroot->tree->varnodes,i); } nclistfree(path); return NC_NOERR; }
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 fillsegmentpath(DCEprojection* p, NClist* nodes) { int i; NCerror ncstat = NC_NOERR; NClist* path = nclistnew(); ASSERT(p->discrim == CES_VAR); collectsegmentnames3(p->var->segments,path); ncstat = matchpartialname3(nodes,path,&p->var->cdfleaf); if(ncstat) goto done; /* Now complete the segment path */ nclistclear(path); collectnodepath3(p->var->cdfleaf,path,!WITHDATASET); if(nclistlength(path) != nclistlength(p->var->segments)) { ncstat = NC_EINVAL; goto done; } for(i=0;i<nclistlength(p->var->segments);i++) { DCEsegment* seg = (DCEsegment*)nclistget(p->var->segments,i); CDFnode* node = (CDFnode*)nclistget(path,i); seg->cdfnode = node; #ifdef DEBUG fprintf(stderr,"reref: %s -> %s\n",seg->name,node->name); #endif } done: nclistfree(path); return ncstat; }
NCerror showprojection3(NCDAPCOMMON* dapcomm, CDFnode* var) { int i,rank; NCerror ncstat = NC_NOERR; NCbytes* projection = ncbytesnew(); NClist* path = nclistnew(); NC* drno = dapcomm->controller; /* Collect the set of DDS node name forming the xpath */ collectnodepath3(var,path,WITHOUTDATASET); for(i=0;i<nclistlength(path);i++) { CDFnode* node = (CDFnode*)nclistget(path,i); if(i > 0) ncbytescat(projection,"."); ncbytescat(projection,node->ocname); } /* Now, add the dimension info */ rank = nclistlength(var->array.dimset0); for(i=0;i<rank;i++) { CDFnode* dim = (CDFnode*)nclistget(var->array.dimset0,i); char tmp[32]; ncbytescat(projection,"["); snprintf(tmp,sizeof(tmp),"%lu",(unsigned long)dim->dim.declsize); ncbytescat(projection,tmp); ncbytescat(projection,"]"); } /* Define the attribute */ ncstat = nc_put_att_text(getncid(drno),var->ncid, "_projection", ncbyteslength(projection), ncbytescontents(projection)); return ncstat; }
/* Convert a CDFnode var to a projection; include pseudodimensions; always whole variable. */ int dapvar2projection(CDFnode* var, DCEprojection** projectionp) { int i,j; int ncstat = NC_NOERR; NClist* path = nclistnew(); NClist* segments; DCEprojection* projection = NULL; int dimindex; /* Collect the nodes needed to construct the projection segment */ collectnodepath3(var,path,!WITHDATASET); segments = nclistnew(); dimindex = 0; /* point to next subset of slices */ nclistsetalloc(segments,nclistlength(path)); for(i=0;i<nclistlength(path);i++) { DCEsegment* segment = (DCEsegment*)dcecreate(CES_SEGMENT); CDFnode* n = (CDFnode*)nclistget(path,i); int localrank; NClist* dimset; segment->annotation = (void*)n; segment->name = nulldup(n->ocname); /* We need to assign whole slices to each segment */ localrank = nclistlength(n->array.dimsetplus); segment->rank = localrank; dimset = n->array.dimsetplus; for(j=0;j<localrank;j++) { DCEslice* slice; CDFnode* dim; slice = &segment->slices[j]; dim = (CDFnode*)nclistget(dimset,j); ASSERT(dim->dim.declsize0 > 0); dcemakewholeslice(slice,dim->dim.declsize0); } segment->slicesdefined = 1; segment->slicesdeclized = 1; dimindex += localrank; nclistpush(segments,(ncelem)segment); } projection = (DCEprojection*)dcecreate(CES_PROJECT); projection->discrim = CES_VAR; projection->var = (DCEvar*)dcecreate(CES_VAR); projection->var->annotation = (void*)var; projection->var->segments = segments; #ifdef DEBUG1 fprintf(stderr,"dapvar2projection: projection=%s\n", dumpprojection(projection)); #endif nclistfree(path); if(ncstat) dcefree((DCEnode*)projection); else if(projectionp) *projectionp = projection; return ncstat; }
static NCerror computeseqcountconstraints3(NCDAPCOMMON* dapcomm, CDFnode* seq, NCbytes* seqcountconstraints) { int i,j; NClist* path = NULL; CDFnode* var = NULL; ASSERT(seq->nctype == NC_Sequence); computeseqcountconstraints3r(dapcomm,seq,&var); ASSERT((var != NULL)); /* Compute var path */ path = nclistnew(); collectnodepath3(var,path,WITHOUTDATASET); /* construct the projection path using minimal index values */ for(i=0;i<nclistlength(path);i++) { CDFnode* node = (CDFnode*)nclistget(path,i); if(i > 0) ncbytescat(seqcountconstraints,"."); ncbytescat(seqcountconstraints,node->ocname); if(node == seq) { /* Use the limit */ if(node->sequencelimit > 0) { char tmp[64]; snprintf(tmp,sizeof(tmp),"[0:%lu]", (unsigned long)(node->sequencelimit - 1)); ncbytescat(seqcountconstraints,tmp); } } else if(nclistlength(node->array.dimset0) > 0) { int ndims = nclistlength(node->array.dimset0); for(j=0;j<ndims;j++) { CDFnode* dim = (CDFnode*)nclistget(node->array.dimset0,j); if(DIMFLAG(dim,CDFDIMSTRING)) { ASSERT((j == (ndims - 1))); break; } ncbytescat(seqcountconstraints,"[0]"); } } } /* Finally, add in any selection from the original URL */ if(dapcomm->oc.url->selection != NULL) ncbytescat(seqcountconstraints,dapcomm->oc.url->selection); nclistfree(path); return NC_NOERR; }
char* dumppath(CDFnode* leaf) { NClist* path = nclistnew(); NCbytes* buf = ncbytesnew(); char* result; int i; if(leaf == NULL) return nulldup(""); collectnodepath3(leaf,path,!WITHDATASET); for(i=0;i<nclistlength(path);i++) { CDFnode* node = (CDFnode*)nclistget(path,i); if(i > 0) ncbytescat(buf,"."); ncbytescat(buf,node->name); } result = ncbytesdup(buf); ncbytesfree(buf); nclistfree(path); return result; }
/* convert all names in projections in paths to be fully qualified by adding prefix segment objects. */ static NCerror qualifyprojectionnames3(DCEprojection* proj) { NCerror ncstat = NC_NOERR; NClist* fullpath = nclistnew(); ASSERT((proj->discrim == CES_VAR && proj->var->annotation != NULL && ((CDFnode*)proj->var->annotation)->ocnode != OCNULL)); collectnodepath3((CDFnode*)proj->var->annotation,fullpath,!WITHDATASET); #ifdef DEBUG fprintf(stderr,"qualify: %s -> ", dumpprojection(proj)); #endif /* Now add path nodes to create full path */ completesegments3(fullpath,proj->var->segments); #ifdef DEBUG fprintf(stderr,"%s\n", dumpprojection(proj)); #endif nclistfree(fullpath); return ncstat; }
NCerror fixprojections(NClist* list) { int i,j,k; NCerror ncstat = NC_NOERR; NClist* tmp = nclistnew(); /* misc. uses */ #ifdef DEBUG fprintf(stderr,"fixprojection: list = %s\n",dumpprojections(list)); #endif if(nclistlength(list) == 0) goto done; /* Step 1: remove duplicates and complain about slice mismatches */ for(i=0;i<nclistlength(list);i++) { DCEprojection* p1 = (DCEprojection*)nclistget(list,i); if(p1 == NULL) continue; if(p1->discrim != CES_VAR) continue; /* dont try to unify functions */ for(j=i;j<nclistlength(list);j++) { DCEprojection* p2 = (DCEprojection*)nclistget(list,j); if(p2 == NULL) continue; if(p1 == p2) continue; if(p2->discrim != CES_VAR) continue; if(p1->var->annotation != p2->var->annotation) continue; /* check for slice mismatches */ if(!slicematch(p1->var->segments,p2->var->segments)) { /* complain */ nclog(NCLOGWARN,"Malformed projection: same variable with different slicing"); } /* remove p32 */ nclistset(list,j,(ncelem)NULL); dcefree((DCEnode*)p2); } } /* Step 2: remove containers when a field is also present */ for(i=0;i<nclistlength(list);i++) { DCEprojection* p1 = (DCEprojection*)nclistget(list,i); if(p1 == NULL) continue; if(p1->discrim != CES_VAR) continue; /* dont try to unify functions */ if(!iscontainer((CDFnode*)p1->var->annotation)) continue; for(j=i;j<nclistlength(list);j++) { DCEprojection* p2 = (DCEprojection*)nclistget(list,j); if(p2 == NULL) continue; if(p2->discrim != CES_VAR) continue; nclistclear(tmp); collectnodepath3((CDFnode*)p2->var->annotation,tmp,WITHDATASET); for(k=0;k<nclistlength(tmp);k++) { void* candidate = (void*)nclistget(tmp,k); if(candidate == p1->var->annotation) { nclistset(list,i,(ncelem)NULL); dcefree((DCEnode*)p1); goto next; } } } next: continue; } /* Step 3: expand all containers recursively down to the leaf nodes */ for(;;) { nclistclear(tmp); for(i=0;i<nclistlength(list);i++) { DCEprojection* target = (DCEprojection*)nclistget(list,i); CDFnode* leaf; if(target == NULL) continue; if(target->discrim != CES_VAR) continue; /* dont try to unify functions */ leaf = (CDFnode*)target->var->annotation; ASSERT(leaf != NULL); if(iscontainer(leaf)) {/* capture container */ if(!nclistcontains(tmp,(ncelem)target)) nclistpush(tmp,(ncelem)target); nclistset(list,i,(ncelem)NULL); } } if(nclistlength(tmp) == 0) break; /*done*/ /* Now explode the containers */ for(i=0;i<nclistlength(tmp);i++) { DCEprojection* container = (DCEprojection*)nclistget(tmp,i); CDFnode* leaf = (CDFnode*)container->var->annotation; for(j=0;i<nclistlength(leaf->subnodes);j++) { CDFnode* field = (CDFnode*)nclistget(leaf->subnodes,j); /* Convert field node to a proper constraint */ DCEprojection* proj = projectify(field,container); nclistpush(list,(ncelem)proj); } /* reclaim the container */ dcefree((DCEnode*)container); } } /*for(;;)*/ /* remove all NULL elements */ for(i=nclistlength(list)-1;i>=0;i--) { DCEprojection* target = (DCEprojection*)nclistget(list,i); if(target == NULL) nclistremove(list,i); } done: #ifdef DEBUG fprintf(stderr,"fixprojection: exploded = %s\n",dumpprojections(list)); #endif nclistfree(tmp); return ncstat; }
static NCerror matchpartialname3(NClist* nodes, NClist* segments, CDFnode** nodep) { int i,nsegs; NCerror ncstat = NC_NOERR; DCEsegment* lastseg = NULL; NClist* namematches = nclistnew(); NClist* matches = nclistnew(); NClist* matchpath = nclistnew(); /* Locate all nodes with the same name as the last element in the segment path */ nsegs = nclistlength(segments); lastseg = (DCEsegment*)nclistget(segments,nsegs-1); for(i=0;i<nclistlength(nodes);i++) { CDFnode* node = (CDFnode*)nclistget(nodes,i); if(node->ocname == null) continue; /* Path names come from oc space */ if(strcmp(node->ocname,lastseg->name) != 0) continue; /* Only look at selected kinds of nodes */ if(node->nctype != NC_Sequence && node->nctype != NC_Structure && node->nctype != NC_Grid && node->nctype != NC_Primitive ) continue; nclistpush(namematches,(ncelem)node); } if(nclistlength(namematches)==0) { nclog(NCLOGERR,"No match for projection name: %s",lastseg->name); ncstat = NC_EDDS; goto done; } /* Now, collect and compare paths of the matching nodes */ for(i=0;i<nclistlength(namematches);i++) { CDFnode* matchnode = (CDFnode*)nclistget(namematches,i); nclistclear(matchpath); collectnodepath3(matchnode,matchpath,0); /* Do a suffix match */ if(matchsuffix3(matchpath,segments)) { nclistpush(matches,(ncelem)matchnode); #ifdef DEBUG fprintf(stderr,"matchpartialname: pathmatch: %s :: %s\n", matchnode->ncfullname,dumpsegments(segments)); #endif } } /* |matches|==0 => no match; |matches|>1 => ambiguity */ switch (nclistlength(matches)) { case 0: nclog(NCLOGERR,"No match for projection name: %s",lastseg->name); ncstat = NC_EDDS; break; case 1: if(nodep) *nodep = (CDFnode*)nclistget(matches,0); break; default: { CDFnode* minnode = NULL; int minpath = 0; int nmin = 0; /* to catch multiple ones with same short path */ /* ok, see if one of the matches has a path that is shorter then all the others */ for(i=0;i<nclistlength(matches);i++) { CDFnode* candidate = (CDFnode*)nclistget(matches,i); nclistclear(matchpath); collectnodepath3(candidate,matchpath,0); if(minpath == 0) { minpath = nclistlength(matchpath); minnode = candidate; } else if(nclistlength(matchpath) == minpath) { nmin++; } else if(nclistlength(matchpath) < minpath) { minpath = nclistlength(matchpath); minnode = candidate; nmin = 1; } } /*for*/ if(minnode == NULL || nmin > 1) { nclog(NCLOGERR,"Ambiguous match for projection name: %s", lastseg->name); ncstat = NC_EDDS; } else if(nodep) *nodep = minnode; } break; } #ifdef DEBUG fprintf(stderr,"matchpartialname: choice: %s %s for %s\n", (nclistlength(matches) > 1?"":"forced"), (*nodep)->ncfullname,dumpsegments(segments)); #endif done: return THROW(ncstat); }
NCerror buildvaraprojection3(Getvara* getvar, const size_t* startp, const size_t* countp, const ptrdiff_t* stridep, DCEprojection** projectionp) { int i,j; int ncrank; NCerror ncstat = NC_NOERR; CDFnode* var = getvar->target; NClist* vardims = var->array.dimensions; DCEprojection* projection = NULL; NClist* path = nclistnew(); NClist* segments = NULL; int dimindex; NClist* dimset = NULL; /* Collect the nodes needed to construct the projection segment */ collectnodepath3(var,path,!WITHDATASET); dimset = var->array.dimensions; ncrank = nclistlength(dimset); segments = nclistnew(); nclistsetalloc(segments,nclistlength(path)); for(i=0;i<nclistlength(path);i++) { DCEsegment* segment = (DCEsegment*)dcecreate(CES_SEGMENT); CDFnode* n = (CDFnode*)nclistget(path,i); segment->cdfnode = n; ASSERT((segment->cdfnode != NULL)); segment->name = nulldup(n->name); segment->slicesdefined = 0; /* temporary */ segment->slicesdeclized = 0; /* temporary */ nclistpush(segments,(ncelem)segment); } projection = (DCEprojection*)dcecreate(CES_PROJECT); projection->discrim = CES_VAR; projection->var = (DCEvar*)dcecreate(CES_VAR); projection->var->cdfleaf = var; projection->var->segments = segments; /* We need to assign slices to each segment */ dimindex = 0; /* point to next subset of slices */ for(i=0;i<nclistlength(segments);i++) { DCEsegment* segment = (DCEsegment*)nclistget(segments,i); int localrank = nclistlength(segment->cdfnode->array.dimensions0); if(segment->cdfnode->array.stringdim != NULL) localrank++; if(segment->cdfnode->array.seqdim != NULL) localrank++; segment->rank = localrank; for(j=0;j<localrank;j++) { DCEslice* slice = &segment->slices[j]; CDFnode* dim = (CDFnode*)nclistget(vardims,dimindex+j); slice->first = startp[dimindex+j]; slice->stride = stridep[dimindex+j]; slice->count = countp[dimindex+j]; slice->length = slice->count * slice->stride; if(slice->length > dim->dim.declsize) slice->length = dim->dim.declsize; slice->stop = (slice->first + slice->length); if(slice->stop > dim->dim.declsize) slice->stop = dim->dim.declsize; slice->declsize = dim->dim.declsize; } segment->slicesdefined = 1; segment->slicesdeclized = 1; dimindex += localrank; ASSERT((dimindex <= ncrank)); } ASSERT((dimindex == ncrank)); if(projectionp) *projectionp = projection; nclistfree(path); if(ncstat) dcefree((DCEnode*)projection); return ncstat; }
void restrictprojection34(NClist* varlist, NClist* projections) { int i,j,len; #ifdef DEBUG fprintf(stderr,"restriction.before=|%s|\n", dumpprojections(projections)); #endif if(nclistlength(varlist) == 0) goto done; /* nothing to add or remove */ /* If the projection list is empty, then add a projection for every variable in varlist */ if(nclistlength(projections) == 0) { NClist* path = nclistnew(); NClist* nodeset = NULL; /* Attempt to unify the vars into larger units (like a complete grid) */ nodeset = unifyprojectionnodes3(varlist); for(i=0;i<nclistlength(nodeset);i++) { CDFnode* var = (CDFnode*)nclistget(nodeset,i); #ifdef DEBUG fprintf(stderr,"restriction.candidate=|%s|\n",var->ncfullname); #endif DCEprojection* newp = (DCEprojection*)dcecreate(CES_PROJECT); newp->discrim = CES_VAR; newp->var = (DCEvar*)dcecreate(CES_VAR); newp->var->cdfleaf = var; nclistclear(path); collectnodepath3(var,path,!WITHDATASET); newp->var->segments = nclistnew(); for(j=0;j<nclistlength(path);j++) { CDFnode* node = (CDFnode*)nclistget(path,j); DCEsegment* newseg = (DCEsegment*)dcecreate(CES_SEGMENT); newseg->name = nulldup(node->name); makewholesegment3(newseg,node);/*treat as simple projections*/ newseg->cdfnode = node; nclistpush(newp->var->segments,(ncelem)newseg); } nclistpush(projections,(ncelem)newp); } nclistfree(path); nclistfree(nodeset); } else { /* Otherwise, walk all the projections and see if they intersect any of the variables. If not, then remove from the projection list. */ len = nclistlength(projections); for(i=len-1;i>=0;i--) {/* Walk backward to facilitate removal*/ int intersect = 0; DCEprojection* proj = (DCEprojection*)nclistget(projections,i); if(proj->discrim != CES_VAR) continue; for(j=0;j<nclistlength(varlist);j++) { CDFnode* var = (CDFnode*)nclistget(varlist,j); /* Note that intersection could go either way */ if(treecontains3(var,proj->var->cdfleaf) || treecontains3(proj->var->cdfleaf,var)) {intersect = 1; break;} } if(!intersect) { /* suppress this projection */ DCEprojection* p = (DCEprojection*)nclistremove(projections,i); dcefree((DCEnode*)p); } } /* Now looks for containment between projections and only keep the more restrictive. Is this algorithm stable against reordering?. */ for(;;) { int removed = 0; for(i=0;i<nclistlength(projections);i++) { DCEprojection* pi = (DCEprojection*)nclistget(projections,i); if(pi->discrim != CES_VAR) continue; for(j=0;j<i;j++) { DCEprojection* pj = (DCEprojection*)nclistget(projections,j); if(pj->discrim != CES_VAR) continue; if(treecontains3(pi->var->cdfleaf,pj->var->cdfleaf)) { DCEprojection* p = (DCEprojection*)nclistremove(projections,j); dcefree((DCEnode*)p); removed = 1; break; } else if(treecontains3(pj->var->cdfleaf,pi->var->cdfleaf)) { DCEprojection* p = (DCEprojection*)nclistremove(projections,i); dcefree((DCEnode*)p); removed = 1; break; } } } if(!removed) break; } } done: #ifdef DEBUG fprintf(stderr,"restriction.after=|%s|\n", dumpprojections(projections)); #endif return; }
static NCerror matchpartialname3(NClist* nodes, NClist* segments, CDFnode** nodep) { int i,j,nsegs; NCerror ncstat = NC_NOERR; DCEsegment* lastseg = NULL; NClist* namematches = nclistnew(); NClist* matches = nclistnew(); NClist* matchpath = nclistnew(); /* Locate all nodes with the same name as the last element in the path */ nsegs = nclistlength(segments); lastseg = (DCEsegment*)nclistget(segments,nsegs-1); for(i=0;i<nclistlength(nodes);i++) { CDFnode* node = (CDFnode*)nclistget(nodes,i); if(node->nctype != NC_Sequence && node->nctype != NC_Structure && node->nctype != NC_Grid && node->nctype != NC_Primitive ) continue; if(strcmp(node->name,lastseg->name) != 0) continue; nclistpush(namematches,(ncelem)node); } if(nclistlength(namematches)==0) { nclog(NCLOGERR,"No match for projection name: %s",lastseg->name); ncstat = NC_EDDS; goto done; } /* Now, collect and compare paths of the matching nodes */ for(i=0;i<nclistlength(namematches);i++) { CDFnode* matchnode = (CDFnode*)nclistget(namematches,i); nclistclear(matchpath); collectnodepath3(matchnode,matchpath,0); /* Do a suffix match */ /* starting at each node in matchpath in the path in turn, try to suffix match */ for(j=0;j<nclistlength(matchpath);j++) { if(nclistlength(matchpath)- j < nsegs) continue; /* cannot match */ if(matchsuffix3(matchpath,segments,j)) { nclistpush(matches,(ncelem)matchnode); break; } } } /* |matches|==0 => no match; |matches|>1 => ambiguity */ switch (nclistlength(matches)) { case 0: nclog(NCLOGERR,"No match for projection name: %s",lastseg->name); ncstat = NC_EDDS; break; case 1: if(nodep) *nodep = (CDFnode*)nclistget(matches,0); break; default: { CDFnode* minnode = NULL; int minpath = 0; int nmin = 0; /* to catch multiple ones with same short path */ /* ok, see if one of the matches has a path that is shorter then all the others */ for(i=0;i<nclistlength(matches);i++) { CDFnode* candidate = (CDFnode*)nclistget(matches,i); nclistclear(matchpath); collectnodepath3(candidate,matchpath,0); if(minpath == 0) { minpath = nclistlength(matchpath); minnode = candidate; } else if(nclistlength(matchpath) == minpath) { nmin++; } else if(nclistlength(matchpath) < minpath) { minpath = nclistlength(matchpath); minnode = candidate; nmin = 1; } } /*for*/ if(minnode == NULL || nmin > 1) { nclog(NCLOGERR,"Ambiguous match for projection name: %s", lastseg->name); ncstat = NC_EDDS; } else if(nodep) *nodep = minnode; } break; } done: return THROW(ncstat); }
static NCerror countsequence(NCDAPCOMMON* dapcomm, CDFnode* xseq, size_t* sizep) { unsigned int i; NClist* path = nclistnew(); int index; OCerror ocstat = OC_NOERR; NCerror ncstat = NC_NOERR; OClink conn = dapcomm->oc.conn; size_t recordcount; CDFnode* xroot; OCdatanode data = NULL; ASSERT((xseq->nctype == NC_Sequence)); /* collect the path to the sequence node */ collectnodepath3(xseq,path,WITHDATASET); /* Get tree root */ ASSERT(xseq->root == (CDFnode*)nclistget(path,0)); xroot = xseq->root; ocstat = oc_data_getroot(conn,xroot->tree->ocroot,&data); if(ocstat) goto done; /* Basically we use the path to walk the data instances to reach the sequence instance */ for(i=0;i<nclistlength(path);i++) { CDFnode* current = (CDFnode*)nclistget(path,i); OCdatanode nextdata = NULL; CDFnode* next = NULL; /* invariant: current = ith node in path; data = corresponding datanode */ /* get next node in next and next instance in nextdata */ if(current->nctype == NC_Structure || current->nctype == NC_Dataset) { if(nclistlength(current->array.dimset0) > 0) { /* Cannot handle this case */ ncstat = THROW(NC_EDDS); goto done; } /* get next node in path; structure/dataset => exists */ next = (CDFnode*)nclistget(path,i+1); index = fieldindex(current,next); /* Move to appropriate field */ ocstat = oc_data_ithfield(conn,data,index,&nextdata); if(ocstat) goto done; oc_data_free(conn,data); data = nextdata; /* set up for next loop iteration */ } else if(current->nctype == NC_Sequence) { /* Check for nested Sequences */ if(current != xseq) { /* Cannot handle this case */ ncstat = THROW(NC_EDDS); goto done; } /* Get the record count */ ocstat = oc_data_recordcount(conn,data,&recordcount); if(sizep) *sizep = recordcount; oc_data_free(conn,data); /* reclaim */ break; /* leave the loop */ } else { PANIC("unexpected mode"); return NC_EINVAL; } } done: nclistfree(path); if(ocstat) ncstat = ocerrtoncerr(ocstat); return THROW(ncstat); }