1/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
2   See the COPYRIGHT file for more information. */
3
4#include "config.h"
5#include "ocinternal.h"
6#include "occompile.h"
7#include "ocdebug.h"
8
9static const unsigned int MAX_UINT = 0xffffffff;
10
11static OCerror mergedas1(OCnodeddsOCnodedas);
12static OCerror mergedods1(OCnodeddsOCnodedas);
13static OCerror mergeother1(OCnoderootOCnodedas);
14static char* pathtostring(OClistpath, char* separator);
15static void computefullname(OCnodenode);
16
17/* Process ocnodes to fix various semantic issues*/
18void
19occomputesemantics(OClistocnodes)
20{
21    unsigned int i,j;
22    OCASSERT((ocnodes != NULL));
23    for(i=0;i<oclistlength(ocnodes);i++) {
24 OCnodenode = (OCnode*)oclistget(ocnodes,i);
25 /* set the container for dims*/
26 if(node->octype == OC_Dimension && node->dim.array != NULL) {
27     node->container = node->dim.array->container;
28 }
29    }
30    /* Fill in array.sizes */
31    for(i=0;i<oclistlength(ocnodes);i++) {
32 OCnodenode = (OCnode*)oclistget(ocnodes,i);
33 if(node->array.rank > 0) {
34     node->array.sizes = (size_t*)malloc(node->array.rank*sizeof(size_t));
35     for(j=0;j<node->array.rank;j++) {
36 OCnodedim = (OCnode*)oclistget(node->array.dimensions,j);
37 node->array.sizes[j] = dim->dim.declsize;
38     }
39 }
40    }
41}
42
43void
44occomputefullnames(OCnoderoot)
45{
46    unsigned int i;
47    if(root->name != NULLcomputefullname(root);
48    if(root->subnodes != NULL) { /* recurse*/
49        for(i=0;i<oclistlength(root->subnodes);i++) {
50     OCnodenode = (OCnode*)oclistget(root->subnodes,i);
51     occomputefullnames(node);
52 }
53    }
54}
55
56static void
57computefullname(OCnodenode)
58{
59    char* tmp;
60    char* fullname;
61    OClistpath;
62
63    OCASSERT((node->name != NULL));
64    if(node->fullname != NULL)
65 return;
66    path = oclistnew();
67    occollectpathtonode(node,path);
68    tmp = pathtostring(path,PATHSEPARATOR);
69    if(tmp == NULL) {
70        fullname = nulldup(node->name);
71    } else {
72        fullname = tmp;
73    }
74    node->fullname = fullname;
75    oclistfree(path);
76}
77
78/* Convert path to a string */
79static char*
80pathtostring(OClistpath, char* separator)
81{
82    int slen,i,len;
83    char* pathname;
84    if(path == NULL) return NULL;
85    len = oclistlength(path);
86    if(len == 0) return NULL;
87    for(i=0,slen=0;i<len;i++) {
88 OCnodenode = (OCnode*)oclistget(path,(size_t)i);
89 if(node->container == NULL || node->name == NULL) continue;
90 slen += strlen(node->name);
91    }
92    slen += ((len-1)*strlen(separator));
93    slen += 1;   /* for null terminator*/
94    pathname = (char*)ocmalloc((size_t)slen);
95    MEMCHECK(pathname,NULL);
96    pathname[0] = '\0';
97    for(i=0;i<len;i++) {
98 OCnodenode = (OCnode*)oclistget(path,(size_t)i);
99 if(node->container == NULL || node->name == NULL) continue;
100 if(strlen(pathname) > 0) strcat(pathname,separator);
101        strcat(pathname,node->name);
102    }
103    return pathname;
104}
105
106/* Collect the set of nodes ending in "node"*/
107void
108occollectpathtonode(OCnodenodeOClistpath)
109{
110    if(node == NULL) return;
111    occollectpathtonode(node->container,path);
112    oclistpush(path,(void*)node);
113}
114
115OCnode*
116ocnode_new(char* nameOCtype ptypeOCnoderoot)
117{
118    OCnodecdf = (OCnode*)ocmalloc(sizeof(OCnode));
119    MEMCHECK(cdf,(OCnode*)NULL);
120    memset((void*)cdf,0,sizeof(OCnode));
121    cdf->header.magic = OCMAGIC;
122    cdf->header.occlass = OC_Node;
123    cdf->name = (name?nulldup(name):NULL);
124    cdf->octype = ptype;
125    cdf->array.dimensions = NULL;
126    cdf->root = root;
127    return cdf;
128}
129
130static OCattribute*
131makeattribute(char* nameOCtype ptypeOClistvalues)
132{
133    OCattributeatt = (OCattribute*)ocmalloc(sizeof(OCattribute)); /* ocmalloc zeros*/
134    MEMCHECK(att,(OCattribute*)NULL);
135    att->name = nulldup(name);
136    att->etype = ptype;
137    att->nvalues = oclistlength(values);
138    att->values = NULL;
139    if(att->nvalues > 0) {
140 int i;
141        att->values = (char**)ocmalloc(sizeof(char*)*att->nvalues);
142        for(i=0;i<att->nvalues;i++)
143     att->values[i] = nulldup((char*)oclistget(values,(size_t)i));
144    }
145    return att;
146}
147
148void
149ocroot_free(OCnoderoot)
150{
151    OCtreetree;
152    OCstatestate;
153    int i;
154
155    if(root == NULL || root->tree == NULL) return;
156
157    tree = root->tree;
158    state = tree->state;
159
160    /* Free up the OCDATA instance, if any */
161    if(tree->data.data != NULL)
162 ocdata_free(state,tree->data.data);
163
164    for(i=0;i<oclistlength(state->trees);i++) {
165 OCnodenode = (OCnode*)oclistget(state->trees,(size_t)i);
166 if(root == node)
167     oclistremove(state->trees,(size_t)i);
168    }
169    /* Note: it is ok if state->trees does not contain this root */
170    octree_free(tree);
171}
172
173void
174octree_free(OCtreetree)
175{
176    if(tree == NULL) return;
177    ocnodes_free(tree->nodes);
178    ocfree(tree->constraint);
179    ocfree(tree->text);
180    if(tree->data.xdrs != NULL) {
181        xxdr_free(tree->data.xdrs);
182    }
183    ocfree(tree->data.filename); /* may be null */
184    if(tree->data.file != NULL) fclose(tree->data.file);
185    ocfree(tree->data.memory);
186    ocfree(tree);
187}
188
189void
190ocnodes_free(OClistnodes)
191{
192    unsigned int i,j;
193    for(i=0;i<oclistlength(nodes);i++) {
194 OCnodenode = (OCnode*)oclistget(nodes,i);
195        ocfree(node->name);
196        ocfree(node->fullname);
197        while(oclistlength(node->att.values) > 0) {
198     char* value = (char*)oclistpop(node->att.values);
199     ocfree(value);
200        }
201        while(oclistlength(node->attributes) > 0) {
202            OCattributeattr = (OCattribute*)oclistpop(node->attributes);
203     ocfree(attr->name);
204#if 0
205     /* If the attribute type is string, then we need to free them*/
206all values are strings now
207     if(attr->etype == OC_String || attr->etype == OC_URL)
208#endif
209     {
210 char** strings = (char**)attr->values;
211 for(j=0;j<attr->nvalues;j++) {ocfree(*strings); strings++;}
212     }
213     ocfree(attr->values);
214     ocfree(attr);
215        }
216        if(node->array.dimensions != NULLoclistfree(node->array.dimensions);
217        if(node->subnodes != NULLoclistfree(node->subnodes);
218        if(node->att.values != NULLoclistfree(node->att.values);
219        if(node->attributes != NULLoclistfree(node->attributes);
220 if(node->array.sizes != NULL) free(node->array.sizes);
221        ocfree(node);
222    }
223    oclistfree(nodes);
224}
225
226/*
227In order to be as compatible as possible with libdap,
228we try to use the same algorithm for DAS->DDS matching.
229As described there, the algorithm is as follows.
230    If the [attribute] name contains one or
231    more field separators then look for a [DDS]variable whose
232    name matches exactly. If the name contains no field separators then
233    the look first in the top level [of the DDS] and then in all subsequent
234    levels and return the first occurrence found. In general, this
235    searches constructor types in the order in which they appear
236    in the DDS, but there is no requirement that it do so.
237
238    Note: If a dataset contains two constructor types which have field names
239    that are the same (say point.x and pair.x) one should use fully qualified
240    names to get each of those variables.
241
242*/
243
244OCerror
245ocddsdasmerge(OCstatestateOCnodedasrootOCnodeddsroot)
246{
247    OCerror stat = OC_NOERR;
248    OClistdasglobals = oclistnew();
249    OClistdodsglobals = oclistnew(); /* top-level DODS_XXX {...} */
250    OClistdasnodes = oclistnew();
251    OClistvarnodes = oclistnew();
252    OClistddsnodes;
253    unsigned int i,j;
254
255    if(dasroot->tree == NULL || dasroot->tree->dxdclass != OCDAS)
256 {stat = OCTHROW(OC_EINVAL); goto done;}
257    if(ddsroot->tree == NULL || (ddsroot->tree->dxdclass != OCDDS
258        && ddsroot->tree->dxdclass != OCDATADDS))
259 {stat = OCTHROW(OC_EINVAL); goto done;}
260
261    ddsnodes = ddsroot->tree->nodes;
262
263    /* 1. collect all the relevant DAS nodes;
264          namely those that contain at least one
265          attribute value, not including the leaf attributes.
266          Simultaneously look for potential ambiguities
267          if found; complain but continue: result are indeterminate.
268          also collect globals separately*/
269    for(i=0;i<oclistlength(dasroot->tree->nodes);i++) {
270 OCnodedas = (OCnode*)oclistget(dasroot->tree->nodes,i);
271 int hasattributes = 0;
272 if(das->octype == OC_Attribute) continue; /* ignore these for now*/
273 if(das->name == NULL || das->att.isglobal) {
274     oclistpush(dasglobals,(void*)das);
275     continue;
276 }
277 if(das->att.isdods) {
278     oclistpush(dodsglobals,(void*)das);
279     continue;
280 }
281 for(j=0;j<oclistlength(das->subnodes);j++) {
282     OCnodesubnode = (OCnode*)oclistget(das->subnodes,j);
283     if(subnode->octype == OC_Attribute) {hasattributes = 1; break;}
284 }
285 if(hasattributes) {
286     /* Look for previously collected nodes with same name*/
287            for(j=0;j<oclistlength(dasnodes);j++) {
288         OCnodedas2 = (OCnode*)oclistget(dasnodes,j);
289 if(das->name == NULL || das2->name == NULL) continue;
290 if(strcmp(das->name,das2->name)==0) {
291     oclog(OCLOGWARN,"oc_mergedas: potentially ambiguous DAS name: %s",das->name);
292 }
293     }
294     oclistpush(dasnodes,(void*)das);
295 }
296    }
297
298    /* 2. collect all the leaf DDS nodes (of type OC_Atomic)*/
299    for(i=0;i<oclistlength(ddsnodes);i++) {
300 OCnodedds = (OCnode*)oclistget(ddsnodes,i);
301 if(dds->octype == OC_Atomicoclistpush(varnodes,(void*)dds);
302    }
303
304    /* 3. For each das node, locate matching DDS node(s) and attach
305          attributes to the DDS node(s).
306          Match means:
307          1. DAS->fullname :: DDS->fullname
308          2. DAS->name :: DDS->fullname (support DAS names with embedded '.')
309          3. DAS->name :: DDS->name
310    */
311    for(i=0;i<oclistlength(dasnodes);i++) {
312 OCnodedas = (OCnode*)oclistget(dasnodes,i);
313        for(j=0;j<oclistlength(varnodes);j++) {
314     OCnodedds = (OCnode*)oclistget(varnodes,j);
315     if(strcmp(das->fullname,dds->fullname)==0
316        || strcmp(das->name,dds->fullname)==0
317        || strcmp(das->name,dds->name)==0) {
318 mergedas1(dds,das);
319 /* remove from dasnodes list*/
320 oclistset(dasnodes,i,(void*)NULL);
321     }
322 }
323    }
324
325    /* 4. Assign globals*/
326    for(i=0;i<oclistlength(dasglobals);i++) {
327 OCnodedas = (OCnode*)oclistget(dasglobals,i);
328 if(das == NULL) continue;
329 mergedas1(ddsroot,das);
330    }
331    /* 5. Assign DODS_*/
332    for(i=0;i<oclistlength(dodsglobals);i++) {
333 OCnodedas = (OCnode*)oclistget(dodsglobals,i);
334 if(das == NULL) continue;
335 mergedods1(ddsroot,das);
336    }
337    /* 6. Assign other orphan attributes, which means
338   construct their full name and assign as a global attribute. */
339    for(i=0;i<oclistlength(dasnodes);i++) {
340 OCnodedas = (OCnode*)oclistget(dasnodes,i);
341 if(das == NULL) continue;
342 mergeother1(ddsrootdas);
343    }
344
345done:
346    /* cleanup*/
347    oclistfree(dasglobals);
348    oclistfree(dodsglobals);
349    oclistfree(dasnodes);
350    oclistfree(varnodes);
351    return OCTHROW(stat);
352}
353
354static OCerror
355mergedas1(OCnodeddsOCnodedas)
356{
357    unsigned int i;
358    OCerror stat = OC_NOERR;
359    if(das == NULL) return OC_NOERR; /* nothing to do */
360    if(dds->attributes == NULLdds->attributes = oclistnew();
361    /* assign the simple attributes in the das set to this dds node*/
362    for(i=0;i<oclistlength(das->subnodes);i++) {
363 OCnodeattnode = (OCnode*)oclistget(das->subnodes,i);
364 if(attnode->octype == OC_Attribute) {
365     OCattributeatt = makeattribute(attnode->name,
366 attnode->etype,
367 attnode->att.values);
368            oclistpush(dds->attributes,(void*)att);
369 }
370    }
371    return OCTHROW(stat);
372}
373
374static OCerror
375mergedods1(OCnodeddsOCnodedods)
376{
377    unsigned int i;
378    OCerror stat = OC_NOERR;
379    if(dods == NULL) return OC_NOERR; /* nothing to do */
380    OCASSERT(dods->octype == OC_Attributeset);
381    if(dds->attributes == NULLdds->attributes = oclistnew();
382    /* assign the simple attributes in the das set to this dds node
383       with renaming to tag as DODS_
384    */
385    for(i=0;i<oclistlength(dods->subnodes);i++) {
386 OCnodeattnode = (OCnode*)oclistget(dods->subnodes,i);
387 if(attnode->octype == OC_Attribute) {
388     OCattributeatt;
389     /* prefix the attribute name with the name of the attribute
390               set plus "."
391            */
392     size_t len =   strlen(attnode->name)
393                         + strlen(dods->name)
394  + strlen(".")
395  + 1; /*null*/
396     char* newname = (char*)malloc(len);
397     if(newname == NULL) return OC_ENOMEM;
398     strcpy(newname,dods->name);
399     strcat(newname,".");
400     strcat(newname,attnode->name);
401     att = makeattribute(newname,attnode->etype,attnode->att.values);
402     free(newname);
403            oclistpush(dds->attributes,(void*)att);
404 }
405    }
406    return OCTHROW(stat);
407}
408
409static OCerror
410mergeother1(OCnoderootOCnodedas)
411{
412    OCerror stat = OC_NOERR;
413    OCattributeatt = NULL;
414
415    OCASSERT(root != NULL);
416    if(root->attributes == NULLroot->attributes = oclistnew();
417
418    if(das->octype == OC_Attribute) {
419        /* compute the full name of this attribute */
420        computefullname(das);
421        /* create attribute */
422        att = makeattribute(das->fullname,das->etype,das->att.values);
423        oclistpush(root->attributes,(void*)att);
424    } else if(das->octype == OC_Attributeset) {
425 int i;
426 /* Recurse */
427        for(i=0;i<oclistlength(das->subnodes);i++) {
428     OCnodesub = (OCnode*)oclistget(das->subnodes,i);
429     if(sub == NULL) continue;
430     mergeother1(root,sub);
431 }
432    } else
433 stat = OC_EDAS;
434    return OCTHROW(stat);
435}
436
437static void
438ocuncorrelate(OCnoderoot)
439{
440    OCtreetree = root->tree;
441    unsigned int i;
442    if(tree == NULL) return;
443    for(i=0;i<oclistlength(tree->nodes);i++) {
444 OCnodenode = (OCnode*)oclistget(tree->nodes,i);
445 node->datadds = NULL;
446    }
447}
448
449static OCerror
450occorrelater(OCnodeddsOCnodedxd)
451{
452    int i,j;
453    OCerror ocstat = OC_NOERR;
454
455    if(dds->octype != dxd->octype) {
456 OCTHROWCHK((ocstat = OC_EINVAL)); goto fail;
457    }
458    if(dxd->name != NULL && dxd->name != NULL
459       && strcmp(dxd->name,dds->name) != 0) {
460 OCTHROWCHK((ocstat = OC_EINVAL)); goto fail;
461    } else if(dxd->name != dxd->name) { /* test NULL==NULL */
462 OCTHROWCHK((ocstat = OC_EINVAL)); goto fail;
463    }
464
465    if(dxd->array.rank != dds->array.rank) {
466 OCTHROWCHK((ocstat = OC_EINVAL)); goto fail;
467    }
468
469    dds->datadds = dxd;
470
471    switch (dds->octype) {
472    case OC_Dataset:
473    case OC_Structure:
474    case OC_Grid:
475    case OC_Sequence:
476 /* Remember: there may be fewer datadds fields than dds fields */
477 for(i=0;i<oclistlength(dxd->subnodes);i++) {
478     OCnodedxd1 = (OCnode*)oclistget(dxd->subnodes,(size_t)i);
479     for(j=0;j<oclistlength(dds->subnodes);j++) {
480 OCnodedds1 = (OCnode*)oclistget(dds->subnodes,(size_t)j);
481 if(strcmp(dxd1->name,dds1->name) == 0) {
482     ocstat = occorrelater(dds1,dxd1);
483     if(ocstat != OC_NOERR) {OCTHROWCHK(ocstat); goto fail;}
484     break;
485 }
486     }
487 }
488 break;
489    case OC_Dimension:
490    case OC_Atomic:
491 break;
492    default: OCPANIC1("unexpected node type: %d",dds->octype);
493    }
494    /* Correlate the dimensions */
495    if(dds->array.rank > 0) {
496 for(i=0;i<oclistlength(dxd->subnodes);i++) {
497     OCnodeddsdim = (OCnode*)oclistget(dds->array.dimensions,(size_t)i);
498     OCnodedxddim = (OCnode*)oclistget(dxd->array.dimensions,(size_t)i);
499     ocstat = occorrelater(ddsdim,dxddim);
500     if(!ocstat) goto fail;
501 }
502    }
503
504fail:
505    return OCTHROW(ocstat);
506
507}
508
509OCerror
510occorrelate(OCnodeddsOCnodedxd)
511{
512    if(dds == NULL || dxd == NULL) return OCTHROW(OC_EINVAL);
513    ocuncorrelate(dds);
514    return occorrelater(dds,dxd);
515}
516
517/*
518Mark cacheable those atomic String/URL typed nodes
519that are contained only in structures with rank > 0.
520*/
521void
522ocmarkcacheable(OCstatestateOCnodeddsroot)
523{
524    int i,j;
525#if 0
526    int ok;
527#endif
528    OClisttreenodes = ddsroot->tree->nodes;
529    OClistpath = oclistnew();
530    for(i=0;i<oclistlength(treenodes);i++) {
531        OCnodenode = (OCnode*)oclistget(treenodes,(size_t)i);
532 if(node->octype != OC_Atomic) continue;
533 if(node->etype != OC_String && node->etype != OC_URL) continue;
534 /* collect node path */
535        oclistclear(path);
536        occollectpathtonode(node,path);
537#if 0
538        ok = 1;
539#endif
540 for(j=1;j<oclistlength(path)-1;j++) {/* skip top level dataset and node itself*/
541            OCnodepathnode = (OCnode*)oclistget(path,(size_t)j);
542     if(pathnode->octype != OC_Structure
543 || pathnode->array.rank > 0) {
544#if 0
545     ok=0;
546#endif
547     break;
548     }
549 }
550#if 0
551 if(ok) {
552        node->cache.cacheable = 1;
553     node->cache.valid = 0;
554 }
555#endif
556    }
557    oclistfree(path);
558}
559
560#if 0
561
562OCerror
563ocddsdasmerge(OCstatestateOCnodeddsrootOCnodedasroot)
564{
565    int i,j;
566    OCerror stat = OC_NOERR;
567    OClistglobals = oclistnew();
568    if(dasroot == NULL) return OCTHROW(stat);
569    /* Start by looking for global attributes*/
570    for(i=0;i<oclistlength(dasroot->subnodes);i++) {
571 OCnodenode = (OCnode*)oclistget(dasroot->subnodes,i);
572 if(node->att.isglobal) {
573     for(j=0;j<oclistlength(node->subnodes);j++) {
574 OCnodeattnode = (OCnode*)oclistget(node->subnodes,j);
575 Attributeatt = makeattribute(attnode->name,
576 attnode->etype,
577 attnode->att.values);
578 oclistpush(globals,(void*)att);
579     }
580 }
581    }
582    ddsroot->attributes = globals;
583    /* Now try to match subnode names with attribute set names*/
584    for(i=0;i<oclistlength(dasroot->subnodes);i++) {
585 OCnodedas = (OCnode*)oclistget(dasroot->subnodes,i);
586 int match = 0;
587        if(das->att.isglobal) continue;
588        if(das->octype == OC_Attributeset) {
589            for(j=0;j<oclistlength(ddsroot->subnodes) && !match;j++) {
590         OCnodedds = (OCnode*)oclistget(ddsroot->subnodes,j);
591         if(strcmp(das->name,dds->name) == 0) {
592     match = 1;
593             stat = mergedas1(dds,das);
594             if(stat != OC_NOERR) break;
595 }
596     }
597 }
598        if(!match) {marklostattribute(das);}
599    }
600    if(stat == OC_NOERRddsroot->attributed = 1;
601    return OCTHROW(stat);
602}
603
604/* Merge das attributes into the dds node*/
605
606static int
607mergedas1(OCnodeddsOCnodedas)
608{
609    int i,j;
610    int stat = OC_NOERR;
611    if(dds->attributes == NULLdds->attributes = oclistnew();
612    /* assign the simple attributes in the das set to this dds node*/
613    for(i=0;i<oclistlength(das->subnodes);i++) {
614 OCnodeattnode = (OCnode*)oclistget(das->subnodes,i);
615 if(attnode->octype == OC_Attribute) {
616     Attributeatt = makeattribute(attnode->name,
617 attnode->etype,
618 attnode->att.values);
619            oclistpush(dds->attributes,(void*)att);
620 }
621    }
622    /* Try to merge any enclosed sets with subnodes of dds*/
623    for(i=0;i<oclistlength(das->subnodes);i++) {
624 OCnodedasnode = (OCnode*)oclistget(das->subnodes,i);
625 int match = 0;
626        if(dasnode->octype == OC_Attribute) continue; /* already dealt with above*/
627        for(j=0;j<oclistlength(dds->subnodes) && !match;j++) {
628     OCnodeddsnode = (OCnode*)oclistget(dds->subnodes,j);
629     if(strcmp(dasnode->name,ddsnode->name) == 0) {
630         match = 1;
631         stat = mergedas1(ddsnode,dasnode);
632         if(stat != OC_NOERR) break;
633     }
634 }
635        if(!match) {marklostattribute(dasnode);}
636    }
637    return OCTHROW(stat);
638}
639
640void*
641oclinearize(OCtype etype, unsigned int nstrings, char** strings)
642{
643    int i;
644    size_t typesize;
645    char* memp;
646    char* memory;
647
648    if(nstrings == 0) return NULL;
649    typesize = octypesize(etype);
650    memory = (char*)ocmalloc(nstrings*typesize);
651    MEMCHECK(memory,NULL);
652    memp = memory;
653    for(i=0;i<nstrings;i++) {
654 char* value = strings[i];
655        converttype(etype,value,memp);
656 memp += typesize;
657    }
658    return memory;
659}
660
661static int
662converttype(OCtype etype, char* value, char* memory)
663{
664    long iv;
665    unsigned long uiv;
666    double dv;
667    char c[1];
668    int outofrange = 0;
669#ifdef HAVE_LONG_LONG_INT
670    long long llv;
671    unsigned long long ullv;
672#endif
673
674    switch (etype) {
675    case OC_Char:
676 if(sscanf(value,"%c",c) != 1) goto fail;
677 *((char*)memory) = c[0];
678 break;
679    case OC_Byte:
680 if(sscanf(value,"%ld",&iv) != 1) goto fail;
681        else if(iv > OC_BYTE_MAX || iv < OC_BYTE_MIN) {iv = OC_BYTE_MAXoutofrange = 1;}
682 *((signed char*)memory) = (signed char)iv;
683 break;
684    case OC_UByte:
685 if(sscanf(value,"%lu",&uiv) != 1) goto fail;
686        else if(uiv > OC_UBYTE_MAX) {uiv = OC_UBYTE_MAXoutofrange = 1;}
687 *((unsigned char*)memory) = (unsigned char)uiv;
688 break;
689    case OC_Int16:
690 if(sscanf(value,"%ld",&iv) != 1) goto fail;
691        else if(iv > OC_INT16_MAX || iv < OC_INT16_MIN) {iv = OC_INT16_MAXoutofrange = 1;}
692 *((signed short*)memory) = (signed short)iv;
693 break;
694    case OC_UInt16:
695 if(sscanf(value,"%lu",&uiv) != 1) goto fail;
696        else if(uiv > OC_UINT16_MAX) {uiv = OC_UINT16_MAXoutofrange = 1;}
697 *((unsigned short*)memory) = (unsigned short)uiv;
698 break;
699    case OC_Int32:
700 if(sscanf(value,"%ld",&iv) != 1) goto fail;
701        else if(iv > OC_INT32_MAX || iv < OC_INT32_MIN) {iv = OC_INT32_MAXoutofrange = 1;}
702 *((signed int*)memory) = (signed int)iv;
703 break;
704    case OC_UInt32:
705 if(sscanf(value,"%lu",&uiv) != 1) goto fail;
706        else if(uiv > OC_UINT32_MAX) {uiv = OC_UINT32_MAXoutofrange = 1;}
707 *((unsigned char*)memory) = (unsigned int)uiv;
708 break;
709#ifdef HAVE_LONG_LONG_INT
710    case OC_Int64:
711 if(sscanf(value,"%lld",&llv) != 1) goto fail;
712        /*else if(iv > OC_INT64_MAX || iv < OC_INT64_MIN) goto fail;*/
713 *((signed long long*)memory) = (signed long long)llv;
714 break;
715    case OC_UInt64:
716 if(sscanf(value,"%llu",&ullv) != 1) goto fail;
717 *((unsigned long long*)memory) = (unsigned long long)ullv;
718 break;
719#endif
720    case OC_Float32:
721 if(sscanf(value,"%lf",&dv) != 1) goto fail;
722 *((float*)memory) = (float)dv;
723 break;
724    case OC_Float64:
725 if(sscanf(value,"%lf",&dv) != 1) goto fail;
726 *((double*)memory) = (double)dv;
727 break;
728    case OC_String: case OC_URL:
729 *((char**)memory) = nulldup(value);
730 break;
731    default:
732 goto fail;
733    }
734    if(outofrange)
735        oc_log(LOGWARN,"converttype range failure: %d: %s",etype,value);
736    return 1;
737fail:
738    oc_log(LOGERR,"converttype bad value: %d: %s",etype,value);
739    return 0;
740}
741#endif /*0*/


HyperKWIC - Version 7.20DA executed at 11:37 on 27 Oct 2017 | Polyhedron Solutions - INTERNAL USE | COMMERCIAL (Any O/S) SN 4AKIed