source: XIOS/dev/dev_olga/extern/src_netcdf4/ocutil.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: 11.0 KB
Line 
1/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
2   See the COPYRIGHT file for more information. */
3
4#include "config.h"
5#ifdef HAVE_UNISTD_H
6#include <unistd.h>
7#endif
8#include <fcntl.h>
9#include "ocinternal.h"
10#include "ocdebug.h"
11
12#ifdef WIN32
13#define snprintf _snprintf
14#endif
15
16/* Order is important: longest first */
17static char* DDSdatamarks[3] = {"Data:\r\n","Data:\n",(char*)NULL};
18
19/* Not all systems have strndup, so provide one*/
20char*
21ocstrndup(const char* s, size_t len)
22{
23    char* dup;
24    if(s == NULL) return NULL;
25    dup = (char*)ocmalloc(len+1);
26    MEMCHECK(dup,NULL);
27    memcpy((void*)dup,s,len);
28    dup[len] = '\0';
29    return dup;
30}
31
32/* Do not trust strncmp semantics */
33int
34ocstrncmp(const char* s1, const char* s2, size_t len)
35{
36    const char *p,*q;
37    if(s1 == s2) return 0;
38    if(s1 == NULL) return -1;
39    if(s2 == NULL) return +1;
40    for(p=s1,q=s2;len > 0;p++,q++,len--) {
41        if(*p == 0 && *q == 0) return 0; /* *p == *q == 0 */
42        if(*p != *q)
43            return (*p - *q);   
44    }
45    /* 1st len chars are same */
46    return 0;
47}
48
49
50void
51makedimlist(OClist* path, OClist* dims)
52{
53    unsigned int i,j;
54    for(i=0;i<oclistlength(path);i++) {
55        OCnode* node = (OCnode*)oclistget(path,i);
56        unsigned int rank = node->array.rank;
57        for(j=0;j<rank;j++) {
58            OCnode* dim = (OCnode*)oclistget(node->array.dimensions,j);
59            oclistpush(dims,(ocelem)dim);
60        }
61    }
62}
63
64void
65ocfreeprojectionclause(OCprojectionclause* clause)
66{
67    if(clause->target != NULL) free(clause->target);
68    while(oclistlength(clause->indexsets) > 0) {
69        OClist* slices = (OClist*)oclistpop(clause->indexsets);
70        while(oclistlength(slices) > 0) {
71            OCslice* slice = (OCslice*)oclistpop(slices);
72            if(slice != NULL) free(slice);
73        }
74        oclistfree(slices);
75    }
76    oclistfree(clause->indexsets);
77    free(clause);
78}
79
80static void
81freeAttributes(OClist* attset)
82{
83    unsigned int i,j;
84    for(i=0;i<oclistlength(attset);i++) {
85        OCattribute* att = (OCattribute*)oclistget(attset,i);
86        if(att->name != NULL) free(att->name);
87        if(att->etype == OC_String || att->etype == OC_URL) {
88            for(j=0;j<att->nvalues;j++) {
89                char* s = ((char**)att->values)[j];
90                if(s != NULL) free(s);
91            }
92        } else {
93            free(att->values);
94        }
95    }
96}
97
98void
99freeOCnode(OCnode* cdf, int deep)
100{
101    unsigned int i;
102    if(cdf == NULL) return;
103    if(cdf->name != NULL) free(cdf->name);
104    if(cdf->fullname != NULL) free(cdf->fullname);
105    if(cdf->attributes != NULL) freeAttributes(cdf->attributes);
106    if(cdf->subnodes != NULL) {
107        if(deep) {
108            for(i=0;i<oclistlength(cdf->subnodes);i++) {
109                OCnode* node = (OCnode*)oclistget(cdf->subnodes,i);
110                freeOCnode(node,deep);
111            }
112        }
113        oclistfree(cdf->subnodes);
114    }
115    free(cdf);
116}
117
118int
119findbod(OCbytes* buffer, size_t* bodp, size_t* ddslenp)
120{
121    unsigned int i;
122    char* content;
123    size_t len = ocbyteslength(buffer);
124    char** marks;
125   
126    content = ocbytescontents(buffer);
127
128    for(marks = DDSdatamarks;*marks;marks++) {
129        char* mark = *marks;
130        int tlen = strlen(mark);
131        for(i=0;i<len;i++) {
132            if((i+tlen) <= len
133                && (ocstrncmp(content+i,mark,tlen)==0)) {
134               *ddslenp = i;
135                i += tlen;
136                *bodp = i;
137                return 1;
138            }
139        }
140    }
141    *ddslenp = 0;
142    *bodp = 0;
143    return 0; /* tag not found; not necessarily an error*/
144}
145
146/* Compute total # of elements if dimensioned*/
147size_t
148totaldimsize(OCnode* node)
149{
150    unsigned int i;
151    size_t count = 1;
152    for(i=0;i<node->array.rank;i++) {
153        OCnode* dim = (OCnode*)oclistget(node->array.dimensions,i);
154        count *= (dim->dim.declsize);
155    }
156    return count;
157}
158
159#ifdef OCIGNORE
160size_t
161totaldimsize(unsigned int rank, size_t* dimsizes)
162{
163    unsigned int i;
164    int unlim = 0;
165    unsigned long size = 1;
166    for(i=0;i<rank;i++) {
167        if(dimsizes[i] != 0) size = (size * dimsizes[i]); else unlim = 1;
168    }
169    return size;
170}
171#endif
172
173size_t
174octypesize(OCtype etype)
175{
176    switch (etype) {
177    case OC_Char:       return sizeof(char);
178    case OC_Byte:       return sizeof(signed char);
179    case OC_UByte:      return sizeof(unsigned char);
180    case OC_Int16:      return sizeof(short);
181    case OC_UInt16:     return sizeof(unsigned short);
182    case OC_Int32:      return sizeof(int);
183    case OC_UInt32:     return sizeof(unsigned int);
184    case OC_Float32:    return sizeof(float);
185    case OC_Float64:    return sizeof(double);
186#ifdef HAVE_LONG_LONG_INT
187    case OC_Int64:      return sizeof(long long);
188    case OC_UInt64:     return sizeof(unsigned long long);
189#endif
190    case OC_String:     return sizeof(char*);
191    case OC_URL:        return sizeof(char*);
192    default: break;     /* Ignore all others */
193    }
194    return 0;
195}
196
197char*
198octypetostring(OCtype octype)
199{
200    switch (octype) {
201    case OC_NAT:          return "OC_NAT";
202    case OC_Char:         return "OC_Char";
203    case OC_Byte:         return "OC_Byte";
204    case OC_UByte:         return "OC_UByte";
205    case OC_Int16:        return "OC_Int16";
206    case OC_UInt16:       return "OC_UInt16";
207    case OC_Int32:        return "OC_Int32";
208    case OC_UInt32:       return "OC_UInt32";
209    case OC_Int64:        return "OC_Int64";
210    case OC_UInt64:       return "OC_UInt64";
211    case OC_Float32:      return "OC_Float32";
212    case OC_Float64:      return "OC_Float64";
213    case OC_String:       return "OC_String";
214    case OC_URL:          return "OC_URL";
215    /* Non-primitives*/
216    case OC_Dataset:      return "OC_Dataset";
217    case OC_Sequence:     return "OC_Sequence";
218    case OC_Grid:         return "OC_Grid";
219    case OC_Structure:    return "OC_Structure";
220    case OC_Dimension:    return "OC_Dimension";
221    case OC_Attribute:    return "OC_Attribute";
222    case OC_Attributeset: return "OC_Attributeset";
223    case OC_Primitive:    return "OC_Primitive";
224    default: break;
225    }
226    return NULL;
227}
228
229char*
230octypetoddsstring(OCtype octype)
231{
232    switch (octype) {
233    case OC_Byte:         return "Byte";
234    case OC_Int16:        return "Int16";
235    case OC_UInt16:       return "UInt16";
236    case OC_Int32:        return "Int32";
237    case OC_UInt32:       return "UInt32";
238    case OC_Float32:      return "Float32";
239    case OC_Float64:      return "Float64";
240    case OC_String:       return "String";
241    case OC_URL:          return "Url";
242    default: break;
243    }
244    return "<unknown>";
245}
246
247
248OCerror
249octypeprint(OCtype etype, char* buf, size_t bufsize, void* value)
250{
251    if(buf == NULL || bufsize == 0 || value == NULL) return OC_EINVAL;
252    buf[0] = '\0';
253    switch (etype) {
254    case OC_Char:
255        snprintf(buf,bufsize,"'%c'",*(char*)value);
256        break;
257    case OC_Byte:
258        snprintf(buf,bufsize,"%d",*(signed char*)value);
259        break;
260    case OC_UByte:
261        snprintf(buf,bufsize,"%u",*(unsigned char*)value);
262        break;
263    case OC_Int16:
264        snprintf(buf,bufsize,"%d",*(short*)value);
265        break;
266    case OC_UInt16:
267        snprintf(buf,bufsize,"%u",*(unsigned short*)value);
268        break;
269    case OC_Int32:
270        snprintf(buf,bufsize,"%d",*(int*)value);
271        break;
272    case OC_UInt32:
273        snprintf(buf,bufsize,"%u",*(unsigned int*)value);
274        break;
275    case OC_Float32:
276        snprintf(buf,bufsize,"%g",*(float*)value);
277        break;
278    case OC_Float64:
279        snprintf(buf,bufsize,"%g",*(double*)value);
280        break;
281#ifdef HAVE_LONG_LONG_INT
282    case OC_Int64:
283        snprintf(buf,bufsize,"%lld",*(long long*)value);
284        break;
285    case OC_UInt64:
286        snprintf(buf,bufsize,"%llu",*(unsigned long long*)value);
287        break;
288#endif
289    case OC_String:
290    case OC_URL: {
291        char* s = *(char**)value;
292        snprintf(buf,bufsize,"\"%s\"",s);
293        } break;
294    default: break;
295    }
296    return OC_NOERR;
297}
298
299size_t
300xxdrsize(OCtype etype)
301{
302    switch (etype) {
303    case OC_Char:
304    case OC_Byte:
305    case OC_UByte:
306    case OC_Int16:
307    case OC_UInt16:
308    case OC_Int32:
309    case OC_UInt32:
310        return XDRUNIT;
311    case OC_Int64:
312    case OC_UInt64:
313        return (2*XDRUNIT);
314    case OC_Float32:
315        return XDRUNIT;
316    case OC_Float64:
317        return (2*XDRUNIT);
318    case OC_String:
319    case OC_URL:
320    default: break;
321    }
322    return 0;
323}
324
325/**************************************/
326
327char*
328ocerrstring(int err)
329{
330    if(err == 0) return "no error";
331    if(err > 0) return strerror(err);
332    switch (err) {
333        case OC_EBADID:
334            return "OC_EBADID: Not a valid ID";
335        case OC_EINVAL:
336            return "OC_EINVAL: Invalid argument";
337        case OC_EPERM:
338            return "OC_EPERM: Write to read only";
339        case OC_EINVALCOORDS:
340            return "OC_EINVALCOORDS: Index exceeds dimension bound";
341        case OC_ENOTVAR:
342            return "OC_ENOTVAR: Variable not found";
343        case OC_ECHAR:
344            return "OC_ECHAR: Attempt to convert between text & numbers";
345        case OC_EEDGE:
346            return "OC_EEDGE: Start+count exceeds dimension bound";
347        case OC_ESTRIDE:
348            return "OC_ESTRIDE: Illegal stride";
349        case OC_ENOMEM:
350            return "OC_ENOMEM: Memory allocation (malloc) failure";
351        case OC_EDIMSIZE:
352            return "OC_EDIMSIZE: Invalid dimension size";
353        case OC_EDAP:
354            return "OC_EDAP: DAP failure";
355        case OC_EXDR:
356            return "OC_EXDR: XDR failure";
357        case OC_ECURL:
358            return "OC_ECURL: libcurl failure";
359        case OC_EBADURL:
360            return "OC_EBADURL: malformed url";
361        case OC_EBADVAR:
362            return "OC_EBADVAR: no such variable";
363        case OC_EOPEN:
364            return "OC_EOPEN: temporary file open failed";     
365        case OC_EIO:
366            return "OC_EIO: I/O failure";
367        case OC_ENODATA:
368            return "OC_ENODATA: Variable has no data in DAP request";
369        case OC_EDAPSVC:
370            return "OC_EDAPSVC: DAP Server error";
371        case OC_ENAMEINUSE:
372            return "OC_ENAMEINUSE: Duplicate name in DDS";
373        case OC_EDAS:
374            return "OC_EDAS: Malformed or unreadable DAS";
375        case OC_EDDS:
376            return "OC_EDDS: Malformed or unreadable DDS";
377        case OC_EDATADDS:
378            return "OC_EDATADDS: Malformed or unreadable DATADDS";
379        case OC_ERCFILE:
380            return "OC_ERCFILE: Malformed or unreadable run-time configuration file";
381        case OC_ENOFILE:
382            return "OC_ENOFILE: cannot read content of URL";
383        default: break;
384    }
385    return "<unknown error code>";
386}
387
388OCerror
389ocsvcerrordata(OCstate* state, char** codep, char** msgp, long* httpp)
390{
391    if(codep) *codep = state->error.code;
392    if(msgp) *msgp = state->error.message;
393    if(httpp) *httpp = state->error.httpcode;
394    return OC_NOERR;   
395}
396
397/* if we get OC_EDATADDS error, then try to capture any
398   error message and log it; assumes that in this case,
399   the datadds is not big.
400*/
401void
402ocdataddsmsg(OCstate* state, OCtree* tree)
403{
404#define ERRCHUNK 1024
405#define ERRFILL ' '
406#define ERRTAG "Error {"
407    unsigned int i,j,len;
408    XXDR* xdrs;
409    char* contents;
410    off_t ckp;
411
412    if(tree == NULL) return;
413    /* get available space */
414    xdrs = tree->data.xdrs;
415    len = xxdr_length(xdrs);
416    if(len < strlen(ERRTAG))
417        return; /* no room */
418    ckp = xxdr_getpos(xdrs);
419    xxdr_setpos(xdrs,0);
420    /* read the whole thing */
421    contents = (char*)malloc(len+1);
422    xxdr_getbytes(xdrs,contents,len);
423    contents[len] = '\0';
424    /* Look for error tag */
425    for(i=0;i<len;i++) {
426        if(ocstrncmp(contents+i,ERRTAG,strlen(ERRTAG))==0) {
427            /* log the error message */
428            /* Do a quick and dirty escape */
429            for(j=i;j<len;j++) {
430                int c = contents[i+j];
431                if(c > 0 && (c < ' ' || c >= '\177'))
432                    contents[i+j] = ERRFILL;
433            }
434            oc_log(LOGERR,"DATADDS failure, possible message: '%s'\n",
435                        contents+i);
436            goto done;
437        }
438    }
439    xxdr_setpos(xdrs,ckp);
440done:
441    return;
442}
Note: See TracBrowser for help on using the repository browser.