source: XIOS/dev/dev_olga/extern/src_netcdf4/cdf3.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: 22.6 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/libncdap3/cdf3.c,v 1.33 2009/12/03 03:42:37 dmh Exp $
5 *********************************************************************/
6
7#include "ncdap3.h"
8#include "daputil.h"
9#include "dapdump.h"
10
11CDFnode* v4node = NULL;
12
13/* Forward*/
14static NCerror sequencecheck3r(CDFnode* node, NClist* vars, CDFnode* topseq);
15static NCerror regrid3r(CDFnode*, CDFnode*, NClist*);
16static NCerror testregrid3(CDFnode* node, CDFnode* template, NClist*);
17static CDFnode* makenewgrid3(CDFnode* node, CDFnode* template);
18static NCerror regridinsert(CDFnode* newgrid, CDFnode* node);
19static NCerror regridremove(CDFnode* newgrid, CDFnode* node);
20static NCerror mapnodes3r(CDFnode*, CDFnode*, int depth);
21static NCerror mapfcn(CDFnode* dstnode, CDFnode* srcnode);
22static NCerror definedimsetplus3(NCDAPCOMMON* nccomm, CDFnode* node);
23static NCerror definedimsetall3(NCDAPCOMMON* nccomm, CDFnode* node);
24
25/* Accumulate useful node sets  */
26NCerror
27computecdfnodesets3(NCDAPCOMMON* nccomm)
28{
29    unsigned int i;
30    NClist* varnodes = nclistnew(); 
31    NClist* allnodes = nccomm->cdf.ddsroot->tree->nodes;
32
33    if(nccomm->cdf.seqnodes == NULL) nccomm->cdf.seqnodes = nclistnew();
34    if(nccomm->cdf.gridnodes == NULL) nccomm->cdf.gridnodes = nclistnew();
35    nclistclear(nccomm->cdf.seqnodes);
36    nclistclear(nccomm->cdf.gridnodes);
37
38    computevarnodes3(nccomm,allnodes,varnodes);
39    nclistfree(nccomm->cdf.varnodes);
40    nccomm->cdf.varnodes = varnodes;
41
42    /* Now compute other sets of interest */
43    for(i=0;i<nclistlength(allnodes);i++) {
44        CDFnode* node = (CDFnode*)nclistget(allnodes,i);
45        if(!node->visible) continue;
46        switch (node->nctype) {
47        case NC_Sequence:
48            nclistpush(nccomm->cdf.seqnodes,(ncelem)node);
49            break;
50        case NC_Grid:
51            nclistpush(nccomm->cdf.gridnodes,(ncelem)node);
52            break;
53        default: break;
54        }
55    }
56    return NC_NOERR;
57}
58
59NCerror
60computevarnodes3(NCDAPCOMMON* nccomm, NClist* allnodes, NClist* varnodes)
61{
62    unsigned int i,len;
63    NClist* allvarnodes = nclistnew();
64    for(i=0;i<nclistlength(allnodes);i++) {
65        CDFnode* node = (CDFnode*)nclistget(allnodes,i);
66        /* If this node has a bad name, repair it */
67        if(dap_badname(node->ocname)) {
68            char* newname = dap_repairname(node->ocname);
69            nullfree(node->ocname);
70            node->ocname = newname;
71        }
72        if(!node->visible) continue;
73        if(node->nctype == NC_Primitive)
74            nclistpush(allvarnodes,(ncelem)node);
75    }
76    /* Further process the variable nodes to get the final set */
77    /* Use toplevel vars first */
78    len = nclistlength(allvarnodes);
79    for(i=0;i<len;i++) {
80        CDFnode* node = (CDFnode*)nclistget(allvarnodes,i);
81        if(node == NULL) continue;
82        if(daptoplevel(node)) {
83            nclistpush(varnodes,(ncelem)node);
84            nclistset(allvarnodes,i,(ncelem)NULL);
85        }
86    }
87    /*... then grid arrays and maps.
88      but exclude the coordinate variables if we are trying to
89      exactly mimic nc-dap
90    */
91    for(i=0;i<len;i++) {
92        CDFnode* node = (CDFnode*)nclistget(allvarnodes,i);
93        if(node == NULL) continue;
94        if(dapgridarray(node)) {
95            nclistpush(varnodes,(ncelem)node);
96            nclistset(allvarnodes,i,(ncelem)NULL);
97        } else if(dapgridmap(node)) {
98            if(!FLAGSET(nccomm->controls,NCF_NCDAP))
99                nclistpush(varnodes,(ncelem)node);
100            nclistset(allvarnodes,i,(ncelem)NULL);
101        }
102    }
103    /*... then all others */
104    for(i=0;i<len;i++) {
105        CDFnode* node = (CDFnode*)nclistget(allvarnodes,i);
106        if(node == NULL) continue;
107        nclistpush(varnodes,(ncelem)node);
108    }
109    nclistfree(allvarnodes);
110#ifdef DEBUG2
111for(i=0;i<nclistlength(varnodes);i++) {
112CDFnode* node = (CDFnode*)nclistget(varnodes,i);
113if(node == NULL) continue;
114fprintf(stderr,"computevarnodes: var: %s\n",makecdfpathstring3(node,"."));
115}
116#endif
117    return NC_NOERR;
118}
119
120NCerror
121fixgrids3(NCDAPCOMMON* nccomm)
122{
123    unsigned int i;
124    NClist* gridnodes = nccomm->cdf.gridnodes;
125
126    for(i=0;i<nclistlength(gridnodes);i++) {
127        CDFnode* grid = (CDFnode*)nclistget(gridnodes,i);
128        (void)fixgrid34(nccomm,grid);
129        /* Ignore mal-formed grids */
130    }
131    return NC_NOERR;
132}
133
134/*
135Figure out the names for variables.
136*/
137NCerror
138computecdfvarnames3(NCDAPCOMMON* nccomm, CDFnode* root, NClist* varnodes)
139{
140    unsigned int i,j,d;
141
142    /* clear all elided marks; except for dataset and grids */
143    for(i=0;i<nclistlength(root->tree->nodes);i++) {
144        CDFnode* node = (CDFnode*)nclistget(root->tree->nodes,i);
145        node->elided = 0;
146        if(node->nctype == NC_Grid || node->nctype == NC_Dataset)
147            node->elided = 1;
148    }
149
150    /* ensure all variables have an initial full name defined */
151    for(i=0;i<nclistlength(varnodes);i++) {
152        CDFnode* var = (CDFnode*)nclistget(varnodes,i);
153        nullfree(var->ncfullname);
154        var->ncfullname = makecdfpathstring3(var,nccomm->cdf.separator);
155#ifdef DEBUG2
156fprintf(stderr,"var names: %s %s %s\n",
157        var->ocname,var->ncbasename,var->ncfullname);
158#endif
159    }
160
161    /*  unify all variables with same fullname and dimensions
162        basevar fields says: "for duplicate grid variables";
163        when does this happen?
164    */
165    if(FLAGSET(nccomm->controls,NCF_NC3)) {
166        for(i=0;i<nclistlength(varnodes);i++) {
167            int match;
168            CDFnode* var = (CDFnode*)nclistget(varnodes,i);
169            for(j=0;j<i;j++) {
170                CDFnode* testnode = (CDFnode*)nclistget(varnodes,j);
171                match = 1;
172                if(testnode->array.basevar != NULL)
173                    continue; /* already processed */
174                if(strcmp(var->ncfullname,testnode->ncfullname) != 0)
175                    match = 0;
176                else if(nclistlength(testnode->array.dimsetall)
177                        != nclistlength(var->array.dimsetall))
178                    match = 0;
179                else for(d=0;d<nclistlength(testnode->array.dimsetall);d++) {
180                    CDFnode* vdim = (CDFnode*)nclistget(var->array.dimsetall,d);
181                    CDFnode* tdim = (CDFnode*)nclistget(testnode->array.dimsetall,d);
182                    if(vdim->dim.declsize != tdim->dim.declsize) {
183                        match = 0;
184                        break;
185                    }
186                }
187                if(match) {
188                    testnode->array.basevar = var;
189fprintf(stderr,"basevar invoked: %s\n",var->ncfullname);
190                }
191            }
192        }
193    }
194
195    /* Finally, verify unique names */
196    for(i=0;i<nclistlength(varnodes);i++) {
197        CDFnode* var1 = (CDFnode*)nclistget(varnodes,i);
198        if(var1->array.basevar != NULL) continue;
199        for(j=0;j<i;j++) {
200            CDFnode* var2 = (CDFnode*)nclistget(varnodes,j);
201            if(var2->array.basevar != NULL) continue;
202            if(strcmp(var1->ncfullname,var2->ncfullname)==0) {
203                PANIC1("duplicate var names: %s",var1->ncfullname);
204            }
205        }
206    }
207    return NC_NOERR;
208}
209
210
211/* locate and connect usable sequences and vars.
212A sequence is usable iff:
2131. it has a path from one of its subnodes to a leaf and that
214   path does not contain a sequence.
2152. No parent container has dimensions.
216*/
217
218NCerror
219sequencecheck3(NCDAPCOMMON* nccomm)
220{
221    (void)sequencecheck3r(nccomm->cdf.ddsroot,nccomm->cdf.varnodes,NULL);   
222    return NC_NOERR;
223}
224
225
226static NCerror
227sequencecheck3r(CDFnode* node, NClist* vars, CDFnode* topseq)
228{
229    unsigned int i;
230    NCerror err = NC_NOERR;
231    int ok = 0;
232    if(topseq == NULL && nclistlength(node->array.dimset0) > 0) {
233        err = NC_EINVAL; /* This container has dimensions, so no sequence within it
234                            can be usable */
235    } else if(node->nctype == NC_Sequence) {
236        /* Recursively walk the path for each subnode of this sequence node
237           looking for a path without any sequence */
238        for(i=0;i<nclistlength(node->subnodes);i++) {
239            CDFnode* sub = (CDFnode*)nclistget(node->subnodes,i);
240            err = sequencecheck3r(sub,vars,node);
241            if(err == NC_NOERR) ok = 1; /* there is at least 1 usable var below */
242        }
243        if(topseq == NULL && ok == 1) {
244            /* this sequence is usable because it has scalar container
245               (by construction) and has a path to a leaf without an intermediate
246               sequence. */
247            err = NC_NOERR;
248            node->usesequence = 1;
249        } else {
250            /* this sequence is unusable because it has no path
251               to a leaf without an intermediate sequence. */
252            node->usesequence = 0;
253            err = NC_EINVAL;
254        }
255    } else if(nclistcontains(vars,(ncelem)node)) {
256        /* If we reach a leaf, then topseq is usable, so save it */
257        node->array.sequence = topseq;
258    } else { /* Some kind of non-sequence container node with no dimensions */
259        /* recursively compute usability */
260        for(i=0;i<nclistlength(node->subnodes);i++) {
261            CDFnode* sub = (CDFnode*)nclistget(node->subnodes,i);
262            err = sequencecheck3r(sub,vars,topseq);
263            if(err == NC_NOERR) ok = 1;
264        }
265        err = (ok?NC_NOERR:NC_EINVAL);
266    }
267    return err;
268}
269
270/*
271OPeNDAP is in the process of changing servers so that
272partial grids are converted to structures.  However, not all
273servers do this: some elide the grid altogether, which can
274lead to ambiguities.  Handle this last case by attempting to
275convert the elided case to look like the newer structure
276case.  [for some reason, this code has been difficult to get
277right; I have rewritten 6 times and it probably is still not
278right.]
279
280Input is
281(1) the root of the dds that needs to be re-gridded
282(2) the full datadds tree that defines where the grids are.
283(3) the projections that were used to produce (1) from (2).
284*/
285
286NCerror
287regrid3(CDFnode* ddsroot, CDFnode* template, NClist* projections)
288{
289    NCerror ncstat = NC_NOERR;
290    NClist* newgrids = nclistnew();
291
292    /* The current regrid assumes that the ddsroot tree
293       has missing grids compared to the template.
294       It is also assumed that order of the nodes
295       in the ddsroot is the same as in the template.
296    */
297    if(ddsroot->tree->regridded) return NC_NOERR;
298
299#ifdef DEBUG
300fprintf(stderr,"regrid: ddsroot=%s\n",dumptree(ddsroot));
301fprintf(stderr,"regrid: template=%s\n",dumptree(template));
302#endif
303
304
305#ifdef PROJECTED
306    /* turn off the projection tag for all nodes */
307    unprojected3(template->tree->nodes);
308    /* Set the projection flag for all paths of all nodes
309       that are referenced in the projections that produced ddsroot.
310       This includes containers and subnodes. If there are no
311       projections then mark all nodes
312    */
313     projectall3(template->tree->nodes);
314#endif
315
316    if(simplenodematch34(ddsroot,template)) {
317        ncstat = regrid3r(ddsroot,template,newgrids);
318        ddsroot->tree->regridded = 1;
319    } else
320        ncstat = NC_EINVAL;
321    nclistfree(newgrids);
322    return ncstat;
323}
324
325#ifdef PROJECTED
326static void
327unprojected3(NClist* nodes)
328{
329    int i;
330    for(i=0;i<nclistlength(nodes);i++) {
331        CDFnode* node = (CDFnode*)nclistget(nodes,i);
332        node->projected = 0;
333    }
334}
335
336static void
337projectall3(NClist* nodes)
338{
339    int i;
340    for(i=0;i<nclistlength(nodes);i++) {
341        CDFnode* node = (CDFnode*)nclistget(nodes,i);
342        node->projected = 1;
343    }
344}
345
346static void
347projection3r(CDFnode* node)
348{
349    int i;
350    NClist* path = nclistnew();
351    collectnodepath3(node,path,!WITHDATASET);
352    for(i=0;i<nclistlength(path);i++) {
353        CDFnode* pathnode = (CDFnode*)nclistget(path,i);
354#ifdef DEBUG
355if(pathnode->projected == 0)
356fprintf(stderr,"projection: %s\n",makesimplepathstring3(pathnode));
357#endif
358        pathnode->projected = 1;
359    }
360    /* Now tag everything below me */
361    for(i=0;i<nclistlength(node->subnodes);i++) {
362        CDFnode* subnode = (CDFnode*)nclistget(node->subnodes,i);
363        projection3r(subnode);
364    }
365    nclistfree(path);
366}
367#endif /*PROJECTED*/
368
369/*
370Add in virtual structure nodes so that
371old style constrainted DDS and DATADDS
372look like the new style with structures.
373*/
374static NCerror
375regrid3r(CDFnode* node, CDFnode* template, NClist* gridnodes)
376{
377    unsigned int inode, itemp;
378    NCerror ncstat = NC_NOERR;
379
380    /* Try to match node's subnodes to a subset of the
381       template subnodes
382    */
383#ifdef DEBUG
384fprintf(stderr,"regrid: matched: %s -> %s\n",
385node->ocname,template->ocname);
386#endif
387    for(inode=0;inode<nclistlength(node->subnodes);inode++) {
388        CDFnode* subnode = (CDFnode*)nclistget(node->subnodes,inode);
389        int match = 0;
390        for(itemp=0;itemp<nclistlength(template->subnodes);itemp++) {
391            CDFnode* subtemp = (CDFnode*)nclistget(template->subnodes,itemp);
392            if(
393#ifdef PROJECTED
394                subtemp->projected &&
395#endif
396                simplenodematch34(subnode,subtemp)) {
397                ncstat = regrid3r(subnode,subtemp,gridnodes);
398                if(ncstat != NC_NOERR) return THROW(ncstat);
399                match = 1;
400#ifdef PROJECTED
401                subtemp->projected = 0; /*make sure we dont reuse this node*/
402#endif
403                break;
404            }
405        }
406        if(!match) { /* subnode has no match */
407            /* ok, see if we can regrid */
408            for(itemp=0;itemp<nclistlength(template->subnodes);itemp++) {
409                CDFnode* subtemp = (CDFnode*)nclistget(template->subnodes,itemp);
410#ifdef DEBUG
411fprintf(stderr,"regrid: inside: %s.%s :: %s.%s\n",
412node->ocname,subnode->ocname,
413template->ocname,subtemp->ocname);
414#endif
415                if(subtemp->nctype != NC_Grid)
416                    continue;
417#ifdef PROJECTED
418                if(!subtemp->projected) continue;
419#endif
420                ncstat = testregrid3(subnode,subtemp,gridnodes);
421                if(ncstat == NC_NOERR) {match=1; break;}
422            }
423            if(!match) {/* really no match */
424                ncstat = THROW(NC_EDDS); /* no match */
425            }
426        }
427    }
428    return THROW(ncstat);
429}
430
431/* See if this node can match a subnode of the template
432   as a grid, and if so, then rebuild the node graph.
433*/
434static NCerror
435testregrid3(CDFnode* node, CDFnode* template, NClist* gridnodes)
436{
437    int i,match;
438    NCerror ncstat = NC_NOERR;
439    ASSERT((template->nctype == NC_Grid));
440    { /* try to match inside the grid */
441        for(match=0,i=0;i<nclistlength(template->subnodes);i++) {
442            CDFnode* gridelem = (CDFnode*)nclistget(template->subnodes,i);
443            if(!simplenodematch34(gridelem,node))
444                continue;
445            ncstat = regrid3r(node,gridelem,gridnodes);
446            if(ncstat == NC_NOERR) {
447                /* create new grid node if not already created */
448                CDFnode* newgrid = NULL;
449                match = 1;
450                for(i=0;i<nclistlength(gridnodes);i++) {
451                    newgrid = (CDFnode*)nclistget(gridnodes,i);
452                    if(newgrid->template == template) break;
453                    newgrid = NULL;
454                }
455                if(newgrid == NULL) {
456                    newgrid = makenewgrid3(node,template);
457                    if(newgrid == NULL) {ncstat = NC_ENOMEM; goto done;}
458                    /* Insert the grid into node's parent */
459                    regridinsert(newgrid,node);
460                    nclistpush(gridnodes,(ncelem)newgrid);
461                    nclistpush(node->root->tree->nodes,(ncelem)newgrid);
462                } 
463                regridremove(newgrid, node);
464                node->container = newgrid;
465                nclistpush(newgrid->subnodes,(ncelem)node);
466                break; /* done with node */
467            }
468        }
469    }
470    if(!match) ncstat = NC_EDDS;
471done:
472    return ncstat;
473}
474
475
476static CDFnode*
477makenewgrid3(CDFnode* node, CDFnode* template)
478{
479    CDFnode* newgrid;
480    newgrid = (CDFnode*)calloc(1,sizeof(CDFnode));
481    if(newgrid == NULL) return NULL;
482    memset((void*)newgrid,0,sizeof(CDFnode));
483    newgrid->virtual = 1;
484    newgrid->ocname = nulldup(template->ocname);
485    newgrid->ncbasename = nulldup(template->ncbasename);
486    newgrid->nctype = NC_Grid;
487    newgrid->subnodes = nclistnew();
488    newgrid->container = node->container;
489    newgrid->template = template;
490    return newgrid;
491}
492
493static NCerror
494regridinsert(CDFnode* newgrid, CDFnode* node)
495{
496    int i;
497    CDFnode* parent;
498    /* Locate the index of the node in its current parent */
499    parent = node->container;
500    for(i=0;i<nclistlength(parent->subnodes);i++) {
501        CDFnode* subnode = (CDFnode*)nclistget(parent->subnodes,i);
502        if(subnode == node) {
503            /* Insert the grid right before this node */
504            nclistinsert(parent->subnodes,i,(ncelem)newgrid);
505            return NC_NOERR;
506        }
507    }
508    PANIC("regridinsert failure");
509    return NC_EINVAL;
510}
511
512static NCerror
513regridremove(CDFnode* newgrid, CDFnode* node)
514{
515    int i;
516    CDFnode* parent;
517    /* Locate the index of the node in its current parent and remove */
518    parent = node->container;
519    for(i=0;i<nclistlength(parent->subnodes);i++) {
520        CDFnode* subnode = (CDFnode*)nclistget(parent->subnodes,i);
521        if(subnode == node) {
522            nclistremove(parent->subnodes,i);
523            return NC_NOERR;
524        }
525    }
526    PANIC("regridremove failure");
527    return NC_EINVAL;
528}   
529
530/**
531
532Make the constrained dds nodes (root)
533point to the corresponding unconstrained
534dds nodes (fullroot).
535 */
536
537NCerror
538mapnodes3(CDFnode* root, CDFnode* fullroot)
539{
540    NCerror ncstat = NC_NOERR;
541    ASSERT(root != NULL && fullroot != NULL);
542    if(!simplenodematch34(root,fullroot))
543        {THROWCHK(ncstat=NC_EINVAL); goto done;}
544    /* clear out old associations*/
545    unmap3(root);
546    ncstat = mapnodes3r(root,fullroot,0);
547done:
548    return ncstat;
549}
550
551static NCerror
552mapnodes3r(CDFnode* connode, CDFnode* fullnode, int depth)
553{
554    unsigned int i,j;
555    NCerror ncstat = NC_NOERR;
556
557    ASSERT((simplenodematch34(connode,fullnode)));
558   
559#ifdef DEBUG
560{
561char* path1 = makecdfpathstring3(fullnode,".");
562char * path2 = makecdfpathstring3(connode,".");
563fprintf(stderr,"mapnode: %s->%s\n",path1,path2);
564nullfree(path1); nullfree(path2);
565}
566#endif
567
568    /* Map node */
569    mapfcn(connode,fullnode);
570
571    /* Try to match connode subnodes against fullnode subnodes */
572    ASSERT(nclistlength(connode->subnodes) <= nclistlength(fullnode->subnodes));
573
574    for(i=0;i<nclistlength(connode->subnodes);i++) {
575        CDFnode* consubnode = (CDFnode*)nclistget(connode->subnodes,i);
576        /* Search full subnodes for a matching subnode from con */
577        for(j=0;j<nclistlength(fullnode->subnodes);j++) {
578            CDFnode* fullsubnode = (CDFnode*)nclistget(fullnode->subnodes,j);
579            if(simplenodematch34(fullsubnode,consubnode)) {
580                ncstat = mapnodes3r(consubnode,fullsubnode,depth+1);
581                if(ncstat) goto done;
582            }
583        }
584    }
585done:
586    return THROW(ncstat);
587}
588
589
590/* The specific actions of a map are defined
591   by this function.
592*/
593static NCerror
594mapfcn(CDFnode* dstnode, CDFnode* srcnode)
595{
596    /* Mark node as having been mapped */
597    dstnode->visible = 1;
598    dstnode->basenode = srcnode;
599    return NC_NOERR;
600}
601
602void
603unmap3(CDFnode* root)
604{
605    unsigned int i;
606    CDFtree* tree = root->tree;
607    for(i=0;i<nclistlength(tree->nodes);i++) {
608        CDFnode* node = (CDFnode*)nclistget(tree->nodes,i);
609        node->basenode = NULL;
610        node->visible = 0;
611    }
612}
613
614/*
615Move dimension data from basenodes to nodes
616*/
617
618NCerror
619dimimprint3(NCDAPCOMMON* nccomm)
620{
621    NCerror ncstat = NC_NOERR;
622    NClist* allnodes;
623    int i,j;
624    CDFnode* basenode;
625
626    allnodes = nccomm->cdf.ddsroot->tree->nodes;
627    for(i=0;i<nclistlength(allnodes);i++) {
628        CDFnode* node = (CDFnode*)nclistget(allnodes,i);
629        int noderank, baserank;
630        /* Do dimension imprinting */
631        basenode = node->basenode;
632        if(basenode == NULL) continue;
633        noderank = nclistlength(node->array.dimset0);
634        baserank = nclistlength(basenode->array.dimset0);
635        if(noderank == 0) continue;
636        ASSERT(noderank == baserank);
637#ifdef DEBUG
638fprintf(stderr,"dimimprint %s/%d -> %s/%d\n",
639        makecdfpathstring3(basenode,"."),
640        noderank,
641        makecdfpathstring3(node,"."),
642        baserank);
643#endif
644        for(j=0;j<noderank;j++) {
645            CDFnode* dim = (CDFnode*)nclistget(node->array.dimset0,j);
646            CDFnode* basedim = (CDFnode*)nclistget(basenode->array.dimset0,j);
647            dim->dim.declsize0 = basedim->dim.declsize; 
648#ifdef DEBUG
649fprintf(stderr,"dimimprint: %d: %lu -> %lu\n",i,basedim->dim.declsize,dim->dim.declsize0);
650#endif
651        }
652    }
653    return ncstat;
654}
655
656static CDFnode*
657clonedim(NCDAPCOMMON* nccomm, CDFnode* dim, CDFnode* var)
658{
659    CDFnode* clone;
660    clone = makecdfnode34(nccomm,dim->ocname,OC_Dimension,
661                          OCNULL,dim->container);
662    /* Record its existence */
663    nclistpush(dim->container->root->tree->nodes,(ncelem)clone);
664    clone->dim = dim->dim; /* copy most everything */
665    clone->dim.dimflags |= CDFDIMCLONE;
666    clone->dim.array = var;
667    return clone;
668}
669
670static NClist*
671clonedimset3(NCDAPCOMMON* nccomm, NClist* dimset, CDFnode* var)
672{
673    NClist* result = nclistnew();
674    int i;
675    for(i=0;i<nclistlength(dimset);i++) {
676        CDFnode* dim = (CDFnode*)nclistget(dimset,i);
677        nclistpush(result,(ncelem)clonedim(nccomm,dim,var));
678    }
679    return result;
680}
681
682/* Define the dimsetplus list for a node */
683static NCerror
684definedimsetplus3(NCDAPCOMMON* nccomm, CDFnode* node)
685{
686    int ncstat = NC_NOERR;
687    NClist* dimset;
688    CDFnode* clone;
689
690    ASSERT(node->array.dimsetplus == NULL);
691    if(node->array.dimset0 == NULL)
692        dimset = nclistnew();
693    else { /* copy the dimset0 into dimset */
694        dimset = nclistclone(node->array.dimset0);
695    }
696    /* Insert the sequence or string dims */
697    if(node->array.stringdim != NULL) {
698        clone = node->array.stringdim;
699        nclistpush(dimset,(ncelem)clone);
700    }
701    if(node->array.seqdim != NULL) {
702        clone = node->array.seqdim;
703        nclistpush(dimset,(ncelem)clone);
704    }
705    node->array.dimsetplus = dimset;
706    return ncstat;
707}
708
709/* Define the dimsetall list for a node */
710static NCerror
711definedimsetall3(NCDAPCOMMON* nccomm, CDFnode* node)
712{
713    int i;
714    int ncstat = NC_NOERR;
715    NClist* dimsetall;
716
717    ASSERT(node->array.dimsetall == NULL);
718    if(node->container != NULL) {
719        if(node->container->array.dimsetall == NULL) {
720#ifdef DEBUG1
721fprintf(stderr,"dimsetall: recurse %s\n",node->container->ocname);
722#endif
723            ncstat = definedimsetall3(nccomm,node->container);
724            if(ncstat != NC_NOERR) return ncstat;
725        }
726        /* We need to clone the parent dimensions because we will be assigning
727           indices vis-a-vis this variable */
728        dimsetall = clonedimset3(nccomm,node->container->array.dimsetall,node);
729    } else
730        dimsetall = nclistnew();
731    /* concat parentall and dimset;*/
732    for(i=0;i<nclistlength(node->array.dimsetplus);i++) {
733        CDFnode* clone = (CDFnode*)nclistget(node->array.dimsetplus,i);
734        nclistpush(dimsetall,(ncelem)clone);
735    }
736    node->array.dimsetall = dimsetall;
737#ifdef DEBUG1
738fprintf(stderr,"dimsetall: |%s|=%d\n",node->ocname,nclistlength(dimsetall));
739#endif
740    return ncstat;
741}
742
743/* Define the dimsetplus and dimsetall lists for
744   all nodes with dimensions
745*/
746NCerror
747definedimsets3(NCDAPCOMMON* nccomm)
748{
749    int i;
750    int ncstat = NC_NOERR;
751    NClist* allnodes = nccomm->cdf.ddsroot->tree->nodes;
752
753    for(i=0;i<nclistlength(allnodes);i++) {
754        CDFnode* rankednode = (CDFnode*)nclistget(allnodes,i);
755        if(rankednode->nctype == NC_Dimension) continue; /* ignore */
756        ASSERT((rankednode->array.dimsetplus == NULL));
757        ncstat = definedimsetplus3(nccomm,rankednode);
758        if(ncstat != NC_NOERR) return ncstat;
759    }
760    for(i=0;i<nclistlength(allnodes);i++) {
761        CDFnode* rankednode = (CDFnode*)nclistget(allnodes,i);
762        if(rankednode->nctype == NC_Dimension) continue; /*ignore*/
763        ASSERT((rankednode->array.dimsetall == NULL));
764        ASSERT((rankednode->array.dimsetplus != NULL));
765        ncstat = definedimsetall3(nccomm,rankednode);
766        if(ncstat != NC_NOERR) return ncstat;
767    }     
768    return NC_NOERR;
769}
770
Note: See TracBrowser for help on using the repository browser.