1 /*
2  * Copyright 2006 Sony Computer Entertainment Inc.
3  *
4  * Licensed under the MIT Open Source License, for details please see license.txt or the website
5  * http://www.opensource.org/licenses/mit-license.php
6  *
7  */
8 
9 #include <sstream>
10 #include <iomanip>
11 #include <limits>
12 #include <dae/daeAtomicType.h>
13 #include <dae/daeElement.h>
14 #include <dae/daeURI.h>
15 #include <dae/daeIDRef.h>
16 #include <dae/daeMetaElement.h>
17 #include <dae/daeDatabase.h>
18 #include <dae/daeErrorHandler.h>
19 #include <dae/daeUtils.h>
20 
21 namespace {
22 // Skip leading whitespace
skipWhitespace(daeChar * s)23 daeChar* skipWhitespace(daeChar* s) {
24     if (s) {
25         // !!!GAC NEEDS TO BE CHANGED to use XML standard whitespace parsing
26         while(*s == ' ' || *s == '\r' || *s == '\n' || *s == '\t') s++;
27     }
28 
29     return s;
30 }
31 
32 // Move forward past this token
skipToken(daeChar * s)33 daeChar* skipToken(daeChar* s) {
34     while(*s != ' ' && *s != '\r' && *s != '\n' && *s != '\t' && *s != 0) s++;
35     return s;
36 }
37 
38 // Given a string of whitespace-separated tokens, this function returns a null-terminated string
39 // containing the next token. If the next token is already null-terminated, no memory is allocated
40 // and the function returns the pointer that was passed in. Note that this function assumes that
41 // the string passed in starts with the next token and not a whitespace.
42 // If returnValue != s, the client should free the returnValue with delete[].
extractToken(daeChar * s)43 daeChar* extractToken(daeChar* s) {
44     if (!s)
45         return 0;
46 
47     daeChar* tmp = skipToken(s);
48     if (*tmp != 0) {
49         daeChar* scopy = new daeChar[tmp-s+1];
50         strncpy(scopy, s, tmp-s);
51         scopy[tmp-s] = 0;
52         return scopy;
53     }
54 
55     return s;
56 }
57 }
58 
59 
daeAtomicTypeList(DAE & dae)60 daeAtomicTypeList::daeAtomicTypeList(DAE& dae) {
61     types.append(new daeUIntType(dae));
62     types.append(new daeIntType(dae));
63     types.append(new daeLongType(dae));
64     types.append(new daeShortType(dae));
65     types.append(new daeULongType(dae));
66     types.append(new daeFloatType(dae));
67     types.append(new daeDoubleType(dae));
68     types.append(new daeStringRefType(dae));
69     types.append(new daeElementRefType(dae));
70     types.append(new daeEnumType(dae));
71     types.append(new daeRawRefType(dae));
72     types.append(new daeResolverType(dae));
73     types.append(new daeIDResolverType(dae));
74     types.append(new daeBoolType(dae));
75     types.append(new daeTokenType(dae));
76 }
77 
~daeAtomicTypeList()78 daeAtomicTypeList::~daeAtomicTypeList() {
79     size_t types_count = types.getCount();
80     for (size_t i = 0; i < types_count; i++)
81         delete types[i];
82 }
83 
append(daeAtomicType * t)84 daeInt daeAtomicTypeList::append(daeAtomicType* t) {
85     return (daeInt)types.append(t);
86 }
87 
getByIndex(daeInt index)88 const daeAtomicType* daeAtomicTypeList::getByIndex(daeInt index) {
89     return types[index];
90 }
91 
getCount()92 daeInt daeAtomicTypeList::getCount() {
93     return (daeInt)types.getCount();
94 }
95 
get(daeStringRef typeString)96 daeAtomicType* daeAtomicTypeList::get(daeStringRef typeString) {
97     size_t types_count = types.getCount();
98     for (size_t i = 0; i < types_count; i++) {
99         daeStringRefArray& nameBindings = types[i]->getNameBindings();
100         size_t nameBindings_count = nameBindings.getCount();
101         for (size_t j = 0; j < nameBindings_count; j++) {
102             if (strcmp(typeString, nameBindings[j]) == 0)
103                 return types[i];
104         }
105     }
106 
107     return NULL;
108 }
109 
get(daeEnum typeEnum)110 daeAtomicType* daeAtomicTypeList::get(daeEnum typeEnum) {
111     size_t types_count = types.getCount();
112     for (size_t i = 0; i < types_count; i++)
113         if (typeEnum == types[i]->getTypeEnum())
114             return types[i];
115     return NULL;
116 }
117 
118 
daeAtomicType(DAE & dae)119 daeAtomicType::daeAtomicType(DAE& dae)
120 {
121     _dae = &dae;
122     _size = -1;
123     _alignment = -1;
124     _typeEnum = -1;
125     _typeString = "notype";
126     _printFormat = "badtype";
127     _scanFormat = "";
128     _maxStringLength = -1;
129 }
130 
131 daeBool
stringToMemory(daeChar * src,daeChar * dstMemory)132 daeAtomicType::stringToMemory(daeChar *src, daeChar* dstMemory)
133 {
134     sscanf(src, _scanFormat, dstMemory);
135     return true;
136 }
137 
arrayToString(daeArray & array,std::ostringstream & buffer)138 void daeAtomicType::arrayToString(daeArray& array, std::ostringstream& buffer) {
139     if (array.getCount() > 0)
140         memoryToString(array.getRaw(0), buffer);
141 
142     size_t array_count = array.getCount();
143     for (size_t i = 1; i < array_count; i++) {
144         buffer << ' ';
145         memoryToString(array.getRaw(i), buffer);
146     }
147 }
148 
149 daeBool
stringToArray(daeChar * src,daeArray & array)150 daeAtomicType::stringToArray(daeChar* src, daeArray& array) {
151     array.clear();
152     array.setElementSize(_size);
153 
154     if (src == 0)
155         return false;
156 
157     // We're about to insert null terminators into the string so that scanf doesn't take forever
158     // doing strlens. Since the memory might not be writable, I need to duplicate the string and
159     // write into the duplicate, or else I might get access violations.
160     // This sucks... surely we can do better than this.
161     daeChar* srcDup = new daeChar[strlen(src)+1];
162     strcpy(srcDup, src);
163     src = srcDup;
164 
165     while (*src != 0)
166     {
167         src = skipWhitespace(src);
168         if(*src != 0)
169         {
170             daeChar* token = src;
171             src = skipToken(src);
172             daeChar temp = *src;
173             *src = 0;
174             size_t count = array.getCount();
175             array.setCount(count+1);
176             if (!stringToMemory(token, array.getRaw(count))) {
177                 delete[] srcDup;
178                 return false;
179             }
180 
181             *src = temp;
182         }
183     }
184 
185     delete[] srcDup;
186     return true;
187 }
188 
compareArray(daeArray & value1,daeArray & value2)189 daeInt daeAtomicType::compareArray(daeArray& value1, daeArray& value2) {
190     if (value1.getCount() != value2.getCount())
191         return value1.getCount() > value2.getCount() ? 1 : -1;
192 
193     size_t value1_count = value1.getCount();
194     for (size_t i = 0; i < value1_count; i++) {
195         daeInt result = compare(value1.getRaw(i), value2.getRaw(i));
196         if (result != 0)
197             return result;
198     }
199 
200     return 0;
201 }
202 
copyArray(daeArray & src,daeArray & dst)203 void daeAtomicType::copyArray(daeArray& src, daeArray& dst) {
204     dst.setCount(src.getCount());
205     size_t src_count = src.getCount();
206     for (size_t i = 0; i < src_count; i++)
207         copy(src.getRaw(i), dst.getRaw(i));
208 }
209 
210 daeInt
compare(daeChar * value1,daeChar * value2)211 daeAtomicType::compare(daeChar* value1, daeChar* value2) {
212     return memcmp(value1, value2, _size);
213 }
214 
daeEnumType(DAE & dae)215 daeEnumType::daeEnumType(DAE& dae) : daeAtomicType(dae)
216 {
217     _size = sizeof(daeEnum);
218     _alignment = sizeof(daeEnum);
219     _typeEnum = EnumType;
220     _nameBindings.append("enum");
221     _printFormat = "%s"; //"%%.%ds";
222     _scanFormat = "%s";
223     _strings = NULL;
224     _values = NULL;
225     _typeString = "enum";
226 }
227 
~daeEnumType()228 daeEnumType::~daeEnumType() {
229     if ( _strings ) {
230         delete _strings;
231         _strings = NULL;
232     }
233     if ( _values ) {
234         delete _values;
235         _values = NULL;
236     }
237 }
238 
daeBoolType(DAE & dae)239 daeBoolType::daeBoolType(DAE& dae) : daeAtomicType(dae)
240 {
241     _size = sizeof(daeBool);
242     _alignment = sizeof(daeBool);
243     _typeEnum = BoolType;
244     _printFormat = "%d";
245     _scanFormat = "%d";
246     _typeString = "bool";
247     _maxStringLength = (daeInt)strlen("false")+1;
248     _nameBindings.append("bool");
249     //_nameBindings.append("xsBool");
250     _nameBindings.append("xsBoolean");
251 }
252 
daeIntType(DAE & dae)253 daeIntType::daeIntType(DAE& dae) : daeAtomicType(dae)
254 {
255     _size = sizeof(daeInt);
256     _alignment = sizeof(daeInt);
257     _typeEnum = IntType;
258     _maxStringLength = 16;
259     _nameBindings.append("int");
260     _nameBindings.append("xsInteger");
261     _nameBindings.append("xsHexBinary");
262     _nameBindings.append("xsIntegerArray");
263     _nameBindings.append("xsHexBinaryArray");
264     _nameBindings.append("xsByte");
265     _nameBindings.append("xsInt");
266     _printFormat = "%d";
267     _scanFormat = "%d";
268     _typeString = "int";
269 }
daeLongType(DAE & dae)270 daeLongType::daeLongType(DAE& dae) : daeAtomicType(dae)
271 {
272     _size = sizeof(daeLong);
273     _alignment = sizeof(daeLong);
274     _typeEnum = LongType;
275     _maxStringLength = 32;
276     _nameBindings.append("xsLong");
277     _nameBindings.append("xsLongArray");
278 #if defined(_MSC_VER) || defined(__MINGW32__)
279     _printFormat = "%I64d";
280     _scanFormat = "%I64d";
281 #else
282     _printFormat = "%lld";
283     _scanFormat = "%lld";
284 #endif
285     _typeString = "long";
286 }
daeShortType(DAE & dae)287 daeShortType::daeShortType(DAE& dae) : daeAtomicType(dae)
288 {
289     _maxStringLength = 8;
290     _size = sizeof(daeShort);
291     _alignment = sizeof(daeShort);
292     _typeEnum = ShortType;
293     _nameBindings.append("short");
294     _nameBindings.append("xsShort");
295     _printFormat = "%hd";
296     _scanFormat = "%hd";
297     _typeString = "short";
298 }
daeUIntType(DAE & dae)299 daeUIntType::daeUIntType(DAE& dae) : daeAtomicType(dae)
300 {
301     _maxStringLength = 16;
302     _size = sizeof(daeUInt);
303     _alignment = sizeof(daeUInt);
304     _typeEnum = UIntType;
305     _nameBindings.append("uint");
306     _nameBindings.append("xsNonNegativeInteger");
307     _nameBindings.append("xsUnsignedByte");
308     _nameBindings.append("xsUnsignedInt");
309     _nameBindings.append("xsPositiveInteger");
310     _printFormat = "%u";
311     _scanFormat = "%u";
312     _typeString = "uint";
313 }
daeULongType(DAE & dae)314 daeULongType::daeULongType(DAE& dae) : daeAtomicType(dae)
315 {
316     _size = sizeof(daeULong);
317     _alignment = sizeof(daeULong);
318     _typeEnum = ULongType;
319     _maxStringLength = 32;
320     _nameBindings.append("ulong");
321     _nameBindings.append("xsUnsignedLong");
322 #if defined(_MSC_VER) || defined(__MINGW32__)
323     _printFormat = "%I64u";
324     _scanFormat = "%I64u";
325 #else
326     _printFormat = "%llu";
327     _scanFormat = "%llu";
328 #endif
329     _typeString = "ulong";
330 }
daeFloatType(DAE & dae)331 daeFloatType::daeFloatType(DAE& dae) : daeAtomicType(dae)
332 {
333     _maxStringLength = 64;
334     _size = sizeof(daeFloat);
335     _alignment = sizeof(daeFloat);
336     _typeEnum = FloatType;
337     _nameBindings.append("float");
338     _nameBindings.append("xsFloat");
339     _printFormat = "%g";
340     _scanFormat = "%g";
341     _typeString = "float";
342 }
daeDoubleType(DAE & dae)343 daeDoubleType::daeDoubleType(DAE& dae) : daeAtomicType(dae)
344 {
345     _size = sizeof(daeDouble);
346     _alignment = sizeof(daeDouble);
347     _typeEnum = DoubleType;
348     _nameBindings.append("double");
349     _nameBindings.append("xsDouble");
350     _nameBindings.append("xsDecimal");
351     _printFormat = "%lg";
352     _scanFormat = "%lg";
353     _typeString = "double";
354     _maxStringLength = 64;
355 }
356 
daeStringRefType(DAE & dae)357 daeStringRefType::daeStringRefType(DAE& dae) : daeAtomicType(dae)
358 {
359     _size = sizeof(daeStringRef);
360     _alignment = sizeof(daeStringRef);
361     _typeEnum = StringRefType;
362     _nameBindings.append("string");
363     _nameBindings.append("xsString");
364     _nameBindings.append("xsDateTime");
365     _printFormat = "%s";
366     _scanFormat = "%s";
367     _typeString = "string";
368 }
369 
daeTokenType(DAE & dae)370 daeTokenType::daeTokenType(DAE& dae) : daeStringRefType(dae)
371 {
372     _size = sizeof(daeStringRef);
373     _alignment = sizeof(daeStringRef);
374     _typeEnum = TokenType;
375     _nameBindings.append("token");
376     _nameBindings.append("xsID");
377     _nameBindings.append("xsNCName");
378     _nameBindings.append("xsNMTOKEN");
379     _nameBindings.append("xsName");
380     _nameBindings.append("xsToken");
381     _nameBindings.append("xsNameArray");
382     _nameBindings.append("xsTokenArray");
383     _nameBindings.append("xsNCNameArray");
384     _printFormat = "%s";
385     _scanFormat = "%s";
386     _typeString = "token";
387 }
388 
daeElementRefType(DAE & dae)389 daeElementRefType::daeElementRefType(DAE& dae) : daeAtomicType(dae)
390 {
391     _size = sizeof(daeElementRef);
392     _alignment = sizeof(daeElementRef);
393     _typeEnum = ElementRefType;
394     _nameBindings.append("element");
395     _nameBindings.append("Element");
396     _nameBindings.append("TrackedElement");
397     _printFormat = "%p";
398     _scanFormat = "%p";
399     _typeString = "element";
400     _maxStringLength = 64;
401 }
402 
daeRawRefType(DAE & dae)403 daeRawRefType::daeRawRefType(DAE& dae) : daeAtomicType(dae)
404 {
405     _size = sizeof(daeRawRef);
406     _alignment = sizeof(daeRawRef);
407     _typeEnum = RawRefType;
408     _nameBindings.append("raw");
409     _printFormat = "%p";
410     _scanFormat = "%p";
411     _typeString = "raw";
412     _maxStringLength = 64;
413 }
414 
daeResolverType(DAE & dae)415 daeResolverType::daeResolverType(DAE& dae) : daeAtomicType(dae)
416 {
417     _size = sizeof(daeURI);
418     _alignment = sizeof(daeURI);
419     _typeEnum = ResolverType;
420     _nameBindings.append("resolver");
421     _nameBindings.append("xsAnyURI");
422     _printFormat = "%s";
423     _scanFormat = "%s";
424     _typeString = "resolver";
425 }
daeIDResolverType(DAE & dae)426 daeIDResolverType::daeIDResolverType(DAE& dae) : daeAtomicType(dae)
427 {
428     _size = sizeof(daeIDRef);
429     _alignment = sizeof(daeIDRef);
430     _typeEnum = IDResolverType;
431     _nameBindings.append("xsIDREF");
432     _nameBindings.append("xsIDREFS");
433     _printFormat = "%s";
434     _scanFormat = "%s";
435     _typeString = "idref_resolver";
436 }
437 
memoryToString(daeChar * src,std::ostringstream & dst)438 daeBool daeIntType::memoryToString(daeChar* src, std::ostringstream& dst) {
439     dst << *(daeInt*)src;
440     return true;
441 }
442 
memoryToString(daeChar * src,std::ostringstream & dst)443 daeBool daeLongType::memoryToString(daeChar* src, std::ostringstream& dst) {
444     dst << *(daeLong*)src;
445     return true;
446 }
447 
memoryToString(daeChar * src,std::ostringstream & dst)448 daeBool daeShortType::memoryToString(daeChar* src, std::ostringstream& dst) {
449     dst << *(daeShort*)src;
450     return true;
451 }
452 
memoryToString(daeChar * src,std::ostringstream & dst)453 daeBool daeUIntType::memoryToString(daeChar* src, std::ostringstream& dst) {
454     dst << *(daeUInt*)src;
455     return true;
456 }
457 
memoryToString(daeChar * src,std::ostringstream & dst)458 daeBool daeULongType::memoryToString(daeChar* src, std::ostringstream& dst) {
459 #ifdef _MSC_VER
460     // Microsoft's stringstream implementation has weird performance issues
461     static char buffer[64];
462     _snprintf(buffer, 64, _printFormat, *((daeULong*)src));
463     dst << buffer;
464 #else
465     dst << *(daeULong*)src;
466 #endif
467     return true;
468 }
469 
memoryToString(daeChar * src,std::ostringstream & dst)470 daeBool daeFloatType::memoryToString(daeChar* src, std::ostringstream& dst) {
471     if ( *(daeFloat*)src != *(daeFloat*)src ) // NAN
472         dst << "NaN";
473     else if ( *(daeUInt*)src == 0x7f800000 ) // +INF
474         dst << "INF";
475     else if ( *(daeUInt*)src == 0xff800000 ) // -INF
476         dst << "-INF";
477     else {
478 #ifdef COLLADA_DOM_DAEFLOAT_IS64
479         dst << std::setprecision(std::numeric_limits<daeFloat>::digits10+1) << *(daeFloat*)src;
480 #else
481         dst << *(daeFloat*)src;
482 #endif
483     }
484     return true;
485 }
486 
487 daeBool
stringToMemory(daeChar * src,daeChar * dstMemory)488 daeFloatType::stringToMemory(daeChar *src, daeChar* dstMemory)
489 {
490     src = skipWhitespace(src);
491 
492     if ( strncmp(src, "NaN", 3) == 0 ) {
493         daeErrorHandler::get()->handleWarning("NaN encountered while setting an attribute or value\n");
494         *(daeInt*)(dstMemory) = 0x7f800002;
495     }
496     else if ( strncmp(src, "INF", 3) == 0 ) {
497         daeErrorHandler::get()->handleWarning( "INF encountered while setting an attribute or value\n" );
498         *(daeInt*)(dstMemory) = 0x7f800000;
499     }
500     else if ( strncmp(src, "-INF", 4) == 0 ) {
501         daeErrorHandler::get()->handleWarning( "-INF encountered while setting an attribute or value\n" );
502         *(daeInt*)(dstMemory) = 0xff800000;
503     }
504     else
505     {
506         sscanf(src, _scanFormat, dstMemory);
507     }
508     return true;
509 }
510 
memoryToString(daeChar * src,std::ostringstream & dst)511 daeBool daeDoubleType::memoryToString(daeChar* src, std::ostringstream& dst) {
512     if ( *(daeDouble*)src != *(daeDouble*)src ) // NAN
513         dst << "NaN";
514     else if ( *(daeULong*)src == 0x7ff0000000000000LL ) // +INF
515         dst << "INF";
516     else if ( *(daeULong*)src == 0xfff0000000000000LL ) // -INF
517         dst << "-INF";
518     else {
519 #ifdef _MSC_VER
520         // Microsoft's stringstream implementation has weird performance issues
521         static char buffer[64];
522         _snprintf(buffer, 64, _printFormat, *((daeDouble*)src));
523         dst << buffer;
524 #else
525 
526 #ifdef COLLADA_DOM_DAEFLOAT_IS64
527         dst << std::setprecision(std::numeric_limits<daeDouble>::digits10+1) << *(daeDouble*)src;
528 #else
529         dst << *(daeDouble*)src;
530 #endif
531 #endif
532     }
533     return true;
534 }
535 
536 daeBool
stringToMemory(daeChar * src,daeChar * dstMemory)537 daeDoubleType::stringToMemory(daeChar *src, daeChar* dstMemory)
538 {
539     src = skipWhitespace(src);
540 
541     if ( strncmp(src, "NaN", 3) == 0 ) {
542         daeErrorHandler::get()->handleWarning( "NaN encountered while setting an attribute or value\n" );
543         *(daeLong*)(dstMemory) = 0x7ff0000000000002LL;
544     }
545     else if ( strncmp(src, "INF", 3) == 0 ) {
546         daeErrorHandler::get()->handleWarning( "INF encountered while setting an attribute or value\n" );
547         *(daeLong*)(dstMemory) = 0x7ff0000000000000LL;
548     }
549     else if ( strncmp(src, "-INF", 4) == 0 ) {
550         daeErrorHandler::get()->handleWarning( "-INF encountered while setting an attribute or value\n" );
551         *(daeLong*)(dstMemory) = 0xfff0000000000000LL;
552     }
553     else
554     {
555         sscanf(src, _scanFormat, dstMemory);
556     }
557     return true;
558 }
559 
memoryToString(daeChar * src,std::ostringstream & dst)560 daeBool daeRawRefType::memoryToString(daeChar* src, std::ostringstream& dst) {
561     dst << (void *)(*((daeRawRef*)src));
562     return true;
563 }
564 
memoryToString(daeChar * src,std::ostringstream & dst)565 daeBool daeStringRefType::memoryToString(daeChar* src, std::ostringstream& dst) {
566     daeString s = *((daeStringRef *)src);
567     if (s)
568         dst << s;
569     return true;
570 }
571 
memoryToString(daeChar * src,std::ostringstream & dst)572 daeBool daeResolverType::memoryToString(daeChar* src, std::ostringstream& dst) {
573     // Get the URI we are trying to write
574     daeURI *thisURI = ((daeURI *)src);
575     // Encode spaces with %20
576     dst << cdom::replace(thisURI->originalStr(), " ", "%20");
577     return true;
578 }
579 
memoryToString(daeChar * src,std::ostringstream & dst)580 daeBool daeIDResolverType::memoryToString(daeChar* src, std::ostringstream& dst) {
581     dst << ((daeIDRef *)src)->getID();
582     return true;
583 }
584 
585 daeBool
stringToMemory(daeChar * src,daeChar * dstMemory)586 daeResolverType::stringToMemory(daeChar* src, daeChar* dstMemory)
587 {
588     ((daeURI*)dstMemory)->set(cdom::replace(src, " ", "%20"));
589     return true;
590 }
591 
592 daeBool
stringToMemory(daeChar * src,daeChar * dstMemory)593 daeIDResolverType::stringToMemory(daeChar* src, daeChar* dstMemory)
594 {
595     src = skipWhitespace(src);
596     daeChar* id = extractToken(src);
597     ((daeIDRef*)dstMemory)->setID(id);
598     if (id != src)
599         delete[] id;
600     return true;
601 }
602 
603 daeBool
stringToMemory(daeChar * srcChars,daeChar * dstMemory)604 daeStringRefType::stringToMemory(daeChar* srcChars, daeChar* dstMemory)
605 {
606     *((daeStringRef*)dstMemory) = srcChars;
607     return true;
608 }
609 
610 daeBool
stringToMemory(daeChar * src,daeChar * dst)611 daeTokenType::stringToMemory(daeChar* src, daeChar* dst)
612 {
613     src = skipWhitespace(src);
614     daeChar* srcTmp = extractToken(src);
615     *((daeStringRef*)dst) = srcTmp;
616     if (srcTmp != src)
617         delete[] srcTmp;
618     return true;
619 }
620 
621 daeBool
stringToMemory(daeChar * src,daeChar * dst)622 daeEnumType::stringToMemory(daeChar* src, daeChar* dst )
623 {
624     src = skipWhitespace(src);
625     daeChar* srcTmp = extractToken(src);
626 
627     size_t index(0);
628     bool result = _strings->find(srcTmp, index) != DAE_ERR_QUERY_NO_MATCH;
629     if (result) {
630         daeEnum val = _values->get( index );
631         *((daeEnum*)dst) = val;
632     }
633 
634     if (srcTmp != src)
635         delete[] srcTmp;
636 
637     return result;
638 }
639 
memoryToString(daeChar * src,std::ostringstream & dst)640 daeBool daeEnumType::memoryToString(daeChar* src, std::ostringstream& dst) {
641     daeStringRef s = "unknown";
642     if (_strings != NULL) {
643         size_t index;
644         if (_values->find(*((daeEnum*)src), index) == DAE_OK)
645             s = _strings->get(index);
646     }
647     dst << (const char*)s;
648     return true;
649 }
650 
651 daeBool
stringToMemory(daeChar * srcChars,daeChar * dstMemory)652 daeBoolType::stringToMemory(daeChar* srcChars, daeChar* dstMemory)
653 {
654     if (strncmp(srcChars,"true",4)==0 || strncmp(srcChars,"1",1)==0)
655         *((daeBool*)dstMemory) = true;
656     else
657         *((daeBool*)dstMemory) = false;
658     return true;
659 }
660 
memoryToString(daeChar * src,std::ostringstream & dst)661 daeBool daeBoolType::memoryToString(daeChar* src, std::ostringstream& dst) {
662     if (*((daeBool*)src))
663         dst << "true";
664     else
665         dst << "false";
666     return true;
667 }
668 //!!!ACL added for 1.4 complex types and groups
669 
670 // Unimplemented
memoryToString(daeChar * src,std::ostringstream & dst)671 daeBool daeElementRefType::memoryToString(daeChar* src, std::ostringstream& dst) {
672     (void)src;
673     (void)dst;
674     return false;
675 }
676 
create()677 daeMemoryRef daeBoolType::create() {
678     return (daeMemoryRef) new daeBool;
679 }
680 
create()681 daeMemoryRef daeIntType::create() {
682     return (daeMemoryRef) new daeInt;
683 }
684 
create()685 daeMemoryRef daeLongType::create() {
686     return (daeMemoryRef) new daeLong;
687 }
688 
create()689 daeMemoryRef daeUIntType::create() {
690     return (daeMemoryRef) new daeUInt;
691 }
692 
create()693 daeMemoryRef daeULongType::create() {
694     return (daeMemoryRef) new daeULong;
695 }
696 
create()697 daeMemoryRef daeShortType::create() {
698     return (daeMemoryRef) new daeShort;
699 }
700 
create()701 daeMemoryRef daeFloatType::create() {
702     return (daeMemoryRef) new daeFloat;
703 }
704 
create()705 daeMemoryRef daeDoubleType::create() {
706     return (daeMemoryRef) new daeDouble;
707 }
708 
create()709 daeMemoryRef daeStringRefType::create() {
710     return (daeMemoryRef) new daeStringRef;
711 }
712 
create()713 daeMemoryRef daeTokenType::create() {
714     return (daeMemoryRef) new daeStringRef;
715 }
716 
create()717 daeMemoryRef daeElementRefType::create() {
718     return (daeMemoryRef) new daeElementRef;
719 }
720 
create()721 daeMemoryRef daeEnumType::create() {
722     return (daeMemoryRef) new daeEnum;
723 }
724 
create()725 daeMemoryRef daeRawRefType::create() {
726     return (daeMemoryRef) new daeRawRef;
727 }
728 
create()729 daeMemoryRef daeResolverType::create() {
730     return (daeMemoryRef) new daeURI(*_dae);
731 }
732 
create()733 daeMemoryRef daeIDResolverType::create() {
734     return (daeMemoryRef) new daeIDRef;
735 }
736 
737 
destroy(daeMemoryRef obj)738 void daeBoolType::destroy(daeMemoryRef obj) {
739     delete (daeBool*)obj;
740 }
741 
destroy(daeMemoryRef obj)742 void daeIntType::destroy(daeMemoryRef obj) {
743     delete (daeInt*)obj;
744 }
745 
destroy(daeMemoryRef obj)746 void daeLongType::destroy(daeMemoryRef obj) {
747     delete (daeLong*)obj;
748 }
749 
destroy(daeMemoryRef obj)750 void daeUIntType::destroy(daeMemoryRef obj) {
751     delete (daeUInt*)obj;
752 }
753 
destroy(daeMemoryRef obj)754 void daeULongType::destroy(daeMemoryRef obj) {
755     delete (daeULong*)obj;
756 }
757 
destroy(daeMemoryRef obj)758 void daeShortType::destroy(daeMemoryRef obj) {
759     delete (daeShort*)obj;
760 }
761 
destroy(daeMemoryRef obj)762 void daeFloatType::destroy(daeMemoryRef obj) {
763     delete (daeFloat*)obj;
764 }
765 
destroy(daeMemoryRef obj)766 void daeDoubleType::destroy(daeMemoryRef obj) {
767     delete (daeDouble*)obj;
768 }
769 
destroy(daeMemoryRef obj)770 void daeStringRefType::destroy(daeMemoryRef obj) {
771     delete (daeStringRef*)obj;
772 }
773 
destroy(daeMemoryRef obj)774 void daeTokenType::destroy(daeMemoryRef obj) {
775     delete (daeStringRef*)obj;
776 }
777 
destroy(daeMemoryRef obj)778 void daeElementRefType::destroy(daeMemoryRef obj) {
779     delete (daeElementRef*)obj;
780 }
781 
destroy(daeMemoryRef obj)782 void daeEnumType::destroy(daeMemoryRef obj) {
783     delete (daeEnum*)obj;
784 }
785 
destroy(daeMemoryRef obj)786 void daeRawRefType::destroy(daeMemoryRef obj) {
787     delete (daeRawRef*)obj;
788 }
789 
destroy(daeMemoryRef obj)790 void daeResolverType::destroy(daeMemoryRef obj) {
791     delete (daeURI*)obj;
792 }
793 
destroy(daeMemoryRef obj)794 void daeIDResolverType::destroy(daeMemoryRef obj) {
795     delete (daeIDRef*)obj;
796 }
797 
798 
compare(daeChar * value1,daeChar * value2)799 daeInt daeStringRefType::compare(daeChar* value1, daeChar* value2) {
800     daeString s1 = *((daeStringRef *)value1);
801     daeString s2 = *((daeStringRef *)value2);
802     // For string types, the empty string and null are considered equivalent
803     if (!s1)
804         s1 = "";
805     if (!s2)
806         s2 = "";
807     return strcmp(s1, s2);
808 }
809 
compare(daeChar * value1,daeChar * value2)810 daeInt daeResolverType::compare(daeChar* value1, daeChar* value2) {
811     return strcmp(((daeURI*)value1)->str().c_str(), ((daeURI*)value2)->str().c_str());
812 }
813 
compare(daeChar * value1,daeChar * value2)814 daeInt daeIDResolverType::compare(daeChar* value1, daeChar* value2) {
815     return strcmp(((daeIDRef*)value1)->getID(), ((daeIDRef*)value2)->getID());
816 }
817 
818 
createArray()819 daeArray* daeBoolType::createArray() {
820     return new daeTArray<daeBool>;
821 }
822 
createArray()823 daeArray* daeIntType::createArray() {
824     return new daeTArray<daeInt>;
825 }
826 
createArray()827 daeArray* daeLongType::createArray() {
828     return new daeTArray<daeLong>;
829 }
830 
createArray()831 daeArray* daeUIntType::createArray() {
832     return new daeTArray<daeUInt>;
833 }
834 
createArray()835 daeArray* daeULongType::createArray() {
836     return new daeTArray<daeULong>;
837 }
838 
createArray()839 daeArray* daeShortType::createArray() {
840     return new daeTArray<daeShort>;
841 }
842 
createArray()843 daeArray* daeFloatType::createArray() {
844     return new daeTArray<daeFloat>;
845 }
846 
createArray()847 daeArray* daeDoubleType::createArray() {
848     return new daeTArray<daeDouble>;
849 }
850 
createArray()851 daeArray* daeStringRefType::createArray() {
852     return new daeTArray<daeStringRef>;
853 }
854 
createArray()855 daeArray* daeTokenType::createArray() {
856     return new daeTArray<daeStringRef>;
857 }
858 
createArray()859 daeArray* daeElementRefType::createArray() {
860     return new daeTArray<daeElementRef>;
861 }
862 
createArray()863 daeArray* daeEnumType::createArray() {
864     return new daeTArray<daeEnum>;
865 }
866 
createArray()867 daeArray* daeRawRefType::createArray() {
868     return new daeTArray<daeRawRef>;
869 }
870 
createArray()871 daeArray* daeResolverType::createArray() {
872     // !!!steveT
873     // The daeURI object no longer has a constructor that takes no arguments, so
874     // it's not compatible with daeTArray. Therefore this method currently can't be used,
875     // and asserts if you try to use it. The DOM doesn't ever call this code now,
876     // so the situation is sort of alright, but we might need to fix this in the future.
877     assert(false);
878     return NULL;
879 }
880 
createArray()881 daeArray* daeIDResolverType::createArray() {
882     return new daeTArray<daeIDRef>;
883 }
884 
885 
copy(daeChar * src,daeChar * dst)886 void daeBoolType::copy(daeChar* src, daeChar* dst) {
887     (daeBool&)*dst = (daeBool&)*src;
888 }
889 
copy(daeChar * src,daeChar * dst)890 void daeIntType::copy(daeChar* src, daeChar* dst) {
891     (daeInt&)*dst = (daeInt&)*src;
892 }
893 
copy(daeChar * src,daeChar * dst)894 void daeLongType::copy(daeChar* src, daeChar* dst) {
895     (daeLong&)*dst = (daeLong&)*src;
896 }
897 
copy(daeChar * src,daeChar * dst)898 void daeUIntType::copy(daeChar* src, daeChar* dst) {
899     (daeUInt&)*dst = (daeUInt&)*src;
900 }
901 
copy(daeChar * src,daeChar * dst)902 void daeULongType::copy(daeChar* src, daeChar* dst) {
903     (daeULong&)*dst = (daeULong&)*src;
904 }
905 
copy(daeChar * src,daeChar * dst)906 void daeShortType::copy(daeChar* src, daeChar* dst) {
907     (daeShort&)*dst = (daeShort&)*src;
908 }
909 
copy(daeChar * src,daeChar * dst)910 void daeFloatType::copy(daeChar* src, daeChar* dst) {
911     (daeFloat&)*dst = (daeFloat&)*src;
912 }
913 
copy(daeChar * src,daeChar * dst)914 void daeDoubleType::copy(daeChar* src, daeChar* dst) {
915     (daeDouble&)*dst = (daeDouble&)*src;
916 }
917 
copy(daeChar * src,daeChar * dst)918 void daeStringRefType::copy(daeChar* src, daeChar* dst) {
919     (daeStringRef&)*dst = (daeStringRef&)*src;
920 }
921 
copy(daeChar * src,daeChar * dst)922 void daeTokenType::copy(daeChar* src, daeChar* dst) {
923     (daeStringRef&)*dst = (daeStringRef&)*src;
924 }
925 
copy(daeChar * src,daeChar * dst)926 void daeElementRefType::copy(daeChar* src, daeChar* dst) {
927     (daeElementRef&)*dst = (daeElementRef&)*src;
928 }
929 
copy(daeChar * src,daeChar * dst)930 void daeEnumType::copy(daeChar* src, daeChar* dst) {
931     (daeEnum&)*dst = (daeEnum&)*src;
932 }
933 
copy(daeChar * src,daeChar * dst)934 void daeRawRefType::copy(daeChar* src, daeChar* dst) {
935     (daeRawRef&)*dst = (daeRawRef&)*src;
936 }
937 
copy(daeChar * src,daeChar * dst)938 void daeResolverType::copy(daeChar* src, daeChar* dst) {
939     (daeURI&)*dst = (daeURI&)*src;
940 }
941 
copy(daeChar * src,daeChar * dst)942 void daeIDResolverType::copy(daeChar* src, daeChar* dst) {
943     (daeIDRef&)*dst = (daeIDRef&)*src;
944 }
945 
setDocument(daeChar * value,daeDocument * doc)946 void daeResolverType::setDocument(daeChar* value, daeDocument* doc) {
947     daeURI* uri = (daeURI*)value;
948     uri->setContainer(uri->getContainer());
949 }
950 
setDocument(daeArray & array,daeDocument * doc)951 void daeResolverType::setDocument(daeArray& array, daeDocument* doc) {
952     // !!!steveT
953     // The daeURI object no longer has a constructor that takes no arguments, so
954     // it's not compatible with daeTArray. Therefore this method currently can't be used,
955     // and asserts if you try to use it. The DOM doesn't ever call this code now,
956     // so the situation is sort of alright, but we might need to fix this in the future.
957     assert(false);
958 }
959