123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853 |
- /*********************************************************************
- * Copyright 1993, UCAR/Unidata
- * See netcdf/COPYRIGHT file for copying and redistribution conditions.
- * $Header: /upc/share/CVS/netcdf-3/libncdce3/constraints3.c,v 1.40 2010/05/27 21:34:07 dmh Exp $
- *********************************************************************/
- #include "ncdap3.h"
- #include "dapodom.h"
- #include "dapdebug.h"
- #include "dapdump.h"
- #include "dceparselex.h"
- static void completesegments3(NClist* fullpath, NClist* segments);
- static NCerror qualifyprojectionnames3(DCEprojection* proj);
- static NCerror qualifyprojectionsizes3(DCEprojection* proj);
- static NCerror matchpartialname3(NClist* nodes, NClist* segments, CDFnode** nodep);
- static int matchsuffix3(NClist* matchpath, NClist* segments);
- static int iscontainer(CDFnode* node);
- static DCEprojection* projectify(CDFnode* field, DCEprojection* container);
- static int slicematch(NClist* seglist1, NClist* seglist2);
- /* Parse incoming url constraints, if any,
- to check for syntactic correctness */
- NCerror
- parsedapconstraints(NCDAPCOMMON* dapcomm, char* constraints,
- DCEconstraint* dceconstraint)
- {
- NCerror ncstat = NC_NOERR;
- char* errmsg;
- ASSERT(dceconstraint != NULL);
- nclistclear(dceconstraint->projections);
- nclistclear(dceconstraint->selections);
- ncstat = dapceparse(constraints,dceconstraint,&errmsg);
- if(ncstat) {
- nclog(NCLOGWARN,"DCE constraint parse failure: %s",errmsg);
- nullfree(errmsg);
- nclistclear(dceconstraint->projections);
- nclistclear(dceconstraint->selections);
- }
- return ncstat;
- }
- /* Map constraint paths to CDFnode paths in specified tree and fill
- in the declsizes.
- The difficulty is that suffix paths are legal.
- */
- NCerror
- mapconstraints3(DCEconstraint* constraint,
- CDFnode* root)
- {
- int i;
- NCerror ncstat = NC_NOERR;
- NClist* nodes = root->tree->nodes;
- NClist* dceprojections = constraint->projections;
- #if 0
- NClist* dceselections = constraint->selections;
- #endif
- /* Convert the projection paths to leaves in the dds tree */
- for(i=0;i<nclistlength(dceprojections);i++) {
- DCEprojection* proj = (DCEprojection*)nclistget(dceprojections,i);
- if(proj->discrim != CES_VAR) continue; /* ignore functions*/
- ncstat = matchpartialname3(nodes,proj->var->segments,
- (CDFnode**)&proj->var->annotation);
- if(ncstat) goto done;
- }
- #ifdef DEBUG
- fprintf(stderr,"mapconstraint.projections: %s\n",
- dumpprojections(dceprojections));
- #endif
- done:
- return THROW(ncstat);
- }
- /* Fill in:
- 1. projection segments
- 2. projection segment slices declsize
- 3. selection path
- */
- NCerror
- qualifyconstraints3(DCEconstraint* constraint)
- {
- NCerror ncstat = NC_NOERR;
- int i;
- #ifdef DEBUG
- fprintf(stderr,"qualifyconstraints.before: %s\n",
- dumpconstraint(constraint));
- #endif
- if(constraint != NULL) {
- for(i=0;i<nclistlength(constraint->projections);i++) {
- DCEprojection* p = (DCEprojection*)nclistget(constraint->projections,i);
- ncstat = qualifyprojectionnames3(p);
- ncstat = qualifyprojectionsizes3(p);
- }
- }
- #ifdef DEBUG
- fprintf(stderr,"qualifyconstraints.after: %s\n",
- dumpconstraint(constraint));
- #endif
- return ncstat;
- }
- /* 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;
- }
- /* Make sure that the slice declsizes are all defined for this projection */
- static NCerror
- qualifyprojectionsizes3(DCEprojection* proj)
- {
- int i,j;
- ASSERT(proj->discrim == CES_VAR);
- #ifdef DEBUG
- fprintf(stderr,"qualifyprojectionsizes.before: %s\n",
- dumpprojection(proj));
- #endif
- for(i=0;i<nclistlength(proj->var->segments);i++) {
- DCEsegment* seg = (DCEsegment*)nclistget(proj->var->segments,i);
- NClist* dimset = NULL;
- CDFnode* cdfnode = (CDFnode*)seg->annotation;
- ASSERT(cdfnode != NULL);
- dimset = cdfnode->array.dimsetplus;
- seg->rank = nclistlength(dimset);
- /* For this, we do not want any string dimensions */
- if(cdfnode->array.stringdim != NULL) seg->rank--;
- for(j=0;j<seg->rank;j++) {
- CDFnode* dim = (CDFnode*)nclistget(dimset,j);
- if(dim->dim.basedim != NULL) dim = dim->dim.basedim;
- ASSERT(dim != null);
- if(seg->slicesdefined)
- seg->slices[j].declsize = dim->dim.declsize;
- else
- dcemakewholeslice(seg->slices+j,dim->dim.declsize);
- }
- seg->slicesdefined = 1;
- seg->slicesdeclized = 1;
- }
- #ifdef DEBUG
- fprintf(stderr,"qualifyprojectionsizes.after: %s\n",
- dumpprojection(proj));
- #endif
- return NC_NOERR;
- }
- static void
- completesegments3(NClist* fullpath, NClist* segments)
- {
- int i,delta;
- /* add path nodes to segments to create full path */
- delta = (nclistlength(fullpath) - nclistlength(segments));
- ASSERT((delta >= 0));
- for(i=0;i<delta;i++) {
- DCEsegment* seg = (DCEsegment*)dcecreate(CES_SEGMENT);
- CDFnode* node = (CDFnode*)nclistget(fullpath,i);
- seg->name = nulldup(node->ocname);
- seg->annotation = (void*)node;
- seg->rank = nclistlength(node->array.dimset0);
- nclistinsert(segments,i,(ncelem)seg);
- }
- /* Now modify the segments to point to the appropriate node
- and fill in the slices.
- */
- for(i=delta;i<nclistlength(segments);i++) {
- DCEsegment* seg = (DCEsegment*)nclistget(segments,i);
- CDFnode* node = (CDFnode*)nclistget(fullpath,i);
- seg->annotation = (void*)node;
- }
- }
- /*
- We are given a set of segments (in path)
- representing a partial path for a CDFnode variable.
- Our goal is to locate all matching
- variables for which the path of that
- variable has a suffix matching
- the given partial path.
- If one node matches exactly, then use that one;
- otherwise there had better be exactly one
- match else ambiguous.
- Additional constraints (4/12/2010):
- 1. if a segment is dimensioned, then use that info
- to distinguish e.g a grid node from a possible
- grid array within it of the same name.
- Treat sequences as of rank 1.
- 2. if there are two matches, and one is the grid
- and the other is the grid array within that grid,
- then choose the grid array.
- 3. If there are multiple matches choose the one with the
- shortest path
- 4. otherwise complain about ambiguity
- */
- /**
- * Given a path as segments,
- * try to locate the CDFnode
- * instance (from a given set)
- * that corresponds to the path.
- * The key difficulty is that the
- * path may only be a suffix of the
- * complete path.
- */
- 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);
- }
- static int
- matchsuffix3(NClist* matchpath, NClist* segments)
- {
- int i,j;
- int nsegs = nclistlength(segments);
- int pathlen = nclistlength(matchpath);
- ASSERT(pathlen >= nsegs);
- for(i=0;i<pathlen;i++) {
- int pathmatch = 1;
- /* Starting at this point in the path, try to match the segment list */
- for(j=0;j<nsegs && (i+j < pathlen);j++) {
- int segmatch = 1;
- DCEsegment* seg = (DCEsegment*)nclistget(segments,j);
- CDFnode* node = (CDFnode*)nclistget(matchpath,i+j);
- int rank = seg->rank;
- /* Do the names match (in oc name space) */
- if(strcmp(seg->name,node->ocname) != 0) {
- segmatch = 0;/* no match */
- } else
- /* Do the ranks match (watch out for sequences) */
- if(rank == 0) /* rank == 9 matches any set of dimensions */
- segmatch = 1;
- else if(node->nctype == NC_Sequence)
- segmatch = (rank == 1?1:0);
- else /*!NC_Sequence*/
- segmatch = (rank == nclistlength(node->array.dimset0)?1:0);
- if(!segmatch) pathmatch = 0;
- }
- if(pathmatch) return 1;
- }
- return 0;
- }
- /* Convert a DCEprojection instance into a string
- that can be used with the url
- */
- char*
- buildprojectionstring3(NClist* projections)
- {
- char* pstring;
- NCbytes* buf = ncbytesnew();
- dcelisttobuffer(projections,buf,",");
- pstring = ncbytesdup(buf);
- ncbytesfree(buf);
- return pstring;
- }
- char*
- buildselectionstring3(NClist* selections)
- {
- NCbytes* buf = ncbytesnew();
- char* sstring;
- dcelisttobuffer(selections,buf,"&");
- sstring = ncbytesdup(buf);
- ncbytesfree(buf);
- return sstring;
- }
- char*
- buildconstraintstring3(DCEconstraint* constraints)
- {
- NCbytes* buf = ncbytesnew();
- char* result = NULL;
- dcetobuffer((DCEnode*)constraints,buf);
- result = ncbytesdup(buf);
- ncbytesfree(buf);
- return result;
- }
- /* Given the arguments to vara
- construct a corresponding projection
- with any pseudo dimensions removed
- */
- NCerror
- buildvaraprojection3(Getvara* getvar,
- const size_t* startp, const size_t* countp, const ptrdiff_t* stridep,
- DCEprojection** projectionp)
- {
- int i,j;
- NCerror ncstat = NC_NOERR;
- CDFnode* var = getvar->target;
- DCEprojection* projection = NULL;
- NClist* path = nclistnew();
- NClist* segments = NULL;
- int dimindex;
- ncstat = dapvar2projection(var,&projection);
- #ifdef DEBUG
- fprintf(stderr,"buildvaraprojection: %s\n",dumpprojection(projection));
- #endif
- /* We need to assign the start/count/stride info to each segment;
- declsize will have been set
- */
- segments = projection->var->segments;
- dimindex = 0;
- for(i=0;i<nclistlength(segments);i++) {
- DCEsegment* segment = (DCEsegment*)nclistget(segments,i);
- for(j=0;j<segment->rank;j++) {
- DCEslice* slice = &segment->slices[j];
- /* make each slice represent the corresponding
- start/count/stride */
- slice->first = startp[dimindex+j];
- slice->stride = stridep[dimindex+j];
- slice->count = countp[dimindex+j];
- slice->length = slice->count * slice->stride;
- if(slice->length > slice->declsize)
- slice->length = slice->declsize;
- slice->stop = (slice->first + slice->length);
- if(slice->stop > slice->declsize)
- slice->stop = slice->declsize;
- }
- dimindex += segment->rank;
- }
- #ifdef DEBUG
- fprintf(stderr,"buildvaraprojection.final: %s\n",dumpprojection(projection));
- #endif
- #ifdef DEBUG
- fprintf(stderr,"buildvaraprojection3: projection=%s\n",
- dumpprojection(projection));
- #endif
- if(projectionp) *projectionp = projection;
- nclistfree(path);
- if(ncstat) dcefree((DCEnode*)projection);
- return ncstat;
- }
- int
- iswholeslice(DCEslice* slice, CDFnode* dim)
- {
- if(slice->first != 0 || slice->stride != 1) return 0;
- if(dim != NULL) {
- if(slice->stop != dim->dim.declsize) return 0;
- } else if(dim == NULL) {
- if(slice->declsize == 0
- || slice->count != slice->declsize) return 0;
- }
- return 1;
- }
- int
- iswholesegment(DCEsegment* seg)
- {
- int i,whole;
- NClist* dimset = NULL;
- unsigned int rank;
-
- if(seg->rank == 0) return 1;
- if(!seg->slicesdefined) return 0;
- if(seg->annotation == NULL) return 0;
- dimset = ((CDFnode*)seg->annotation)->array.dimset0;
- rank = nclistlength(dimset);
- whole = 1; /* assume so */
- for(i=0;i<rank;i++) {
- CDFnode* dim = (CDFnode*)nclistget(dimset,i);
- if(!iswholeslice(&seg->slices[i],dim)) {whole = 0; break;}
- }
- return whole;
- }
- int
- iswholeprojection(DCEprojection* proj)
- {
- int i,whole;
-
- ASSERT((proj->discrim == CES_VAR));
- whole = 1; /* assume so */
- for(i=0;i<nclistlength(proj->var->segments);i++) {
- DCEsegment* segment = (DCEsegment*)nclistget(proj->var->segments,i);
- if(!iswholesegment(segment)) {whole = 0; break;}
- }
- return whole;
- }
- int
- iswholeconstraint(DCEconstraint* con)
- {
- int i;
- if(con == NULL) return 1;
- if(con->projections != NULL) {
- for(i=0;i<nclistlength(con->projections);i++) {
- if(!iswholeprojection((DCEprojection*)nclistget(con->projections,i)))
- return 0;
- }
- }
- if(con->selections != NULL)
- return 0;
- return 1;
- }
- /*
- Given a set of projections, we need to produce
- an expanded, correct, and equivalent set of projections.
- The term "correct" means we must fix the following cases:
- 1. Multiple occurrences of the same leaf variable
- with differing projection slices. Fix is to complain.
- 2. Occurrences of container and one or more of its fields.
- Fix is to suppress the container.
- The term "expanded" means
- 1. Expand all occurrences of only a container by
- replacing it with all of its fields.
- */
- 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 int
- iscontainer(CDFnode* node)
- {
- return (node->nctype == NC_Dataset
- || node->nctype == NC_Sequence
- || node->nctype == NC_Structure
- || node->nctype == NC_Grid);
- }
- static DCEprojection*
- projectify(CDFnode* field, DCEprojection* container)
- {
- DCEprojection* proj = (DCEprojection*)dcecreate(CES_PROJECT);
- DCEvar* var = (DCEvar*)dcecreate(CES_VAR);
- DCEsegment* seg = (DCEsegment*)dcecreate(CES_SEGMENT);
- proj->discrim = CES_VAR;
- proj->var = var;
- var->annotation = (void*)field;
- /* Dup the segment list */
- var->segments = dceclonelist(container->var->segments);
- seg->rank = 0;
- nclistpush(var->segments,(ncelem)seg);
- return proj;
- }
- static int
- slicematch(NClist* seglist1, NClist* seglist2)
- {
- int i,j;
- if((seglist1 == NULL || seglist2 == NULL) && seglist1 != seglist2)
- return 0;
- if(nclistlength(seglist1) != nclistlength(seglist2))
- return 0;
- for(i=0;i<nclistlength(seglist1);i++) {
- DCEsegment* seg1 = (DCEsegment*)nclistget(seglist1,i);
- DCEsegment* seg2 = (DCEsegment*)nclistget(seglist2,i);
- if(seg1->rank != seg2->rank)
- return 0;
- for(j=0;j<seg1->rank;j++) {
- if(seg1->slices[j].first != seg2->slices[j].first
- || seg1->slices[j].count != seg2->slices[j].count
- || seg1->slices[j].stride != seg2->slices[j].stride)
- return 0;
- }
- }
- return 1;
- }
- /* 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;
- }
- /*
- Given a set of projections and a projection
- representing a variable (from, say vara or prefetch)
- construct a single projection for fetching that variable
- with the proper constraints.
- */
- int
- daprestrictprojection(NClist* projections, DCEprojection* var, DCEprojection** resultp)
- {
- int ncstat = NC_NOERR;
- int i;
- DCEprojection* result = NULL;
- #ifdef DEBUG1
- fprintf(stderr,"restrictprojection.before: constraints=|%s| vara=|%s|\n",
- dumpprojections(projections),
- dumpprojection(var));
- #endif
- ASSERT(var != NULL);
- /* the projection list will contain at most 1 match for the var by construction */
- for(result=null,i=0;i<nclistlength(projections);i++) {
- DCEprojection* p1 = (DCEprojection*)nclistget(projections,i);
- if(p1 == NULL || p1->discrim != CES_VAR) continue;
- if(p1->var->annotation == var->var->annotation) {
- result = p1;
- break;
- }
- }
- if(result == NULL) {
- result = (DCEprojection*)dceclone((DCEnode*)var); /* use only the var projection */
- goto done;
- }
- result = (DCEprojection*)dceclone((DCEnode*)result); /* so we can modify */
- #ifdef DEBUG1
- fprintf(stderr,"restrictprojection.choice: |%s|\n",dumpprojection(result));
- #endif
- /* We need to merge the projection from the projection list
- with the var projection
- */
- ncstat = dcemergeprojections(result,var); /* result will be modified */
- done:
- if(resultp) *resultp = result;
- #ifdef DEBUG
- fprintf(stderr,"restrictprojection.after=|%s|\n",
- dumpprojection(result));
- #endif
- return ncstat;
- }
- /* Shift the slice so it runs from 0..count by step 1 */
- static void
- dapshiftslice(DCEslice* slice)
- {
- size_t first = slice->first;
- size_t stride = slice->stride;
- if(first == 0 && stride == 1) return; /* no need to do anything */
- slice->first = 0;
- slice->stride = 1;
- slice->length = slice->count;
- slice->stop = slice->count;
- }
- int
- dapshiftprojection(DCEprojection* projection)
- {
- int ncstat = NC_NOERR;
- int i,j;
- NClist* segments;
- #ifdef DEBUG1
- fprintf(stderr,"dapshiftprojection.before: %s\n",dumpprojection(projection));
- #endif
- ASSERT(projection->discrim == CES_VAR);
- segments = projection->var->segments;
- for(i=0;i<nclistlength(segments);i++) {
- DCEsegment* seg = (DCEsegment*)nclistget(segments,i);
- for(j=0;j<seg->rank;j++) {
- DCEslice* slice = seg->slices+j;
- dapshiftslice(slice);
- }
- }
- #ifdef DEBUG1
- fprintf(stderr,"dapshiftprojection.after: %s\n",dumpprojection(projection));
- #endif
- return ncstat;
- }
|