source: XIOS/dev/dev_olga/extern/src_netcdf4/constraints3.c @ 1620

Last change on this file since 1620 was 409, checked in by ymipsl, 11 years ago

Add improved nectdf internal library src

YM

  • Property svn:eol-style set to native
File size: 24.7 KB
Line 
1/*********************************************************************
2 *   Copyright 1993, UCAR/Unidata
3 *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4 *   $Header: /upc/share/CVS/netcdf-3/libncdce3/constraints3.c,v 1.40 2010/05/27 21:34:07 dmh Exp $
5 *********************************************************************/
6
7#include "ncdap3.h"
8#include "dapodom.h"
9#include "dapdebug.h"
10#include "dapdump.h"
11#include "dceparselex.h"
12
13static void completesegments3(NClist* fullpath, NClist* segments);
14static NCerror qualifyprojectionnames3(DCEprojection* proj);
15static NCerror qualifyprojectionsizes3(DCEprojection* proj);
16static NCerror matchpartialname3(NClist* nodes, NClist* segments, CDFnode** nodep);
17static int matchsuffix3(NClist* matchpath, NClist* segments);
18static int iscontainer(CDFnode* node);
19static DCEprojection* projectify(CDFnode* field, DCEprojection* container);
20static int slicematch(NClist* seglist1, NClist* seglist2);
21
22/* Parse incoming url constraints, if any,
23   to check for syntactic correctness */ 
24NCerror
25parsedapconstraints(NCDAPCOMMON* dapcomm, char* constraints,
26                    DCEconstraint* dceconstraint)
27{
28    NCerror ncstat = NC_NOERR;
29    char* errmsg;
30
31    ASSERT(dceconstraint != NULL);
32    nclistclear(dceconstraint->projections);
33    nclistclear(dceconstraint->selections);
34
35    ncstat = dapceparse(constraints,dceconstraint,&errmsg);
36    if(ncstat) {
37        nclog(NCLOGWARN,"DCE constraint parse failure: %s",errmsg);
38        nullfree(errmsg);
39        nclistclear(dceconstraint->projections);
40        nclistclear(dceconstraint->selections);
41    }
42    return ncstat;
43}
44
45/* Map constraint paths to CDFnode paths in specified tree and fill
46   in the declsizes.
47   The difficulty is that suffix paths are legal.
48*/
49
50NCerror
51mapconstraints3(DCEconstraint* constraint,
52                CDFnode* root)
53{
54    int i;
55    NCerror ncstat = NC_NOERR;
56    NClist* nodes = root->tree->nodes;
57    NClist* dceprojections = constraint->projections;
58#if 0
59    NClist* dceselections = constraint->selections;
60#endif
61
62    /* Convert the projection paths to leaves in the dds tree */
63    for(i=0;i<nclistlength(dceprojections);i++) {
64        DCEprojection* proj = (DCEprojection*)nclistget(dceprojections,i);
65        if(proj->discrim != CES_VAR) continue; /* ignore functions*/
66        ncstat = matchpartialname3(nodes,proj->var->segments,
67                                   (CDFnode**)&proj->var->annotation);
68        if(ncstat) goto done;
69    }
70
71#ifdef DEBUG
72fprintf(stderr,"mapconstraint.projections: %s\n",
73                dumpprojections(dceprojections));
74#endif
75
76done:
77    return THROW(ncstat);
78}
79
80
81/* Fill in:
82    1. projection segments
83    2. projection segment slices declsize
84    3. selection path
85*/
86NCerror
87qualifyconstraints3(DCEconstraint* constraint)
88{
89    NCerror ncstat = NC_NOERR;
90    int i;
91#ifdef DEBUG
92fprintf(stderr,"qualifyconstraints.before: %s\n",
93                dumpconstraint(constraint));
94#endif
95    if(constraint != NULL) {
96        for(i=0;i<nclistlength(constraint->projections);i++) { 
97            DCEprojection* p = (DCEprojection*)nclistget(constraint->projections,i);
98            ncstat = qualifyprojectionnames3(p);
99            ncstat = qualifyprojectionsizes3(p);
100        }
101    }
102#ifdef DEBUG
103fprintf(stderr,"qualifyconstraints.after: %s\n",
104                dumpconstraint(constraint));
105#endif
106    return ncstat;
107}
108
109/* convert all names in projections in paths to be fully qualified
110   by adding prefix segment objects.
111*/
112static NCerror
113qualifyprojectionnames3(DCEprojection* proj)
114{
115    NCerror ncstat = NC_NOERR;
116    NClist* fullpath = nclistnew();
117
118    ASSERT((proj->discrim == CES_VAR
119            && proj->var->annotation != NULL
120            && ((CDFnode*)proj->var->annotation)->ocnode != OCNULL));
121    collectnodepath3((CDFnode*)proj->var->annotation,fullpath,!WITHDATASET);
122#ifdef DEBUG
123fprintf(stderr,"qualify: %s -> ",
124        dumpprojection(proj));
125#endif
126    /* Now add path nodes to create full path */
127    completesegments3(fullpath,proj->var->segments);
128
129#ifdef DEBUG
130fprintf(stderr,"%s\n",
131        dumpprojection(proj));
132#endif
133    nclistfree(fullpath);
134    return ncstat;
135}
136
137/* Make sure that the slice declsizes are all defined for this projection */
138static NCerror
139qualifyprojectionsizes3(DCEprojection* proj)
140{
141    int i,j;
142    ASSERT(proj->discrim == CES_VAR);
143#ifdef DEBUG
144fprintf(stderr,"qualifyprojectionsizes.before: %s\n",
145                dumpprojection(proj));
146#endif
147    for(i=0;i<nclistlength(proj->var->segments);i++) {
148        DCEsegment* seg = (DCEsegment*)nclistget(proj->var->segments,i);
149        NClist* dimset = NULL;
150        CDFnode* cdfnode = (CDFnode*)seg->annotation;
151        ASSERT(cdfnode != NULL);
152        dimset = cdfnode->array.dimsetplus;
153        seg->rank = nclistlength(dimset);
154        /* For this, we do not want any string dimensions */
155        if(cdfnode->array.stringdim != NULL) seg->rank--;
156        for(j=0;j<seg->rank;j++) {
157            CDFnode* dim = (CDFnode*)nclistget(dimset,j);
158            if(dim->dim.basedim != NULL) dim = dim->dim.basedim;
159            ASSERT(dim != null);
160            if(seg->slicesdefined)
161                seg->slices[j].declsize = dim->dim.declsize;
162            else
163                dcemakewholeslice(seg->slices+j,dim->dim.declsize);
164        }
165        seg->slicesdefined = 1;
166        seg->slicesdeclized = 1;
167    }
168#ifdef DEBUG
169fprintf(stderr,"qualifyprojectionsizes.after: %s\n",
170                dumpprojection(proj));
171#endif
172    return NC_NOERR;
173}
174
175static void
176completesegments3(NClist* fullpath, NClist* segments)
177{
178    int i,delta;
179    /* add path nodes to segments to create full path */
180    delta = (nclistlength(fullpath) - nclistlength(segments));
181    ASSERT((delta >= 0));
182    for(i=0;i<delta;i++) {
183        DCEsegment* seg = (DCEsegment*)dcecreate(CES_SEGMENT);
184        CDFnode* node = (CDFnode*)nclistget(fullpath,i);
185        seg->name = nulldup(node->ocname);
186        seg->annotation = (void*)node;
187        seg->rank = nclistlength(node->array.dimset0);
188        nclistinsert(segments,i,(ncelem)seg);
189    }
190    /* Now modify the segments to point to the appropriate node
191       and fill in the slices.
192    */
193    for(i=delta;i<nclistlength(segments);i++) {
194        DCEsegment* seg = (DCEsegment*)nclistget(segments,i);
195        CDFnode* node = (CDFnode*)nclistget(fullpath,i);
196        seg->annotation = (void*)node;
197    }
198}
199
200/*
201We are given a set of segments (in path)
202representing a partial path for a CDFnode variable.
203Our goal is to locate all matching
204variables for which the path of that
205variable has a suffix matching
206the given partial path.
207If one node matches exactly, then use that one;
208otherwise there had better be exactly one
209match else ambiguous.
210Additional constraints (4/12/2010):
2111. if a segment is dimensioned, then use that info
212   to distinguish e.g a grid node from a possible
213   grid array within it of the same name.
214   Treat sequences as of rank 1.
2152. if there are two matches, and one is the grid
216   and the other is the grid array within that grid,
217   then choose the grid array.
2183. If there are multiple matches choose the one with the
219   shortest path
2204. otherwise complain about ambiguity
221*/
222
223/**
224 * Given a path as segments,
225 * try to locate the CDFnode
226 * instance (from a given set)
227 * that corresponds to the path.
228 * The key difficulty is that the
229 * path may only be a suffix of the
230 * complete path.
231 */
232
233static NCerror
234matchpartialname3(NClist* nodes, NClist* segments, CDFnode** nodep)
235{
236    int i,nsegs;
237    NCerror ncstat = NC_NOERR;
238    DCEsegment* lastseg = NULL;
239    NClist* namematches = nclistnew();
240    NClist* matches = nclistnew();
241    NClist* matchpath = nclistnew();
242
243    /* Locate all nodes with the same name
244       as the last element in the segment path
245    */
246    nsegs = nclistlength(segments);
247    lastseg = (DCEsegment*)nclistget(segments,nsegs-1);
248    for(i=0;i<nclistlength(nodes);i++) {
249        CDFnode* node = (CDFnode*)nclistget(nodes,i);
250        if(node->ocname == null)
251            continue;
252        /* Path names come from oc space */
253        if(strcmp(node->ocname,lastseg->name) != 0)
254            continue;
255        /* Only look at selected kinds of nodes */
256        if(node->nctype != NC_Sequence
257               && node->nctype != NC_Structure
258               && node->nctype != NC_Grid
259               && node->nctype != NC_Primitive
260          )
261            continue;
262        nclistpush(namematches,(ncelem)node);
263    }   
264    if(nclistlength(namematches)==0) {
265        nclog(NCLOGERR,"No match for projection name: %s",lastseg->name);
266        ncstat = NC_EDDS;
267        goto done;
268    }
269
270    /* Now, collect and compare paths of the matching nodes */
271    for(i=0;i<nclistlength(namematches);i++) {
272        CDFnode* matchnode = (CDFnode*)nclistget(namematches,i);
273        nclistclear(matchpath);
274        collectnodepath3(matchnode,matchpath,0);
275        /* Do a suffix match */
276        if(matchsuffix3(matchpath,segments)) {
277            nclistpush(matches,(ncelem)matchnode);
278#ifdef DEBUG
279fprintf(stderr,"matchpartialname: pathmatch: %s :: %s\n",
280matchnode->ncfullname,dumpsegments(segments));
281#endif
282        }
283    }
284    /* |matches|==0 => no match; |matches|>1 => ambiguity */
285    switch (nclistlength(matches)) {
286    case 0:
287        nclog(NCLOGERR,"No match for projection name: %s",lastseg->name);
288        ncstat = NC_EDDS;
289        break;
290    case 1:
291        if(nodep)
292            *nodep = (CDFnode*)nclistget(matches,0);
293        break;
294    default: {
295        CDFnode* minnode = NULL;
296        int minpath = 0;
297        int nmin = 0; /* to catch multiple ones with same short path */
298        /* ok, see if one of the matches has a path that is shorter
299           then all the others */
300        for(i=0;i<nclistlength(matches);i++) {
301            CDFnode* candidate = (CDFnode*)nclistget(matches,i);
302            nclistclear(matchpath);
303            collectnodepath3(candidate,matchpath,0);
304            if(minpath == 0) {
305                minpath = nclistlength(matchpath);
306                minnode = candidate;
307            } else if(nclistlength(matchpath) == minpath) {
308                nmin++;         
309            } else if(nclistlength(matchpath) < minpath) {
310                minpath = nclistlength(matchpath);
311                minnode = candidate;
312                nmin = 1;
313            }
314        } /*for*/
315        if(minnode == NULL || nmin > 1) {       
316            nclog(NCLOGERR,"Ambiguous match for projection name: %s",
317                        lastseg->name);
318            ncstat = NC_EDDS;
319        } else if(nodep)
320            *nodep = minnode;
321        } break;
322    }
323#ifdef DEBUG
324fprintf(stderr,"matchpartialname: choice: %s %s for %s\n",
325(nclistlength(matches) > 1?"":"forced"),
326(*nodep)->ncfullname,dumpsegments(segments));
327#endif
328
329done:
330    return THROW(ncstat);
331}
332
333static int
334matchsuffix3(NClist* matchpath, NClist* segments)
335{
336    int i,j;
337    int nsegs = nclistlength(segments);
338    int pathlen = nclistlength(matchpath);
339    ASSERT(pathlen >= nsegs);
340    for(i=0;i<pathlen;i++) {
341        int pathmatch = 1;
342        /* Starting at this point in the path, try to match the segment list */
343        for(j=0;j<nsegs && (i+j < pathlen);j++) {
344            int segmatch = 1;
345            DCEsegment* seg = (DCEsegment*)nclistget(segments,j);
346            CDFnode* node = (CDFnode*)nclistget(matchpath,i+j);
347            int rank = seg->rank;
348            /* Do the names match (in oc name space) */
349            if(strcmp(seg->name,node->ocname) != 0) {
350                segmatch = 0;/* no match */
351            } else
352            /* Do the ranks match (watch out for sequences) */
353            if(rank == 0) /* rank == 9 matches any set of dimensions */
354                segmatch = 1;
355            else if(node->nctype == NC_Sequence)
356                segmatch = (rank == 1?1:0);
357            else /*!NC_Sequence*/
358                segmatch = (rank == nclistlength(node->array.dimset0)?1:0);
359            if(!segmatch) pathmatch = 0;
360        }
361        if(pathmatch) return 1;
362   }
363   return 0;
364}
365
366
367/* Convert a DCEprojection instance into a string
368   that can be used with the url
369*/
370
371char*
372buildprojectionstring3(NClist* projections)
373{
374    char* pstring;
375    NCbytes* buf = ncbytesnew();
376    dcelisttobuffer(projections,buf,",");
377    pstring = ncbytesdup(buf);
378    ncbytesfree(buf);
379    return pstring;
380}
381
382char*
383buildselectionstring3(NClist* selections)
384{
385    NCbytes* buf = ncbytesnew();
386    char* sstring;
387    dcelisttobuffer(selections,buf,"&");
388    sstring = ncbytesdup(buf);
389    ncbytesfree(buf);
390    return sstring;
391}
392
393char*
394buildconstraintstring3(DCEconstraint* constraints)
395{
396    NCbytes* buf = ncbytesnew();
397    char* result = NULL;
398    dcetobuffer((DCEnode*)constraints,buf);
399    result = ncbytesdup(buf);
400    ncbytesfree(buf);
401    return result;
402}
403
404
405/* Given the arguments to vara
406   construct a corresponding projection
407   with any pseudo dimensions removed
408*/
409NCerror
410buildvaraprojection3(Getvara* getvar,
411                     const size_t* startp, const size_t* countp, const ptrdiff_t* stridep,
412                     DCEprojection** projectionp)
413{
414    int i,j;
415    NCerror ncstat = NC_NOERR;
416    CDFnode* var = getvar->target;
417    DCEprojection* projection = NULL;
418    NClist* path = nclistnew();
419    NClist* segments = NULL;
420    int dimindex;
421
422    ncstat = dapvar2projection(var,&projection);
423#ifdef DEBUG
424fprintf(stderr,"buildvaraprojection: %s\n",dumpprojection(projection));
425#endif
426
427    /* We need to assign the start/count/stride info to each segment;
428       declsize will have been set
429    */
430    segments = projection->var->segments;
431    dimindex = 0;
432    for(i=0;i<nclistlength(segments);i++) {
433        DCEsegment* segment = (DCEsegment*)nclistget(segments,i);
434        for(j=0;j<segment->rank;j++) {
435            DCEslice* slice = &segment->slices[j];
436            /* make each slice represent the corresponding
437               start/count/stride */
438            slice->first = startp[dimindex+j];
439            slice->stride = stridep[dimindex+j];
440            slice->count = countp[dimindex+j];
441            slice->length = slice->count * slice->stride;
442            if(slice->length > slice->declsize)
443                slice->length = slice->declsize;
444            slice->stop = (slice->first + slice->length);
445            if(slice->stop > slice->declsize)
446                slice->stop = slice->declsize;
447        }
448        dimindex += segment->rank;
449    }
450#ifdef DEBUG
451fprintf(stderr,"buildvaraprojection.final: %s\n",dumpprojection(projection));
452#endif
453
454#ifdef DEBUG
455fprintf(stderr,"buildvaraprojection3: projection=%s\n",
456        dumpprojection(projection));
457#endif
458
459    if(projectionp) *projectionp = projection;
460
461    nclistfree(path);
462    if(ncstat) dcefree((DCEnode*)projection);
463    return ncstat;
464}
465
466int
467iswholeslice(DCEslice* slice, CDFnode* dim)
468{
469    if(slice->first != 0 || slice->stride != 1) return 0;
470    if(dim != NULL) {
471        if(slice->stop != dim->dim.declsize) return 0;
472    } else if(dim == NULL) {
473        if(slice->declsize == 0
474           || slice->count != slice->declsize) return 0;
475    }
476    return 1;
477}
478
479int
480iswholesegment(DCEsegment* seg)
481{
482    int i,whole;
483    NClist* dimset = NULL;
484    unsigned int rank;
485   
486    if(seg->rank == 0) return 1;
487    if(!seg->slicesdefined) return 0;
488    if(seg->annotation == NULL) return 0;
489    dimset = ((CDFnode*)seg->annotation)->array.dimset0;
490    rank = nclistlength(dimset);
491    whole = 1; /* assume so */
492    for(i=0;i<rank;i++) {
493        CDFnode* dim = (CDFnode*)nclistget(dimset,i);
494        if(!iswholeslice(&seg->slices[i],dim)) {whole = 0; break;}     
495    }
496    return whole;
497}
498
499int
500iswholeprojection(DCEprojection* proj)
501{
502    int i,whole;
503   
504    ASSERT((proj->discrim == CES_VAR));
505
506    whole = 1; /* assume so */
507    for(i=0;i<nclistlength(proj->var->segments);i++) {
508        DCEsegment* segment = (DCEsegment*)nclistget(proj->var->segments,i);
509        if(!iswholesegment(segment)) {whole = 0; break;}       
510    }
511    return whole;
512}
513
514int
515iswholeconstraint(DCEconstraint* con)
516{
517    int i;
518    if(con == NULL) return 1;
519    if(con->projections != NULL) {
520        for(i=0;i<nclistlength(con->projections);i++) {
521         if(!iswholeprojection((DCEprojection*)nclistget(con->projections,i)))
522            return 0;
523        }
524    }
525    if(con->selections != NULL)
526        return 0;
527    return 1;
528}
529
530
531/*
532Given a set of projections, we need to produce
533an expanded, correct, and equivalent set of projections.
534The term "correct" means we must fix the following cases:
5351. Multiple occurrences of the same leaf variable
536   with differing projection slices. Fix is to complain.
5372. Occurrences of container and one or more of its fields.
538   Fix is to suppress the container.
539The term "expanded" means
5401. Expand all occurrences of only a container by
541   replacing it with all of its fields.
542*/
543
544NCerror
545fixprojections(NClist* list)
546{
547    int i,j,k;
548    NCerror ncstat = NC_NOERR;
549    NClist* tmp = nclistnew(); /* misc. uses */
550
551#ifdef DEBUG
552fprintf(stderr,"fixprojection: list = %s\n",dumpprojections(list));
553#endif
554
555    if(nclistlength(list) == 0) goto done;
556
557    /* Step 1: remove duplicates and complain about slice mismatches */
558    for(i=0;i<nclistlength(list);i++) {
559        DCEprojection* p1 = (DCEprojection*)nclistget(list,i);
560        if(p1 == NULL) continue;
561        if(p1->discrim != CES_VAR) continue; /* dont try to unify functions */
562        for(j=i;j<nclistlength(list);j++) {
563            DCEprojection* p2 = (DCEprojection*)nclistget(list,j);
564            if(p2 == NULL) continue;
565            if(p1 == p2) continue;
566            if(p2->discrim != CES_VAR) continue;
567            if(p1->var->annotation != p2->var->annotation) continue;
568            /* check for slice mismatches */
569            if(!slicematch(p1->var->segments,p2->var->segments)) {
570                /* complain */
571                nclog(NCLOGWARN,"Malformed projection: same variable with different slicing");
572            }
573            /* remove p32 */
574            nclistset(list,j,(ncelem)NULL);         
575            dcefree((DCEnode*)p2);         
576        }       
577    }
578
579    /* Step 2: remove containers when a field is also present */
580    for(i=0;i<nclistlength(list);i++) {
581        DCEprojection* p1 = (DCEprojection*)nclistget(list,i);
582        if(p1 == NULL) continue;
583        if(p1->discrim != CES_VAR) continue; /* dont try to unify functions */
584        if(!iscontainer((CDFnode*)p1->var->annotation))
585            continue;
586        for(j=i;j<nclistlength(list);j++) {
587            DCEprojection* p2 = (DCEprojection*)nclistget(list,j);
588            if(p2 == NULL) continue;
589            if(p2->discrim != CES_VAR) continue;
590            nclistclear(tmp);
591            collectnodepath3((CDFnode*)p2->var->annotation,tmp,WITHDATASET);
592            for(k=0;k<nclistlength(tmp);k++) {
593                void* candidate = (void*)nclistget(tmp,k);
594                if(candidate == p1->var->annotation) {
595                    nclistset(list,i,(ncelem)NULL);         
596                    dcefree((DCEnode*)p1);
597                    goto next;
598                }
599            }
600        }
601next:   continue;
602    }
603
604    /* Step 3: expand all containers recursively down to the leaf nodes */
605    for(;;) {
606        nclistclear(tmp);
607        for(i=0;i<nclistlength(list);i++) {
608            DCEprojection* target = (DCEprojection*)nclistget(list,i);
609            CDFnode* leaf;
610            if(target == NULL) continue;
611            if(target->discrim != CES_VAR)
612                continue; /* dont try to unify functions */
613            leaf = (CDFnode*)target->var->annotation;
614            ASSERT(leaf != NULL);
615            if(iscontainer(leaf)) {/* capture container */
616                if(!nclistcontains(tmp,(ncelem)target))
617                    nclistpush(tmp,(ncelem)target);
618                nclistset(list,i,(ncelem)NULL);
619            }
620        }
621        if(nclistlength(tmp) == 0) break; /*done*/
622        /* Now explode the containers */
623        for(i=0;i<nclistlength(tmp);i++) {
624            DCEprojection* container = (DCEprojection*)nclistget(tmp,i);
625            CDFnode* leaf = (CDFnode*)container->var->annotation;
626            for(j=0;i<nclistlength(leaf->subnodes);j++) {
627                CDFnode* field = (CDFnode*)nclistget(leaf->subnodes,j);
628                /* Convert field node to a proper constraint */
629                DCEprojection* proj = projectify(field,container);
630                nclistpush(list,(ncelem)proj);
631            }       
632            /* reclaim the container */
633            dcefree((DCEnode*)container);
634        }
635    } /*for(;;)*/
636
637    /* remove all NULL elements */
638    for(i=nclistlength(list)-1;i>=0;i--) {
639        DCEprojection* target = (DCEprojection*)nclistget(list,i);
640        if(target == NULL)
641            nclistremove(list,i);       
642    }   
643
644done:
645#ifdef DEBUG
646fprintf(stderr,"fixprojection: exploded = %s\n",dumpprojections(list));
647#endif
648    nclistfree(tmp);
649    return ncstat;
650}
651
652static int
653iscontainer(CDFnode* node)
654{
655    return (node->nctype == NC_Dataset
656               || node->nctype == NC_Sequence
657               || node->nctype == NC_Structure
658               || node->nctype == NC_Grid);
659}
660
661static DCEprojection*
662projectify(CDFnode* field, DCEprojection* container)
663{
664    DCEprojection* proj  = (DCEprojection*)dcecreate(CES_PROJECT);
665    DCEvar* var  = (DCEvar*)dcecreate(CES_VAR);
666    DCEsegment* seg  = (DCEsegment*)dcecreate(CES_SEGMENT);
667    proj->discrim = CES_VAR;
668    proj->var = var;
669    var->annotation = (void*)field;
670    /* Dup the segment list */
671    var->segments = dceclonelist(container->var->segments);
672    seg->rank = 0;
673    nclistpush(var->segments,(ncelem)seg);
674    return proj;
675}
676
677static int
678slicematch(NClist* seglist1, NClist* seglist2)
679{
680    int i,j;
681    if((seglist1 == NULL || seglist2 == NULL) && seglist1 != seglist2)
682        return 0;
683    if(nclistlength(seglist1) != nclistlength(seglist2))
684        return 0;
685    for(i=0;i<nclistlength(seglist1);i++) {
686        DCEsegment* seg1 = (DCEsegment*)nclistget(seglist1,i);
687        DCEsegment* seg2 = (DCEsegment*)nclistget(seglist2,i);
688        if(seg1->rank != seg2->rank)
689            return 0;
690        for(j=0;j<seg1->rank;j++) {
691            if(seg1->slices[j].first != seg2->slices[j].first
692               || seg1->slices[j].count != seg2->slices[j].count
693               || seg1->slices[j].stride != seg2->slices[j].stride)
694                return 0;
695        }
696    }
697    return 1;
698}
699
700/* Convert a CDFnode var to a projection; include
701   pseudodimensions; always whole variable.
702*/
703int
704dapvar2projection(CDFnode* var, DCEprojection** projectionp)
705{
706    int i,j;
707    int ncstat = NC_NOERR;
708    NClist* path = nclistnew();
709    NClist* segments;
710    DCEprojection* projection = NULL;
711    int dimindex;
712
713    /* Collect the nodes needed to construct the projection segment */   
714    collectnodepath3(var,path,!WITHDATASET);
715
716    segments = nclistnew();
717    dimindex = 0; /* point to next subset of slices */
718    nclistsetalloc(segments,nclistlength(path));
719    for(i=0;i<nclistlength(path);i++) {
720        DCEsegment* segment = (DCEsegment*)dcecreate(CES_SEGMENT);
721        CDFnode* n = (CDFnode*)nclistget(path,i);
722        int localrank;
723        NClist* dimset;
724
725        segment->annotation = (void*)n;
726        segment->name = nulldup(n->ocname);
727        /* We need to assign whole slices to each segment */
728        localrank = nclistlength(n->array.dimsetplus);
729        segment->rank = localrank;
730        dimset = n->array.dimsetplus;
731        for(j=0;j<localrank;j++) {
732            DCEslice* slice;
733            CDFnode* dim;
734            slice = &segment->slices[j];
735            dim = (CDFnode*)nclistget(dimset,j);
736            ASSERT(dim->dim.declsize0 > 0);
737            dcemakewholeslice(slice,dim->dim.declsize0);
738        }
739        segment->slicesdefined = 1;
740        segment->slicesdeclized = 1;
741        dimindex += localrank;
742        nclistpush(segments,(ncelem)segment);
743    }
744   
745    projection = (DCEprojection*)dcecreate(CES_PROJECT);
746    projection->discrim = CES_VAR;
747    projection->var = (DCEvar*)dcecreate(CES_VAR);
748    projection->var->annotation = (void*)var;
749    projection->var->segments = segments;
750
751#ifdef DEBUG1
752fprintf(stderr,"dapvar2projection: projection=%s\n",
753        dumpprojection(projection));
754#endif
755
756    nclistfree(path);
757    if(ncstat) dcefree((DCEnode*)projection);
758    else if(projectionp) *projectionp = projection;
759    return ncstat;
760}   
761
762/*
763Given a set of projections and a projection
764representing a variable (from, say vara or prefetch)
765construct a single projection for fetching that variable
766with the proper constraints.
767*/
768int
769daprestrictprojection(NClist* projections, DCEprojection* var, DCEprojection** resultp)
770{
771    int ncstat = NC_NOERR;
772    int i;
773    DCEprojection* result = NULL;
774#ifdef DEBUG1
775fprintf(stderr,"restrictprojection.before: constraints=|%s| vara=|%s|\n",
776                dumpprojections(projections),
777                dumpprojection(var));
778#endif
779
780    ASSERT(var != NULL);
781
782    /* the projection list will contain at most 1 match for the var by construction */
783    for(result=null,i=0;i<nclistlength(projections);i++) {
784        DCEprojection* p1 = (DCEprojection*)nclistget(projections,i);
785        if(p1 == NULL || p1->discrim != CES_VAR) continue;
786        if(p1->var->annotation == var->var->annotation) {
787            result = p1;
788            break;
789        }
790    }
791    if(result == NULL) {
792        result = (DCEprojection*)dceclone((DCEnode*)var); /* use only the var projection */
793        goto done;     
794    }
795    result = (DCEprojection*)dceclone((DCEnode*)result); /* so we can modify */
796
797#ifdef DEBUG1
798fprintf(stderr,"restrictprojection.choice: |%s|\n",dumpprojection(result));
799#endif
800    /* We need to merge the projection from the projection list
801       with the var projection
802    */
803    ncstat = dcemergeprojections(result,var); /* result will be modified */   
804
805done:
806    if(resultp) *resultp = result;
807#ifdef DEBUG
808fprintf(stderr,"restrictprojection.after=|%s|\n",
809                dumpprojection(result));
810#endif
811    return ncstat;
812}
813
814/* Shift the slice so it runs from 0..count by step 1 */
815static void
816dapshiftslice(DCEslice* slice)
817{
818    size_t first = slice->first;
819    size_t stride = slice->stride;
820    if(first == 0 && stride == 1) return; /* no need to do anything */
821    slice->first = 0;
822    slice->stride = 1;
823    slice->length = slice->count;
824    slice->stop = slice->count;
825}
826
827int
828dapshiftprojection(DCEprojection* projection)
829{
830    int ncstat = NC_NOERR;
831    int i,j;
832    NClist* segments;
833
834#ifdef DEBUG1
835fprintf(stderr,"dapshiftprojection.before: %s\n",dumpprojection(projection));
836#endif
837
838    ASSERT(projection->discrim == CES_VAR);
839    segments = projection->var->segments;
840    for(i=0;i<nclistlength(segments);i++) {
841        DCEsegment* seg = (DCEsegment*)nclistget(segments,i);
842        for(j=0;j<seg->rank;j++) {
843            DCEslice* slice = seg->slices+j;
844            dapshiftslice(slice);
845        }
846    }
847
848#ifdef DEBUG1
849fprintf(stderr,"dapshiftprojection.after: %s\n",dumpprojection(projection));
850#endif
851
852    return ncstat;
853}
Note: See TracBrowser for help on using the repository browser.