source: XIOS/dev/dev_olga/extern/src_netcdf4/oc.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: 23.2 KB
Line 
1/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
2   See the COPYRIGHT file for more information. */
3
4#include "config.h"
5#include <stdlib.h>
6#include <assert.h>
7#include <string.h>
8
9#include "oc.h"
10#include "ocinternal.h"
11#include "occontent.h"
12#include "ocdebug.h"
13#include "ocdump.h"
14#include "oclog.h"
15#include "occlientparams.h"
16#include "ochttp.h"
17
18#undef TRACK
19
20/**************************************************/
21
22static int ocinitialized = 0;
23
24/**************************************************/
25/* Track legal ids */
26
27#ifdef OC_FASTCONSISTENCY
28
29#define ocverify(object) ((object) != NULL && (*(object) == OCMAGIC)?1:0)
30
31#define ocassign(object) ((OCobject)(object))
32#define ocassignall(list)
33
34#else /*!OC_FASTCONSISTENCY*/
35
36static OClist* ocmap = NULL;
37
38static int
39ocverify(unsigned long object)
40{
41    unsigned int i;
42    void** map = (void**)oclistcontents(ocmap);
43    unsigned int len = oclistlength(ocmap);
44#ifdef TRACK
45fprintf(stderr,"verify: %lu\n",object); fflush(stderr);
46#endif
47    if(object > 0) {
48        for(i=0;i<len;i++,map++) {
49            if(*map == (void*)object) {
50                return 1;
51            }
52        }
53    }
54    fprintf(stderr,"illegal object id: %lu\n",(unsigned long)object);
55    fflush(stderr);
56    return 0;
57}
58
59static OCobject
60ocassign(void* object)
61{
62#ifdef TRACK
63fprintf(stderr,"assign: %lu\n",(unsigned long)object); fflush(stderr);
64#endif
65    oclistpush(ocmap,(ocelem)object);
66    return (OCobject)object;
67}
68
69static void
70ocassignall(OClist* list)
71{
72    unsigned int i;
73    if(list != NULL)
74        for(i=0;i<oclistlength(list);i++) {
75            void* object = (void*)oclistget(list,i);
76#ifdef TRACK
77fprintf(stderr,"assign: %lu\n",(unsigned long)object); fflush(stderr);
78#endif
79            oclistpush(ocmap,(ocelem)object);
80        }
81}
82#endif /*!OC_FASTCONSISTENCY*/
83
84#define OCVERIFYX(T,s,x,r) if(!ocverify(x)) {return (r);}
85#define OCVERIFY(T,s,x) OCVERIFYX(T,s,x,OC_EINVAL)
86
87#define OCDEREF(T,s,x) (s)=(T)(x)
88
89/**************************************************/
90
91static int
92oc_initialize(void)
93{
94    int status = OC_NOERR;
95#ifndef OC_FASTCONSISTENCY
96    ocmap = oclistnew();   
97    oclistsetalloc(ocmap,1024);
98#endif
99    status = ocinternalinitialize();
100    ocinitialized = 1;
101    return status;
102}
103
104/**************************************************/
105
106OCerror
107oc_open(const char* url, OCconnection* connp)
108{
109    OCerror ocerr;
110    OCstate* state;
111    if(!ocinitialized) oc_initialize();
112    ocerr = ocopen(&state,url);
113    if(ocerr == OC_NOERR && connp) {
114        *connp = (OCconnection)ocassign(state);
115    }
116    return ocerr;
117}
118
119OCerror
120oc_close(OCconnection conn)
121{
122    OCstate* state;
123    OCVERIFY(OCstate*,state,conn);
124    OCDEREF(OCstate*,state,conn);
125    occlose(state);
126    return OC_NOERR;
127}
128
129/* Release/reclaim the tree of objects associated with a given root */
130OCerror
131oc_root_free(OCconnection conn, OCobject root0)
132{
133    OCnode* root;
134    OCVERIFY(OCnode*,root,root0);
135    OCDEREF(OCnode*,root,root0);
136
137    ocfreeroot(root);
138    return OC_NOERR;
139}
140
141/* Return the # of  OCobjects associated with a tree with specified root */
142unsigned int
143oc_inq_nobjects(OCconnection conn, OCobject root0)
144{
145    OCnode* root;
146    OClist* nodes;
147    unsigned int nobjects;
148    OCVERIFYX(OCnode*,root,root0,-1);
149    OCDEREF(OCnode*,root,root0);
150
151    if(root == NULL) return 0;
152    root = root->root;
153    if(root == NULL) return 0;
154    nodes = root->tree->nodes;
155    nobjects = oclistlength(nodes);
156    return nobjects;
157}
158
159/* Return all the OCobjects associated with a tree with specified root */
160OCobject*
161oc_inq_objects(OCconnection conn, OCobject root0)
162{
163    unsigned int i;
164    OCnode* root;
165    OClist* nodes;
166    OCobject* objects = NULL;
167    unsigned int nobjects;
168    OCVERIFYX(OCnode*,root,root0,OCNULL);
169    OCDEREF(OCnode*,root,root0);
170
171    if(root == NULL) return NULL;
172    root = root->root;
173    if(root == NULL) return NULL;
174    nodes = root->tree->nodes;
175    nobjects = oclistlength(nodes);
176    if(nodes != NULL && nobjects > 0) {
177        size_t len = sizeof(OCobject)*(1+nobjects);
178        objects = (OCobject*)ocmalloc(len);
179        for(i=0;i<oclistlength(nodes);i++) {
180            objects[i] = (OCobject)oclistget(nodes,i);
181        }
182        objects[nobjects] = OCNULL; /* null terminate */
183    }
184    return objects;
185}
186
187/* Return the text of the DDS or DAS as received from the server */
188/* Return NULL if no fetch was ever made. */
189const char*
190oc_inq_text(OCconnection conn, OCobject root0)
191{
192    OCnode* root;
193    OCVERIFYX(OCnode*,root,root0,NULL);
194    OCDEREF(OCnode*,root,root0);
195
196    if(root == NULL) return NULL;
197    root = root->root;
198    if(root == NULL) return NULL;
199    return root->tree->text;
200}
201
202OCerror
203oc_inq_object(OCconnection conn,
204          OCobject node0,
205          char** namep,
206          OCtype* objecttypep,
207          OCtype* primitivetypep, /* if objecttype == OC_Primitive */
208          OCobject* containerp,
209          unsigned int* rankp,
210          unsigned int* subnodesp,
211          unsigned int* nattrp)
212{
213    OCnode* node;
214    OCVERIFY(OCnode*,node,node0);
215    OCDEREF(OCnode*,node,node0);
216
217    if(namep) *namep = nulldup(node->name);
218    if(objecttypep) *objecttypep = node->octype;
219    if(primitivetypep) *primitivetypep = node->etype;
220    if(rankp) *rankp = node->array.rank;
221    if(containerp) *containerp = (OCobject)node->container;   
222    if(subnodesp) *subnodesp = oclistlength(node->subnodes);
223    if(nattrp) {
224        if(node->octype == OC_Attribute) {
225            *nattrp = oclistlength(node->att.values);
226        } else {
227            *nattrp = oclistlength(node->attributes);
228        }
229    }
230    return OC_NOERR;
231}
232
233/* Useful accessor functions */
234OCerror
235oc_inq_name(OCconnection conn, OCobject node0, char** namep)
236{
237    OCstate* state;
238    OCnode* node;
239    OCVERIFY(OCstate*,state,conn);
240    OCDEREF(OCstate*,state,conn);
241    OCVERIFY(OCnode*,node,node0);
242    OCDEREF(OCnode*,node,node0);
243
244    if(state == NULL || node == NULL) return OC_EINVAL;
245    if(namep) *namep = nulldup(node->name);
246    return OC_NOERR;
247}
248
249OCerror
250oc_inq_nsubnodes(OCconnection conn, OCobject node0, unsigned int* nsubnodesp)
251{
252    OCnode* node;
253    OCVERIFY(OCnode*,node,node0);
254    OCDEREF(OCnode*,node,node0);
255
256    if(nsubnodesp) *nsubnodesp = oclistlength(node->subnodes);
257    return OC_NOERR;
258}
259
260OCerror
261oc_inq_primtype(OCconnection conn, OCobject node0, OCtype* typep)
262{
263    OCnode* node;
264    OCVERIFY(OCnode*,node,node0);
265    OCDEREF(OCnode*,node,node0);
266
267    if(typep) *typep = node->etype;
268    return OC_NOERR;
269}
270
271/* Alias for oc_inq_class */
272OCerror
273oc_inq_type(OCconnection conn, OCobject node0, OCtype* typep)
274{
275    return oc_inq_class(conn,node0,typep);
276}
277
278OCerror
279oc_inq_class(OCconnection conn, OCobject node0, OCtype* typep)
280{
281    OCnode* node;
282    OCVERIFY(OCnode*,node,node0);
283    OCDEREF(OCnode*,node,node0);
284
285    if(typep) *typep = node->octype;
286    return OC_NOERR;
287}
288
289OCerror
290oc_inq_rank(OCconnection conn, OCobject node0, unsigned int* rankp)
291{
292    OCnode* node;
293    OCVERIFY(OCnode*,node,node0);
294    OCDEREF(OCnode*,node,node0);
295
296    if(rankp) *rankp = node->array.rank;
297    return OC_NOERR;
298}
299
300OCerror
301oc_inq_nattr(OCconnection conn, OCobject node0, unsigned int* nattrp)
302{
303    OCnode* node;
304    OCVERIFY(OCnode*,node,node0);
305    OCDEREF(OCnode*,node,node0);
306
307    if(nattrp) {
308        if(node->octype == OC_Attribute) {
309            *nattrp = oclistlength(node->att.values);
310        } else {
311            *nattrp = oclistlength(node->attributes);
312        }
313    }
314    return OC_NOERR;
315}
316
317OCerror
318oc_inq_root(OCconnection conn, OCobject node0, OCobject* rootp)
319{
320    OCnode* node;
321    OCVERIFY(OCnode*,node,node0);
322    OCDEREF(OCnode*,node,node0);
323
324    if(rootp) *rootp = (OCobject)node->root;
325    return OC_NOERR;
326}
327
328OCerror
329oc_inq_container(OCconnection conn, OCobject node0, OCobject* containerp)
330{
331    OCnode* node;
332    OCVERIFY(OCnode*,node,node0);
333    OCDEREF(OCnode*,node,node0);
334
335    if(containerp) *containerp = (OCobject)node->container;
336    return OC_NOERR;
337}
338
339/* Return the subnode objects, if any, for a given object */
340/* Caller must free returned list */
341OCerror
342oc_inq_subnodes(OCconnection conn, OCobject node0, OCobject** subnodesp)
343{
344    OCnode* node;
345    OCobject* subnodes = NULL;
346    unsigned int len;
347    OCVERIFY(OCnode*,node,node0);
348    OCDEREF(OCnode*,node,node0);
349
350    len = oclistlength(node->subnodes);
351    if(len > 0) {
352        unsigned int i;
353        subnodes = (OCobject*)occalloc(sizeof(OCobject),len+1);
354        for(i=0;i<len;i++) {
355            OCnode* ocnode = (OCnode*)oclistget(node->subnodes,i);
356            subnodes[i] = (OCobject)ocnode;
357        }       
358        subnodes[len] = OCNULL; /* NULL terminate */
359    }
360    if(subnodesp) *subnodesp = subnodes;
361    return OC_NOERR;
362}
363
364OCerror
365oc_inq_ith(OCconnection conn,
366           OCobject node0, unsigned int index, OCobject* subnodeidp)
367{
368    OCnode* node;
369    OCobject subnodeid = OCNULL;
370    unsigned int nsubnodes;
371    OCVERIFY(OCnode*,node,node0);
372    OCDEREF(OCnode*,node,node0);
373
374    nsubnodes = oclistlength(node->subnodes);
375    if(nsubnodes > 0 &&  index < nsubnodes) {
376        subnodeid = (OCobject)oclistget(node->subnodes,index);
377    } else
378        return OC_EINVAL;
379    if(subnodeidp) *subnodeidp = subnodeid;
380    return OC_NOERR;
381}
382
383/* Return the dimension objects, if any, for a given object */
384/* Caller must free returned dimids */
385OCerror
386oc_inq_dimset(OCconnection conn, OCobject node0, OCobject** dimids)
387{
388    OCnode* node;
389    OCobject* dims = NULL;
390    OCVERIFY(OCnode*,node,node0);
391    OCDEREF(OCnode*,node,node0);
392
393    if(node->array.rank > 0) {
394        unsigned int i;
395        dims = (OCobject*)occalloc(sizeof(OCobject),node->array.rank+1);
396        for(i=0;i<node->array.rank;i++) {
397            OCnode* dim = (OCnode*)oclistget(node->array.dimensions,i);
398            dims[i] = (OCobject)dim;
399        }       
400        dims[node->array.rank] = OCNULL;
401    }
402    if(dimids) *dimids = dims;
403    return OC_NOERR;
404}
405
406
407OCerror
408oc_inq_ithdim(OCconnection conn, OCobject node0, unsigned int index, OCobject* dimidp)
409{
410    OCnode* node;
411    OCobject dimid = OCNULL;
412    OCVERIFY(OCnode*,node,node0);
413    OCDEREF(OCnode*,node,node0);
414
415    if(node->array.rank > 0 && index < node->array.rank) {
416        dimid = (OCobject)oclistget(node->array.dimensions,index);
417    } else
418        return OC_EINVAL;
419    if(dimidp) *dimidp = dimid;
420    return OC_NOERR;
421}
422
423OCerror
424oc_inq_dim(OCconnection conn, OCobject node0, size_t* sizep, char** namep)
425{
426    OCnode* dim;
427    OCVERIFY(OCnode*,dim,node0);
428    OCDEREF(OCnode*,dim,node0);
429
430    if(dim->octype != OC_Dimension) return OC_EINVAL;
431    if(sizep) *sizep = dim->dim.declsize;
432    if(namep) *namep = nulldup(dim->name);
433    return OC_NOERR;
434}
435
436/* Obtain info about the ith attribute attached to a given DDS node*/
437
438/* This procedure returns the value as the original DAS string */
439OCerror
440oc_inq_attrstrings(OCconnection conn, OCobject node0, unsigned int i,
441                           char** namep, OCtype* octypep,
442                           unsigned int* nvaluesp, char*** stringsp)
443{
444    OCnode* node;
445    OCattribute* attr;
446    unsigned int nattrs;
447    OCVERIFY(OCnode*,node,node0);
448    OCDEREF(OCnode*,node,node0);
449
450    nattrs = oclistlength(node->attributes);
451    if(i >= nattrs) return OC_EINVAL;
452    attr = (OCattribute*)oclistget(node->attributes,i);
453    if(namep) *namep = strdup(attr->name);
454    if(octypep) *octypep = attr->etype;
455    if(nvaluesp) *nvaluesp = attr->nvalues;
456    if(stringsp) {
457        if(attr->nvalues > 0) {
458            size_t space = attr->nvalues * sizeof(char*);
459            char** strings = ocmalloc(space);
460            for(i=0;i<attr->nvalues;i++)
461                strings[i] = nulldup(attr->values[i]);
462            *stringsp = strings;
463        } else
464            *stringsp = NULL;
465    }
466    return OC_NOERR;   
467}
468
469/* This procedure returns the value as the default binary value
470   corresponding to the string value
471*/
472
473OCerror
474oc_inq_attr(OCconnection conn, OCobject node0, unsigned int i,
475            char** namep, OCtype* octypep, unsigned int* nvaluesp, void** valuesp)
476{
477    OCnode* node;
478    OCattribute* attr;
479    unsigned int nattrs;
480    OCVERIFY(OCnode*,node,node0);
481    OCDEREF(OCnode*,node,node0);
482
483    nattrs = oclistlength(node->attributes);
484    if(i >= nattrs) return OC_EINVAL;
485    attr = (OCattribute*)oclistget(node->attributes,i);
486    if(namep) *namep = strdup(attr->name);
487    if(octypep) *octypep = attr->etype;
488    if(nvaluesp) *nvaluesp = attr->nvalues;
489    if(valuesp && attr->nvalues > 0) {
490        void* memory = NULL;
491        memory = oclinearize(attr->etype,attr->nvalues,attr->values);
492        *valuesp = memory;
493    }
494    return OC_NOERR;   
495}
496
497/* Convenience function */
498void
499oc_attr_reclaim(OCtype etype, unsigned int nvalues, void* values)
500{
501    if(nvalues == 0 || values == NULL) return;
502    if(etype == OC_String || etype == OC_URL) {
503        unsigned int i;
504        char** strings = (char**)values;
505        for(i=0;i<nvalues;i++) {ocfree(strings[i]);}   
506    }
507    ocfree(values);   
508}
509
510OCerror
511oc_inq_dasattr_nvalues(OCconnection conn, OCobject node0,
512                        unsigned int* nvaluesp)
513{
514    OCnode* attr;
515    OCVERIFY(OCnode*,attr,node0);
516    OCDEREF(OCnode*,attr,node0);
517    if(attr->octype != OC_Attribute) return OC_EINVAL;
518    if(nvaluesp) *nvaluesp = oclistlength(attr->att.values);
519    return OC_NOERR;
520}
521
522OCerror
523oc_inq_dasattr(OCconnection conn, OCobject node0, unsigned int i,
524               OCtype* primtypep, char** valuep)
525{
526    OCnode* attr;
527    unsigned int nvalues;
528    OCVERIFY(OCnode*,attr,node0);
529    OCDEREF(OCnode*,attr,node0);
530
531    if(attr->octype != OC_Attribute) return OC_EINVAL;
532    nvalues = oclistlength(attr->att.values);
533    if(i >= nvalues) return OC_EINVAL;
534    if(valuep) *valuep = nulldup((char*)oclistget(attr->att.values,i));
535    if(primtypep) *primtypep = attr->etype;
536    return OC_NOERR;
537}
538
539/**************************************************/
540/* Fetch and parse a given class of DXD the server specified
541   at open time, and using a specified set of constraints.
542   Return the root node of the parsed tree of objects.
543*/
544OCerror oc_fetch(OCconnection conn, const char* constraint,
545                 OCdxd dxdkind, OCobject* rootp)
546{
547    return oc_fetchf(conn,constraint,dxdkind,0,rootp);
548}
549
550OCerror oc_fetchf(OCconnection conn, const char* constraint,
551                 OCdxd dxdkind, OCflags flags, OCobject* rootp)
552{
553    OCstate* state;
554    OCerror ocerr = OC_NOERR;
555    OCnode* root;
556    OCVERIFY(OCstate*,state,conn);
557    OCDEREF(OCstate*,state,conn);
558
559    ocerr = ocfetchf(state,constraint,dxdkind,flags,&root);
560    if(ocerr) return ocerr;
561
562    ocassignall(root->tree->nodes);
563    if(rootp) *rootp = (OCobject)ocassign(root);
564    return ocerr;
565}
566
567
568OCerror
569oc_data_root(OCconnection conn, OCobject root0, OCdata content0)
570{
571    OCstate* state;
572    OCnode* root;
573    OCcontent* content;
574    OCerror ocerr = OC_NOERR;
575    OCVERIFY(OCstate*,state,conn);
576    OCDEREF(OCstate*,state,conn);
577    OCVERIFY(OCnode*,root,root0);
578    OCDEREF(OCnode*,root,root0);
579    OCVERIFY(OCcontent*,content,content0);
580    OCDEREF(OCcontent*,content,content0);
581
582    if(root->tree == NULL) {OCTHROWCHK((ocerr=OC_EINVAL)); goto fail;}
583    ocerr = ocrootdata(state,root,content);
584
585fail:
586    return ocerr;
587}
588
589OCdata
590oc_data_new(OCconnection conn)
591{
592    OCstate* state;
593    OCVERIFYX(OCstate*,state,conn,OCNULL);
594    OCDEREF(OCstate*,state,conn);
595
596    return (OCdata)ocassign(ocnewcontent(state));
597}
598
599OCerror
600oc_data_free(OCconnection conn, OCdata content0)
601{
602    OCstate* state;
603    OCcontent* content;
604    if(content0 == OCNULL) return OC_NOERR;
605    OCVERIFY(OCstate*,state,conn);
606    OCDEREF(OCstate*,state,conn);
607    OCVERIFY(OCcontent*,content,content0);
608    OCDEREF(OCcontent*,content,content0);
609
610    ocfreecontent(state,content);
611    return OC_NOERR;
612}
613
614OCerror
615oc_data_ith(OCconnection conn, OCdata parentdata, size_t index, OCdata subdata)
616{
617    OCstate* state;
618    OCcontent* parent;
619    OCcontent* child;
620    OCerror ocerr = OC_NOERR;
621    OCVERIFY(OCstate*,state,conn);
622    OCDEREF(OCstate*,state,conn);
623    OCVERIFY(OCcontent*,parent,parentdata);
624    OCDEREF(OCcontent*,parent,parentdata);
625    OCVERIFY(OCcontent*,child,subdata);
626    OCDEREF(OCcontent*,child,subdata);
627    ocerr = ocdataith(state,parent,index,child);
628    return ocerr;
629}
630
631OCerror
632oc_data_get(OCconnection conn, OCdata currentcontent,
633            void* memory, size_t memsize, size_t start, size_t count)
634{
635    OCstate* state;
636    OCcontent* current;
637    OCerror ocerr = OC_NOERR;
638    OCVERIFY(OCstate*,state,conn);
639    OCDEREF(OCstate*,state,conn);
640    OCVERIFY(OCcontent*,current,currentcontent);
641    OCDEREF(OCcontent*,current,currentcontent);
642
643    ocerr = ocgetcontent(state,current,memory,memsize,start,count);
644
645    if(ocerr == OC_EDATADDS) ocdataddsmsg(state,current->tree);
646
647    return ocerr;
648}
649
650OCerror
651oc_data_count(OCconnection conn, OCdata content0, size_t* sizep)
652{
653    OCstate* state;
654    OCcontent* current;
655    OCerror ocerr = OC_NOERR;
656    OCVERIFY(OCstate*,state,conn);
657    OCDEREF(OCstate*,state,conn);
658    OCVERIFY(OCcontent*,current,content0);
659    OCDEREF(OCcontent*,current,content0);
660    ocerr = ocdatacount(state, current, sizep);
661    return ocerr;
662}
663
664OCerror
665oc_data_index(OCconnection conn, OCdata content0, size_t* sizep)
666{
667    OCcontent* current;
668    OCerror ocerr = OC_NOERR;
669    OCVERIFY(OCcontent*,current,content0);
670    OCDEREF(OCcontent*,current,content0);
671
672    if(sizep)
673        *sizep = (current->cache.valid ? current->cache.index : 0);
674    return ocerr;
675}
676
677OCerror
678oc_data_object(OCconnection conn, OCdata content0, OCobject* op)
679{
680    OCcontent* current;
681    OCerror ocerr = OC_NOERR;
682    OCVERIFY(OCcontent*,current,content0);
683    OCDEREF(OCcontent*,current,content0);
684
685    if(op) *op = (OCobject)current->node;
686    return ocerr;
687}
688
689OCerror
690oc_data_mode(OCconnection conn, OCdata content0, OCmode* modep)
691{
692    OCcontent* current;
693    OCerror ocerr = OC_NOERR;
694    OCVERIFY(OCcontent*,current,content0);
695    OCDEREF(OCcontent*,current,content0);
696
697    if(modep) *modep = current->mode;
698    return ocerr;
699}
700
701/**************************************************/
702/* OCtype management */
703size_t oc_typesize(OCtype etype)
704{
705    return octypesize(etype);
706}
707
708const char*
709oc_typetostring(OCtype octype)
710{
711    return octypetoddsstring(octype);
712}
713
714OCerror
715oc_typeprint(OCtype etype, char* buf, size_t bufsize, void* value)
716{
717    return octypeprint(etype,buf,bufsize,value);
718}
719
720/**************************************************/
721/* The oc_logXXX procedures are define in oclog.c */
722
723/**************************************************/
724/* Miscellaneous */
725
726const char*
727oc_errstring(int err)
728{
729    return ocerrstring(err);
730}
731
732/* Get clientparameters from the URL */
733const char*
734oc_clientparam_get(OCconnection conn, const char* param)
735{
736    OCstate* state;
737    OCVERIFYX(OCstate*,state,conn,NULL);
738    OCDEREF(OCstate*,state,conn);
739
740    return ocparamlookup(state,param);
741}
742
743#ifdef OCIGNORE
744/* Delete client parameter
745   return value:
746        OC_NOERR => defined; deletion performed
747        OC_EINVAL => not already defined
748*/
749OCerror
750oc_clientparam_delete(OCconnection conn, const char* param)
751{
752    OCstate* state;
753    OCVERIFY(OCstate*,state,conn);
754    OCDEREF(OCstate*,state,conn);
755
756    return ocparamdelete(state->clientparams,param);
757}
758
759/* Insert client parameter
760   return value:
761        OC_NOERR => not already define; insertion performed
762        OC_EINVAL => already defined
763*/
764OCerror
765oc_clientparam_insert(OCconnection conn, const char* param, const char* value)
766{
767    OCstate* state;
768    OCVERIFY(OCstate*,state,conn);
769    OCDEREF(OCstate*,state,conn);
770
771    state->clientparams = dapparaminsert(state->clientparams,param,value);
772    return OC_NOERR;
773}
774
775/* Replace client parameter
776   return value:
777        OC_NOERR => already define; replacement performed
778        OC_EINVAL => not already defined
779*/
780OCerror
781oc_clientparam_replace(OCconnection conn, const char* param, const char* value)
782{
783    OCstate* state;
784    OCVERIFY(OCstate*,state,conn);
785    OCDEREF(OCstate*,state,conn);
786
787    return dapparamreplace(state->clientparams,param,value);
788}
789#endif
790
791OCerror
792oc_dd(OCconnection conn, OCobject root0, int level)
793{
794    OCstate* state;
795    OCnode* root;
796    OCVERIFY(OCstate*,state,conn);
797    OCDEREF(OCstate*,state,conn);
798    OCVERIFY(OCnode*,root,root0);
799    OCDEREF(OCnode*,root,root0);
800
801    ocdd(state,root,1,level);
802    return OC_NOERR;
803}
804
805OCerror
806oc_ddnode(OCconnection conn, OCobject root0)
807{
808    OCnode* root;
809    OCVERIFY(OCnode*,root,root0);
810    OCDEREF(OCnode*,root,root0);
811
812    ocdumpnode(root);
813    return OC_NOERR;
814}
815
816/* Merge a specified DAS into a specified DDS or DATADDS */
817OCerror
818oc_attach_das(OCconnection conn, OCobject dasroot, OCobject ddsroot)
819{
820    OCstate* state;
821    OCnode* das;
822    OCnode* dds;
823    OCVERIFY(OCstate*,state,conn);
824    OCDEREF(OCstate*,state,conn);
825    OCVERIFY(OCnode*,das,dasroot);
826    OCDEREF(OCnode*,das,dasroot);
827    OCVERIFY(OCnode*,dds,ddsroot);
828    OCDEREF(OCnode*,dds,ddsroot);
829
830    return ocddsdasmerge(state,das,dds);
831}
832
833#if 0
834/*
835I suppressed this operation because I realized that it
836appears to be impossible to implement correctly in general.
837It also exposes a flaw in the protocol.
838If I have a dds with two identical Grids, G1 and G2,
839and I ask for the projection ?G1.temp,G2.temp,
840then I get back a DATADDS with duplicated temp fields,
841which means the DATADDS is illegal.  The problem is that
842the protocol throws away important scoping information
843about the fact that each temp field is part of a different
844grid.
845*/
846/* Connect a specified DATADDS tree to a specified DDS tree */
847OCerror
848oc_attach_datadds(OCconnection conn, OCobject dataddsroot, OCobject ddsroot)
849{
850    OCstate* state;
851    OCnode* dxd;
852    OCnode* dds;
853    OCVERIFY(OCstate*,state,conn);
854    OCDEREF(OCstate*,state,conn);
855    OCVERIFY(OCnode*,dxd,dataddsroot);
856    OCDEREF(OCnode*,dxd,dataddsroot);
857    OCVERIFY(OCnode*,dds,ddsroot);
858    OCDEREF(OCnode*,dds,ddsroot);
859
860    /* get the true roots */
861    dds = dds->root;
862    dxd = dxd->root;
863    if(dds == NULL || dxd == NULL) return OC_EBADID;   
864    /* correlate the DATADDS to the DDS */
865    return occorrelate(dxd,dds);
866}
867
868/* Return the attached DATADDS object for a given DDS object */
869OCerror oc_inq_datadds(OCconnection conn, OCobject dds0, OCobject* dataddsp)
870{
871    OCstate* state;
872    OCnode* dds;
873    OCVERIFY(OCstate*,state,conn);
874    OCDEREF(OCstate*,state,conn);
875    OCVERIFY(OCnode*,dds,dds0);
876    OCDEREF(OCnode*,dds,dds0);
877
878    if(dataddsp) *dataddsp = (OCobject)dds->datadds;
879    return OC_NOERR;
880}
881#endif
882
883/**************************************************/
884
885OCerror
886oc_svcerrordata(OCconnection conn, char** codep,
887                               char** msgp, long* httpp)
888{
889    OCstate* state;
890    OCVERIFY(OCstate*,state,conn);
891    OCDEREF(OCstate*,state,conn);
892    return ocsvcerrordata(state,codep,msgp,httpp);
893}
894
895
896/**************************************************/
897/* Experimental: this is useful for the netcdf
898   DRNO project.
899*/
900
901/* New 10/31/2009: return the size (in bytes)
902   of the fetched datadds.
903*/
904
905OCerror
906oc_raw_xdrsize(OCconnection conn, OCobject root0, size_t* sizep)
907{
908    OCnode* root;
909    OCerror ocerr = OC_NOERR;
910    OCVERIFY(OCnode*,root,root0);
911    OCDEREF(OCnode*,root,root0);
912
913    if(sizep == NULL) goto done;
914    if(root->tree == NULL || root->tree->dxdclass != OCDATADDS)
915        {OCTHROWCHK((ocerr=OC_EINVAL)); goto done;}
916    if(sizep) *sizep = root->tree->data.datasize;
917
918done:
919    return ocerr;
920}
921
922/* Resend a url as a head request to check the Last-Modified time */
923OCerror
924oc_update_lastmodified_data(OCconnection conn)
925{
926    OCstate* state;
927    OCVERIFY(OCstate*,state,conn);
928    OCDEREF(OCstate*,state,conn);
929    return ocupdatelastmodifieddata(state);
930}
931
932long
933oc_get_lastmodified_data(OCconnection conn)
934{
935    OCstate* state;
936    OCVERIFY(OCstate*,state,conn);
937    OCDEREF(OCstate*,state,conn);
938    return state->datalastmodified;
939}
940
941int
942oc_dumpnode(OCconnection conn, OCobject root0)
943{
944    OCnode* root;
945    OCerror ocerr = OC_NOERR;
946    OCVERIFY(OCnode*,root,root0);
947    OCDEREF(OCnode*,root,root0);
948    ocdumpnode(root);
949    return ocerr;
950}
951
952OCerror
953oc_ping(const char* url)
954{
955    return ocping(url);
956}
957   
Note: See TracBrowser for help on using the repository browser.