1 : // $Id: AnyScalar.cc 59 2007-07-17 14:43:23Z tb $
2 :
3 : /*
4 : * STX Expression Parser C++ Framework v0.7
5 : * Copyright (C) 2007 Timo Bingmann
6 : *
7 : * This library is free software; you can redistribute it and/or modify it
8 : * under the terms of the GNU Lesser General Public License as published by the
9 : * Free Software Foundation; either version 2.1 of the License, or (at your
10 : * option) any later version.
11 : *
12 : * This library is distributed in the hope that it will be useful, but WITHOUT
13 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 : * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15 : * for more details.
16 : *
17 : * You should have received a copy of the GNU Lesser General Public License
18 : * along with this library; if not, write to the Free Software Foundation,
19 : * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 : */
21 :
22 : /** \file AnyScalar.cc
23 : * Implementation of the typed scalar value class AnyScalar used by the parser
24 : * to represent values.
25 : */
26 :
27 : #include "AnyScalar.h"
28 : #include "ExpressionParser.h"
29 :
30 : #include <stdlib.h>
31 : #include <functional>
32 : #include <algorithm>
33 :
34 : #include <boost/lexical_cast.hpp>
35 :
36 : namespace stx {
37 :
38 23 : bool AnyScalar::operator==(const AnyScalar &a) const
39 : {
40 23 : if (atype != a.atype) return false;
41 :
42 22 : switch(atype)
43 : {
44 : case ATTRTYPE_INVALID:
45 0 : assert(0);
46 : return false;
47 :
48 : case ATTRTYPE_BOOL:
49 : case ATTRTYPE_CHAR:
50 : case ATTRTYPE_SHORT:
51 : case ATTRTYPE_INTEGER:
52 14 : return (val._int == a.val._int);
53 :
54 : case ATTRTYPE_BYTE:
55 : case ATTRTYPE_WORD:
56 : case ATTRTYPE_DWORD:
57 0 : return (val._uint == a.val._uint);
58 :
59 : case ATTRTYPE_LONG:
60 0 : return (val._long == a.val._long);
61 :
62 : case ATTRTYPE_QWORD:
63 0 : return (val._ulong == a.val._ulong);
64 :
65 : case ATTRTYPE_FLOAT:
66 0 : return (val._float == a.val._float);
67 :
68 : case ATTRTYPE_DOUBLE:
69 4 : return (val._double == a.val._double);
70 :
71 : case ATTRTYPE_STRING:
72 4 : assert(val._string && a.val._string);
73 4 : return (*val._string == *a.val._string);
74 : }
75 :
76 0 : assert(0);
77 : return false;
78 : }
79 :
80 6 : AnyScalar::attrtype_t AnyScalar::stringToType(const char* s)
81 : {
82 6 : std::string str = s;
83 12 : std::transform(str.begin(), str.end(), str.begin(), tolower);
84 :
85 : // Stupid method, but maybe faster than using a biggy std::map with a
86 : // case-insensitive equality.
87 :
88 6 : if (str == "bool")
89 1 : return ATTRTYPE_BOOL;
90 :
91 5 : if (str == "char")
92 1 : return ATTRTYPE_CHAR;
93 4 : if (str == "short")
94 0 : return ATTRTYPE_SHORT;
95 4 : if (str == "integer" || str == "int")
96 4 : return ATTRTYPE_INTEGER;
97 0 : if (str == "long")
98 0 : return ATTRTYPE_LONG;
99 :
100 0 : if (str == "byte")
101 0 : return ATTRTYPE_BYTE;
102 0 : if (str == "word")
103 0 : return ATTRTYPE_WORD;
104 0 : if (str == "dword")
105 0 : return ATTRTYPE_DWORD;
106 0 : if (str == "qword")
107 0 : return ATTRTYPE_QWORD;
108 :
109 0 : if (str == "float")
110 0 : return ATTRTYPE_FLOAT;
111 0 : if (str == "double")
112 0 : return ATTRTYPE_DOUBLE;
113 :
114 0 : if (str == "string")
115 0 : return ATTRTYPE_STRING;
116 :
117 0 : throw(ConversionException("Invalid type name."));
118 : }
119 :
120 0 : bool AnyScalar::isValidAttrtype(attrtype_t at)
121 : {
122 0 : switch(at)
123 : {
124 : default:
125 : case ATTRTYPE_INVALID:
126 0 : return false;
127 :
128 : case ATTRTYPE_BOOL:
129 : case ATTRTYPE_CHAR:
130 : case ATTRTYPE_SHORT:
131 : case ATTRTYPE_INTEGER:
132 : case ATTRTYPE_LONG:
133 : case ATTRTYPE_BYTE:
134 : case ATTRTYPE_WORD:
135 : case ATTRTYPE_DWORD:
136 : case ATTRTYPE_QWORD:
137 : case ATTRTYPE_FLOAT:
138 : case ATTRTYPE_DOUBLE:
139 : case ATTRTYPE_STRING:
140 0 : return true;
141 : }
142 : }
143 :
144 10 : std::string AnyScalar::getTypeString(attrtype_t at)
145 : {
146 10 : switch(at)
147 : {
148 0 : case ATTRTYPE_INVALID: return "invalid";
149 1 : case ATTRTYPE_BOOL: return "bool";
150 1 : case ATTRTYPE_CHAR: return "char";
151 1 : case ATTRTYPE_SHORT: return "short";
152 4 : case ATTRTYPE_INTEGER: return "integer";
153 1 : case ATTRTYPE_LONG: return "long";
154 0 : case ATTRTYPE_BYTE: return "byte";
155 0 : case ATTRTYPE_WORD: return "word";
156 0 : case ATTRTYPE_DWORD: return "dword";
157 0 : case ATTRTYPE_QWORD: return "qword";
158 0 : case ATTRTYPE_FLOAT: return "float";
159 1 : case ATTRTYPE_DOUBLE: return "double";
160 1 : case ATTRTYPE_STRING: return "string";
161 : }
162 0 : return "unknown";
163 : }
164 :
165 4 : int AnyScalar::getTypeLength(attrtype_t t)
166 : {
167 4 : switch(t)
168 : {
169 : case ATTRTYPE_INVALID:
170 0 : assert(0);
171 : return 0;
172 :
173 : case ATTRTYPE_BOOL:
174 : // weird value. beware!
175 1 : return 0;
176 :
177 : case ATTRTYPE_CHAR:
178 1 : return sizeof(char);
179 :
180 : case ATTRTYPE_BYTE:
181 0 : return sizeof(unsigned char);
182 :
183 : case ATTRTYPE_SHORT:
184 1 : return sizeof(short);
185 :
186 : case ATTRTYPE_WORD:
187 0 : return sizeof(unsigned short);
188 :
189 : case ATTRTYPE_INTEGER:
190 1 : return sizeof(int);
191 :
192 : case ATTRTYPE_DWORD:
193 0 : return sizeof(unsigned int);
194 :
195 : case ATTRTYPE_LONG:
196 0 : return sizeof(long long);
197 :
198 : case ATTRTYPE_QWORD:
199 0 : return sizeof(unsigned long long);
200 :
201 : case ATTRTYPE_FLOAT:
202 0 : return sizeof(float);
203 :
204 : case ATTRTYPE_DOUBLE:
205 0 : return sizeof(double);
206 :
207 : case ATTRTYPE_STRING:
208 0 : return -1;
209 :
210 : }
211 0 : assert(0);
212 : return -1;
213 : }
214 :
215 4 : unsigned int AnyScalar::getValueLength() const
216 : {
217 4 : switch(atype)
218 : {
219 : case ATTRTYPE_INVALID:
220 0 : assert(0);
221 : return 0;
222 :
223 : case ATTRTYPE_BOOL:
224 : // weird value. beware!
225 1 : return 0;
226 :
227 : case ATTRTYPE_CHAR:
228 1 : return sizeof(char);
229 :
230 : case ATTRTYPE_BYTE:
231 0 : return sizeof(unsigned char);
232 :
233 : case ATTRTYPE_SHORT:
234 1 : return sizeof(short);
235 :
236 : case ATTRTYPE_WORD:
237 0 : return sizeof(unsigned short);
238 :
239 : case ATTRTYPE_INTEGER:
240 1 : return sizeof(int);
241 :
242 : case ATTRTYPE_DWORD:
243 0 : return sizeof(unsigned int);
244 :
245 : case ATTRTYPE_LONG:
246 0 : return sizeof(long long);
247 :
248 : case ATTRTYPE_QWORD:
249 0 : return sizeof(unsigned long long);
250 :
251 : case ATTRTYPE_FLOAT:
252 0 : return sizeof(float);
253 :
254 : case ATTRTYPE_DOUBLE:
255 0 : return sizeof(double);
256 :
257 : case ATTRTYPE_STRING:
258 0 : assert(val._string);
259 0 : return sizeof(unsigned char) + static_cast<unsigned int>(val._string->size());
260 : }
261 :
262 0 : assert(0);
263 : return 0;
264 : }
265 :
266 85 : bool AnyScalar::setInteger(int i)
267 : {
268 85 : switch(atype)
269 : {
270 : case ATTRTYPE_INVALID:
271 0 : assert(0);
272 : return false;
273 :
274 : case ATTRTYPE_BOOL:
275 2 : val._int = (i != 0) ? 1 : 0;
276 2 : return true;
277 :
278 : case ATTRTYPE_CHAR:
279 5 : if (SCHAR_MIN <= i && i <= SCHAR_MAX) {
280 4 : val._int = i;
281 4 : return true;
282 : }
283 1 : if (SCHAR_MIN > i) val._int = SCHAR_MIN;
284 1 : if (i > SCHAR_MAX) val._int = SCHAR_MAX;
285 1 : return false;
286 :
287 : case ATTRTYPE_BYTE:
288 0 : if (i <= UCHAR_MAX) {
289 0 : val._uint = static_cast<unsigned char>(i);
290 0 : return true;
291 : }
292 0 : if (0 > i) val._uint = 0;
293 0 : if (i > UCHAR_MAX) val._uint = UCHAR_MAX;
294 0 : return false;
295 :
296 : case ATTRTYPE_SHORT:
297 5 : if (SHRT_MIN <= i && i <= SHRT_MAX) {
298 4 : val._int = i;
299 4 : return true;
300 : }
301 1 : if (SHRT_MIN > i) val._int = SHRT_MIN;
302 1 : if (i > SHRT_MAX) val._int = SHRT_MAX;
303 1 : return false;
304 :
305 : case ATTRTYPE_WORD:
306 0 : if (i <= USHRT_MAX) {
307 0 : val._uint = static_cast<unsigned short>(i);
308 0 : return true;
309 : }
310 0 : if (0 > i) val._uint = 0;
311 0 : if (i > USHRT_MAX) val._uint = USHRT_MAX;
312 0 : return false;
313 :
314 : case ATTRTYPE_INTEGER:
315 : if (INT_MIN <= i && i <= INT_MAX) {
316 70 : val._int = i;
317 70 : return true;
318 : }
319 : if (INT_MIN > i) val._int = INT_MIN;
320 : if (i > INT_MAX) val._int = INT_MAX;
321 : return false;
322 :
323 : case ATTRTYPE_DWORD:
324 : if (static_cast<unsigned int>(i) <= UINT_MAX) {
325 0 : val._uint = i;
326 0 : return true;
327 : }
328 : if (0 > i) val._uint = 0;
329 : return false;
330 :
331 : case ATTRTYPE_LONG:
332 0 : val._long = i;
333 0 : return true;
334 :
335 : case ATTRTYPE_QWORD:
336 0 : val._ulong = i;
337 0 : return true;
338 :
339 : case ATTRTYPE_FLOAT:
340 0 : val._float = static_cast<float>(i);
341 0 : return true;
342 :
343 : case ATTRTYPE_DOUBLE:
344 0 : val._double = static_cast<double>(i);
345 0 : return true;
346 :
347 : case ATTRTYPE_STRING:
348 3 : assert(val._string);
349 3 : *val._string = boost::lexical_cast<std::string>(i);
350 3 : return true;
351 : }
352 :
353 0 : assert(0);
354 : return false;
355 : }
356 :
357 1 : bool AnyScalar::setLong(long long l)
358 : {
359 1 : switch(atype)
360 : {
361 : case ATTRTYPE_INVALID:
362 0 : assert(0);
363 : return false;
364 :
365 : case ATTRTYPE_BOOL:
366 0 : val._int = (l != 0) ? 1 : 0;
367 0 : return true;
368 :
369 : case ATTRTYPE_CHAR:
370 0 : if (SCHAR_MIN <= l && l <= SCHAR_MAX) {
371 0 : val._int = static_cast<char>(l);
372 0 : return true;
373 : }
374 0 : if (SCHAR_MIN > l) val._int = SCHAR_MIN;
375 0 : if (l > SCHAR_MAX) val._int = SCHAR_MAX;
376 0 : return false;
377 :
378 : case ATTRTYPE_BYTE:
379 0 : if (0 <= l && l <= UCHAR_MAX) {
380 0 : val._uint = static_cast<unsigned char>(l);
381 0 : return true;
382 : }
383 0 : if (0 > l) val._uint = 0;
384 0 : if (l > UCHAR_MAX) val._uint = UCHAR_MAX;
385 0 : return false;
386 :
387 : case ATTRTYPE_SHORT:
388 0 : if (SHRT_MIN <= l && l <= SHRT_MAX) {
389 0 : val._int = static_cast<short>(l);
390 0 : return true;
391 : }
392 0 : if (SHRT_MIN > l) val._int = SHRT_MIN;
393 0 : if (l > SHRT_MAX) val._int = SHRT_MAX;
394 0 : return false;
395 :
396 : case ATTRTYPE_WORD:
397 0 : if (l <= USHRT_MAX) {
398 0 : val._uint = static_cast<unsigned short>(l);
399 0 : return true;
400 : }
401 0 : if (0 > l) val._uint = 0;
402 0 : if (l > USHRT_MAX) val._uint = USHRT_MAX;
403 0 : return false;
404 :
405 : case ATTRTYPE_INTEGER:
406 1 : if (INT_MIN <= l && l <= INT_MAX) {
407 0 : val._int = static_cast<int>(l);
408 0 : return true;
409 : }
410 1 : if (INT_MIN > l) val._int = INT_MIN;
411 1 : if (l > INT_MAX) val._int = INT_MAX;
412 1 : return false;
413 :
414 : case ATTRTYPE_DWORD:
415 : if (static_cast<unsigned int>(l) <= UINT_MAX) {
416 0 : val._uint = static_cast<unsigned int>(l);
417 0 : return true;
418 : }
419 : if (0 > l) val._uint = 0;
420 : if (l > UINT_MAX) val._uint = UINT_MAX;
421 : return false;
422 :
423 : case ATTRTYPE_LONG:
424 0 : val._long = l;
425 0 : return true;
426 :
427 : case ATTRTYPE_QWORD:
428 0 : val._ulong = l;
429 0 : return true;
430 :
431 : case ATTRTYPE_FLOAT:
432 0 : val._float = static_cast<float>(l);
433 0 : return true;
434 :
435 : case ATTRTYPE_DOUBLE:
436 0 : val._double = static_cast<double>(l);
437 0 : return true;
438 :
439 : case ATTRTYPE_STRING:
440 0 : assert(val._string);
441 0 : *val._string = boost::lexical_cast<std::string>(l);
442 0 : return true;
443 : }
444 :
445 0 : assert(0);
446 : return false;
447 : }
448 :
449 7 : bool AnyScalar::setDouble(double d)
450 : {
451 7 : switch(atype)
452 : {
453 : case ATTRTYPE_INVALID:
454 0 : assert(0);
455 : return false;
456 :
457 : case ATTRTYPE_BOOL:
458 1 : if (0 <= d && d < 0.5) {
459 1 : val._int = 0;
460 1 : return true;
461 : }
462 0 : if (0.5 <= d && d <= 1) {
463 0 : val._int = 1;
464 0 : return true;
465 : }
466 0 : val._int = 1;
467 0 : return false;
468 :
469 : case ATTRTYPE_CHAR:
470 : case ATTRTYPE_SHORT:
471 : case ATTRTYPE_INTEGER:
472 4 : return setInteger( static_cast<int>(d) );
473 :
474 : case ATTRTYPE_LONG:
475 0 : return setLong( static_cast<long long>(d) );
476 :
477 : case ATTRTYPE_BYTE:
478 : case ATTRTYPE_WORD:
479 : case ATTRTYPE_DWORD:
480 0 : return setInteger( static_cast<unsigned int>(d) );
481 :
482 : case ATTRTYPE_QWORD:
483 0 : return setLong( static_cast<unsigned long long>(d) );
484 :
485 : case ATTRTYPE_FLOAT:
486 2 : val._float = static_cast<float>(d);
487 2 : return true;
488 :
489 : case ATTRTYPE_DOUBLE:
490 0 : val._double = d;
491 0 : return true;
492 :
493 : case ATTRTYPE_STRING:
494 0 : assert(val._string);
495 0 : *val._string = boost::lexical_cast<std::string>(d);
496 0 : return true;
497 : }
498 :
499 0 : assert(0);
500 : return false;
501 : }
502 :
503 94 : bool AnyScalar::setString(const std::string &s)
504 : {
505 94 : switch(atype)
506 : {
507 : case ATTRTYPE_INVALID:
508 0 : assert(0);
509 : return false;
510 :
511 : case ATTRTYPE_BOOL:
512 8 : if (s == "0" || s == "f" || s == "false" || s == "n" || s == "no") {
513 1 : val._int = 0;
514 1 : return true;
515 : }
516 7 : if (s == "1" || s == "t" || s == "true" || s == "y" || s == "yes") {
517 6 : val._int = 1;
518 6 : return true;
519 : }
520 1 : return false;
521 :
522 : case ATTRTYPE_CHAR:
523 : case ATTRTYPE_SHORT:
524 : case ATTRTYPE_INTEGER:
525 : {
526 : char *endptr;
527 68 : long i = strtol(s.c_str(), &endptr, 10);
528 68 : if (endptr != NULL && *endptr == 0)
529 67 : return setInteger(i);
530 1 : return false;
531 : }
532 :
533 : case ATTRTYPE_LONG:
534 : {
535 : char *endptr;
536 : #ifndef _MSC_VER
537 0 : long long l = strtoll(s.c_str(), &endptr, 10);
538 : #else
539 : long long l = _strtoi64(s.c_str(), &endptr, 10);
540 : #endif
541 0 : if (endptr != NULL && *endptr == 0)
542 0 : return setLong(l);
543 0 : return false;
544 : }
545 :
546 : case ATTRTYPE_BYTE:
547 : case ATTRTYPE_WORD:
548 : case ATTRTYPE_DWORD:
549 : {
550 : char *endptr;
551 0 : unsigned long u = strtoul(s.c_str(), &endptr, 10);
552 0 : if (endptr != NULL && *endptr == 0)
553 0 : return setInteger(u);
554 0 : return false;
555 : }
556 :
557 : case ATTRTYPE_QWORD:
558 : {
559 : char *endptr;
560 : #ifndef _MSC_VER
561 0 : unsigned long long u = strtoull(s.c_str(), &endptr, 10);
562 : #else
563 : unsigned long long u = _strtoui64(s.c_str(), &endptr, 10);
564 : #endif
565 0 : if (endptr != NULL && *endptr == 0)
566 0 : return setLong(u);
567 0 : return false;
568 : }
569 :
570 : case ATTRTYPE_FLOAT:
571 : {
572 : char *endptr;
573 1 : float f = static_cast<float>(strtod(s.c_str(), &endptr));
574 1 : if (endptr != NULL && *endptr == 0) {
575 1 : val._float = f;
576 1 : return true;
577 : }
578 0 : return false;
579 : }
580 :
581 : case ATTRTYPE_DOUBLE:
582 : {
583 : char *endptr;
584 10 : double d = strtod(s.c_str(), &endptr);
585 10 : if (endptr != NULL && *endptr == 0) {
586 10 : val._double = d;
587 10 : return true;
588 : }
589 0 : return false;
590 : }
591 :
592 : case ATTRTYPE_STRING:
593 : {
594 7 : assert(val._string);
595 7 : *val._string = s;
596 7 : return true;
597 : }
598 : }
599 :
600 0 : assert(0);
601 : return false;
602 : }
603 :
604 7 : bool AnyScalar::setStringQuoted(const std::string &s)
605 : {
606 : // unescape string
607 7 : if (s.size() < 2) return false;
608 7 : if (s[0] != '"') return false;
609 7 : if (s[s.size()-1] != '"') return false;
610 :
611 7 : std::string t;
612 7 : t.reserve(s.size() + s.size() / 32);
613 :
614 86 : for(unsigned int i = 1; i + 1 < s.size(); i++)
615 : {
616 79 : if (s[i] == '\\')
617 : {
618 16 : i++;
619 23 : if (i >= s.size() - 1) return false;
620 :
621 16 : switch(s[i])
622 : {
623 1 : case 'a': t += '\a'; break;
624 1 : case 'b': t += '\b'; break;
625 1 : case 'f': t += '\f'; break;
626 3 : case 'n': t += '\n'; break;
627 1 : case 'r': t += '\r'; break;
628 1 : case 't': t += '\t'; break;
629 1 : case 'v': t += '\v'; break;
630 1 : case '\'': t += '\''; break;
631 3 : case '"': t += '"'; break;
632 3 : case '\\': t += '\\'; break;
633 0 : case '?': t += '?'; break;
634 :
635 : default:
636 0 : t += '\\';
637 0 : t += s[i];
638 : break;
639 : }
640 : }
641 : else {
642 63 : t += s[i];
643 : }
644 : }
645 :
646 7 : return setString(t);
647 : }
648 :
649 8 : AnyScalar& AnyScalar::setAutoString(const std::string &input)
650 : {
651 : // - int: input was readable by strtoll and is small enough.
652 : // - long: input was readable by strtoll
653 : {
654 : char *endptr;
655 : #ifndef _MSC_VER
656 8 : long long l = strtoll(input.c_str(), &endptr, 10);
657 : #else
658 : long long l = _strtoi64(input.c_str(), &endptr, 10);
659 : #endif
660 8 : if (endptr != NULL && *endptr == 0)
661 : {
662 5 : if (INT_MIN <= l && l <= INT_MAX)
663 : {
664 3 : resetType(ATTRTYPE_INTEGER);
665 3 : val._int = l;
666 3 : return *this;
667 : }
668 : else
669 : {
670 2 : resetType(ATTRTYPE_LONG);
671 2 : val._long = l;
672 2 : return *this;
673 : }
674 : }
675 : }
676 :
677 : // - double: input was readble by strtod
678 : {
679 : char *endptr;
680 3 : double d = strtod(input.c_str(), &endptr);
681 3 : if (endptr != NULL && *endptr == 0)
682 : {
683 1 : resetType(ATTRTYPE_DOUBLE);
684 1 : val._double = d;
685 1 : return *this;
686 : }
687 : }
688 :
689 : // - string: all above failed.
690 2 : resetType(ATTRTYPE_STRING);
691 2 : *val._string = input;
692 :
693 2 : return *this;
694 : }
695 :
696 14 : bool AnyScalar::getBoolean() const
697 : {
698 14 : switch(atype)
699 : {
700 : case ATTRTYPE_INVALID:
701 0 : assert(0);
702 : return false;
703 :
704 : case ATTRTYPE_BOOL:
705 2 : return (val._int != 0);
706 :
707 : case ATTRTYPE_CHAR:
708 : case ATTRTYPE_SHORT:
709 : case ATTRTYPE_INTEGER:
710 9 : return (val._int != 0);
711 :
712 : case ATTRTYPE_BYTE:
713 : case ATTRTYPE_WORD:
714 : case ATTRTYPE_DWORD:
715 0 : return (val._uint != 0);
716 :
717 : case ATTRTYPE_LONG:
718 0 : return (val._long != 0);
719 :
720 : case ATTRTYPE_QWORD:
721 0 : return (val._ulong != 0);
722 :
723 : case ATTRTYPE_FLOAT:
724 1 : return (val._float != 0.0f);
725 :
726 : case ATTRTYPE_DOUBLE:
727 0 : return (val._double != 0.0f);
728 :
729 : case ATTRTYPE_STRING:
730 : {
731 2 : assert(val._string);
732 :
733 2 : if (*val._string == "0" || *val._string == "f" || *val._string == "false"
734 : || *val._string == "n" || *val._string == "no") {
735 1 : return false;
736 : }
737 1 : if (*val._string == "1" || *val._string == "t" || *val._string == "true"
738 : || *val._string == "y" || *val._string == "yes") {
739 0 : return true;
740 : }
741 :
742 1 : throw(ConversionException("Cannot convert string to boolean."));
743 : }
744 : }
745 :
746 0 : assert(0);
747 : return false;
748 : }
749 :
750 41 : int AnyScalar::getInteger() const
751 : {
752 41 : switch(atype)
753 : {
754 : case ATTRTYPE_INVALID:
755 0 : assert(0);
756 : return false;
757 :
758 : case ATTRTYPE_BOOL:
759 29 : return val._int;
760 :
761 : case ATTRTYPE_CHAR:
762 : case ATTRTYPE_SHORT:
763 : case ATTRTYPE_INTEGER:
764 6 : return val._int;
765 :
766 : case ATTRTYPE_BYTE:
767 : case ATTRTYPE_WORD:
768 : case ATTRTYPE_DWORD:
769 0 : return val._uint;
770 :
771 : case ATTRTYPE_LONG:
772 0 : if (val._long > INT_MAX) return INT_MAX;
773 0 : if (val._long < INT_MIN) return INT_MIN;
774 :
775 0 : return static_cast<int>(val._long);
776 :
777 : case ATTRTYPE_QWORD:
778 0 : if (val._ulong > UINT_MAX) return UINT_MAX;
779 0 : return static_cast<int>(val._ulong);
780 :
781 : case ATTRTYPE_FLOAT:
782 3 : return static_cast<int>(val._float);
783 :
784 : case ATTRTYPE_DOUBLE:
785 2 : return static_cast<int>(val._double);
786 :
787 : case ATTRTYPE_STRING:
788 : {
789 1 : assert(val._string);
790 : char *endptr;
791 1 : long i = strtol(val._string->c_str(), &endptr, 10);
792 1 : if (endptr != NULL && *endptr == 0)
793 1 : return i;
794 :
795 0 : throw(ConversionException("Cannot convert string to integer."));
796 : }
797 : }
798 :
799 0 : assert(0);
800 : return false;
801 : }
802 :
803 0 : unsigned int AnyScalar::getUnsignedInteger() const
804 : {
805 0 : switch(atype)
806 : {
807 : case ATTRTYPE_INVALID:
808 0 : assert(0);
809 : return false;
810 :
811 : case ATTRTYPE_BOOL:
812 : case ATTRTYPE_CHAR:
813 : case ATTRTYPE_SHORT:
814 : case ATTRTYPE_INTEGER:
815 0 : return static_cast<unsigned int>(val._int);
816 :
817 : case ATTRTYPE_BYTE:
818 : case ATTRTYPE_WORD:
819 : case ATTRTYPE_DWORD:
820 0 : return val._uint;
821 :
822 : case ATTRTYPE_LONG:
823 0 : return static_cast<unsigned int>(val._long);
824 :
825 : case ATTRTYPE_QWORD:
826 0 : return static_cast<unsigned int>(val._ulong);
827 :
828 : case ATTRTYPE_FLOAT:
829 0 : return static_cast<unsigned int>(val._float);
830 :
831 : case ATTRTYPE_DOUBLE:
832 0 : return static_cast<unsigned int>(val._double);
833 :
834 : case ATTRTYPE_STRING:
835 : {
836 0 : assert(val._string);
837 : char *endptr;
838 0 : unsigned long i = strtoul(val._string->c_str(), &endptr, 10);
839 0 : if (endptr != NULL && *endptr == 0)
840 0 : return i;
841 :
842 0 : throw(ConversionException("Cannot convert string to unsigned integer."));
843 : }
844 : }
845 :
846 0 : assert(0);
847 : return false;
848 : }
849 :
850 0 : long long AnyScalar::getLong() const
851 : {
852 0 : switch(atype)
853 : {
854 : case ATTRTYPE_INVALID:
855 0 : assert(0);
856 : return false;
857 :
858 : case ATTRTYPE_BOOL:
859 : case ATTRTYPE_CHAR:
860 : case ATTRTYPE_SHORT:
861 : case ATTRTYPE_INTEGER:
862 : case ATTRTYPE_BYTE:
863 : case ATTRTYPE_WORD:
864 : case ATTRTYPE_DWORD:
865 0 : return static_cast<long long>(val._int);
866 :
867 : case ATTRTYPE_LONG:
868 0 : return val._long;
869 :
870 : case ATTRTYPE_QWORD:
871 0 : return val._ulong;
872 :
873 : case ATTRTYPE_FLOAT:
874 0 : return static_cast<long long>(val._float);
875 :
876 : case ATTRTYPE_DOUBLE:
877 0 : return static_cast<long long>(val._double);
878 :
879 : case ATTRTYPE_STRING:
880 : {
881 0 : assert(val._string);
882 : char *endptr;
883 : #ifndef _MSC_VER
884 0 : long long l = strtoll(val._string->c_str(), &endptr, 10);
885 : #else
886 : long long l = _strtoi64(val._string->c_str(), &endptr, 10);
887 : #endif
888 0 : if (endptr != NULL && *endptr == 0)
889 0 : return l;
890 :
891 0 : throw(ConversionException("Cannot convert string to long long."));
892 : }
893 : }
894 :
895 0 : assert(0);
896 : return false;
897 : }
898 :
899 0 : unsigned long long AnyScalar::getUnsignedLong() const
900 : {
901 0 : switch(atype)
902 : {
903 : case ATTRTYPE_INVALID:
904 0 : assert(0);
905 : return false;
906 :
907 : case ATTRTYPE_BOOL:
908 : case ATTRTYPE_CHAR:
909 : case ATTRTYPE_SHORT:
910 : case ATTRTYPE_INTEGER:
911 0 : return static_cast<unsigned long long>(val._int);
912 :
913 : case ATTRTYPE_BYTE:
914 : case ATTRTYPE_WORD:
915 : case ATTRTYPE_DWORD:
916 0 : return static_cast<unsigned long long>(val._uint);
917 :
918 : case ATTRTYPE_LONG:
919 0 : return static_cast<unsigned long long>(val._long);
920 :
921 : case ATTRTYPE_QWORD:
922 0 : return val._ulong;
923 :
924 : case ATTRTYPE_FLOAT:
925 0 : return static_cast<unsigned long long>(val._float);
926 :
927 : case ATTRTYPE_DOUBLE:
928 0 : return static_cast<unsigned long long>(val._double);
929 :
930 : case ATTRTYPE_STRING:
931 : {
932 0 : assert(val._string);
933 : char *endptr;
934 : #ifndef _MSC_VER
935 0 : unsigned long long u = strtoull(val._string->c_str(), &endptr, 10);
936 : #else
937 : unsigned long long u = _strtoui64(val._string->c_str(), &endptr, 10);
938 : #endif
939 0 : if (endptr != NULL && *endptr == 0)
940 0 : return u;
941 :
942 0 : throw(ConversionException("Cannot convert string to unsigned long long."));
943 : }
944 : }
945 0 : assert(0);
946 : return false;
947 : }
948 :
949 8 : double AnyScalar::getDouble() const
950 : {
951 8 : switch(atype)
952 : {
953 : case ATTRTYPE_INVALID:
954 0 : assert(0);
955 : return false;
956 :
957 : case ATTRTYPE_BOOL:
958 : case ATTRTYPE_CHAR:
959 : case ATTRTYPE_SHORT:
960 : case ATTRTYPE_INTEGER:
961 : case ATTRTYPE_BYTE:
962 : case ATTRTYPE_WORD:
963 : case ATTRTYPE_DWORD:
964 4 : return static_cast<double>(val._int);
965 :
966 : case ATTRTYPE_LONG:
967 0 : return static_cast<double>(val._long);
968 :
969 : case ATTRTYPE_QWORD:
970 0 : return static_cast<double>(val._ulong);
971 :
972 : case ATTRTYPE_FLOAT:
973 1 : return static_cast<double>(val._float);
974 :
975 : case ATTRTYPE_DOUBLE:
976 2 : return val._double;
977 :
978 : case ATTRTYPE_STRING:
979 : {
980 1 : assert(val._string);
981 : char *endptr;
982 1 : double d = strtod(val._string->c_str(), &endptr);
983 1 : if (endptr != NULL && *endptr == 0)
984 1 : return d;
985 :
986 0 : throw(ConversionException("Cannot convert string to double."));
987 : }
988 : }
989 0 : assert(0);
990 : return false;
991 : }
992 :
993 79 : std::string AnyScalar::getString() const
994 : {
995 79 : switch(atype)
996 : {
997 : case ATTRTYPE_INVALID:
998 0 : assert(0);
999 : return false;
1000 :
1001 : case ATTRTYPE_BOOL:
1002 9 : if (val._int == 0) return "false";
1003 8 : if (val._int == 1) return "true";
1004 0 : assert(0);
1005 : return "invalid";
1006 :
1007 : case ATTRTYPE_CHAR:
1008 : case ATTRTYPE_SHORT:
1009 : case ATTRTYPE_INTEGER:
1010 : {
1011 50 : return boost::lexical_cast<std::string>(val._int);
1012 : }
1013 :
1014 : case ATTRTYPE_BYTE:
1015 : case ATTRTYPE_WORD:
1016 : case ATTRTYPE_DWORD:
1017 : {
1018 0 : return boost::lexical_cast<std::string>(val._uint);
1019 : }
1020 :
1021 : case ATTRTYPE_LONG:
1022 : {
1023 0 : return boost::lexical_cast<std::string>(val._long);
1024 : }
1025 :
1026 : case ATTRTYPE_QWORD:
1027 : {
1028 0 : return boost::lexical_cast<std::string>(val._ulong);
1029 : }
1030 :
1031 : case ATTRTYPE_FLOAT:
1032 : {
1033 3 : return boost::lexical_cast<std::string>(val._float);
1034 : }
1035 :
1036 : case ATTRTYPE_DOUBLE:
1037 : {
1038 7 : return boost::lexical_cast<std::string>(val._double);
1039 : }
1040 :
1041 : case ATTRTYPE_STRING:
1042 : {
1043 10 : assert(val._string);
1044 10 : return *val._string;
1045 : }
1046 : }
1047 0 : assert(0);
1048 : return false;
1049 : }
1050 :
1051 4 : std::string AnyScalar::getStringQuoted() const
1052 : {
1053 4 : std::string str = getString();
1054 4 : std::string os = "\"";
1055 :
1056 8 : os.reserve(2 + str.size() + str.size() / 16);
1057 :
1058 : // escape string s
1059 68 : for(std::string::const_iterator si = str.begin(); si != str.end(); ++si)
1060 : {
1061 64 : switch(*si)
1062 : {
1063 : case '\a':
1064 0 : os += "\\a";
1065 0 : break;
1066 :
1067 : case '\b':
1068 0 : os += "\\b";
1069 0 : break;
1070 :
1071 : case '\f':
1072 0 : os += "\\f";
1073 0 : break;
1074 :
1075 : case '\n':
1076 2 : os += "\\n";
1077 2 : break;
1078 :
1079 : case '\r':
1080 0 : os += "\\r";
1081 0 : break;
1082 :
1083 : case '\t':
1084 0 : os += "\\t";
1085 0 : break;
1086 :
1087 : case '\v':
1088 0 : os += "\\v";
1089 0 : break;
1090 :
1091 : case '\\':
1092 2 : os += "\\\\";
1093 2 : break;
1094 :
1095 : case '"':
1096 2 : os += "\\\"";
1097 2 : break;
1098 :
1099 : case '\'':
1100 0 : os += "\\'";
1101 0 : break;
1102 :
1103 : default:
1104 58 : os += *si;
1105 : break;
1106 : }
1107 : }
1108 :
1109 4 : os += "\"";
1110 4 : return os;
1111 : }
1112 :
1113 8 : void AnyScalar::resetType(attrtype_t t)
1114 : {
1115 : // if setting to a string and this is not a string, create the object
1116 8 : if (t == ATTRTYPE_STRING) {
1117 2 : if (atype != ATTRTYPE_STRING) {
1118 2 : val._string = new std::string;
1119 : }
1120 : }
1121 : else {
1122 6 : if (atype == ATTRTYPE_STRING) {
1123 1 : delete val._string;
1124 : }
1125 :
1126 6 : val._ulong = 0;
1127 : }
1128 :
1129 8 : atype = t;
1130 8 : }
1131 :
1132 4 : bool AnyScalar::convertType(attrtype_t t)
1133 : {
1134 : // same source and target type?
1135 4 : if (atype == t) return true;
1136 :
1137 : // special case if this object was initialised with the ATTRTYPE_INVALID:
1138 : // all the get...() below would assert.
1139 4 : if (atype == ATTRTYPE_INVALID)
1140 : {
1141 0 : atype = t;
1142 0 : if (atype == ATTRTYPE_STRING) {
1143 0 : val._string = new std::string;
1144 : }
1145 0 : return true;
1146 : }
1147 :
1148 4 : switch(t)
1149 : {
1150 : case ATTRTYPE_INVALID:
1151 0 : assert(0);
1152 : return false;
1153 :
1154 : case ATTRTYPE_BOOL:
1155 : {
1156 0 : bool v = getBoolean();
1157 0 : if (atype == ATTRTYPE_STRING) delete val._string;
1158 0 : val._int = v;
1159 0 : atype = t;
1160 0 : return true;
1161 : }
1162 :
1163 : case ATTRTYPE_CHAR:
1164 : case ATTRTYPE_SHORT:
1165 : case ATTRTYPE_INTEGER:
1166 : {
1167 3 : int v = getInteger();
1168 3 : if (atype == ATTRTYPE_STRING) delete val._string;
1169 3 : val._int = v;
1170 3 : atype = t;
1171 3 : return true;
1172 : }
1173 :
1174 : case ATTRTYPE_BYTE:
1175 : case ATTRTYPE_WORD:
1176 : case ATTRTYPE_DWORD:
1177 : {
1178 0 : unsigned int v = getUnsignedInteger();
1179 0 : if (atype == ATTRTYPE_STRING) delete val._string;
1180 0 : val._uint = v;
1181 0 : atype = t;
1182 0 : return true;
1183 : }
1184 :
1185 : case ATTRTYPE_LONG:
1186 : {
1187 0 : long long v = getLong();
1188 0 : if (atype == ATTRTYPE_STRING) delete val._string;
1189 0 : val._long = v;
1190 0 : atype = t;
1191 0 : return true;
1192 : }
1193 :
1194 : case ATTRTYPE_QWORD:
1195 : {
1196 0 : unsigned long long v = getLong();
1197 0 : if (atype == ATTRTYPE_STRING) delete val._string;
1198 0 : val._ulong = v;
1199 0 : atype = t;
1200 0 : return true;
1201 : }
1202 :
1203 : case ATTRTYPE_FLOAT:
1204 : {
1205 0 : float f = static_cast<float>(getDouble());
1206 0 : if (atype == ATTRTYPE_STRING) delete val._string;
1207 0 : val._float = f;
1208 0 : atype = t;
1209 0 : return true;
1210 : }
1211 :
1212 : case ATTRTYPE_DOUBLE:
1213 : {
1214 0 : double d = getDouble();
1215 0 : if (atype == ATTRTYPE_STRING) delete val._string;
1216 0 : val._double = d;
1217 0 : atype = t;
1218 0 : return true;
1219 : }
1220 :
1221 : case ATTRTYPE_STRING:
1222 : {
1223 1 : val._string = new std::string(getString());
1224 1 : atype = t;
1225 1 : return true;
1226 : }
1227 : }
1228 0 : assert(0);
1229 : return false;
1230 : }
1231 :
1232 7 : AnyScalar AnyScalar::operator-() const
1233 : {
1234 7 : AnyScalar at = *this;
1235 :
1236 7 : switch(at.atype)
1237 : {
1238 : case ATTRTYPE_INVALID:
1239 0 : assert(0);
1240 : throw(ConversionException("Negating invalid type."));
1241 :
1242 : case ATTRTYPE_BOOL:
1243 2 : if (at.val._int > 0) at.val._int = 0;
1244 1 : else at.val._int = 1;
1245 2 : break;
1246 :
1247 : case ATTRTYPE_CHAR:
1248 : case ATTRTYPE_SHORT:
1249 : case ATTRTYPE_INTEGER:
1250 3 : at.val._int = - at.val._int;
1251 3 : break;
1252 :
1253 : case ATTRTYPE_BYTE:
1254 : case ATTRTYPE_WORD:
1255 : case ATTRTYPE_DWORD:
1256 0 : at.val._uint = - at.val._uint;
1257 0 : break;
1258 :
1259 : case ATTRTYPE_LONG:
1260 0 : at.val._long = - at.val._long;
1261 0 : break;
1262 :
1263 : case ATTRTYPE_QWORD:
1264 0 : at.val._ulong = - at.val._ulong;
1265 0 : break;
1266 :
1267 : case ATTRTYPE_FLOAT:
1268 0 : at.val._float = - at.val._float;
1269 0 : break;
1270 :
1271 : case ATTRTYPE_DOUBLE:
1272 2 : at.val._double = - at.val._double;
1273 2 : break;
1274 :
1275 : case ATTRTYPE_STRING:
1276 : {
1277 0 : if (!at.convertType(ATTRTYPE_DOUBLE))
1278 0 : throw(ConversionException("Cannot convert string to double for negation."));
1279 :
1280 0 : at.val._double = - at.val._double;
1281 : break;
1282 : }
1283 : }
1284 :
1285 0 : return at;
1286 : }
1287 :
1288 : template <template <typename Type> class Operator, char OpName>
1289 : AnyScalar AnyScalar::binary_arith_op(const AnyScalar &b) const
1290 : {
1291 25 : switch(atype)
1292 : {
1293 : case ATTRTYPE_INVALID:
1294 0 : assert(0);
1295 : throw(ConversionException(std::string("Invalid type for first operand of binary operator ")+OpName+"."));
1296 :
1297 : case ATTRTYPE_BOOL:
1298 0 : throw(ConversionException("No binary operators are allowed on bool values."));
1299 :
1300 : case ATTRTYPE_CHAR:
1301 : case ATTRTYPE_SHORT:
1302 : case ATTRTYPE_INTEGER:
1303 : {
1304 18 : switch(b.atype)
1305 : {
1306 : case ATTRTYPE_INVALID:
1307 0 : assert(0);
1308 : throw(ConversionException(std::string("Invalid type for second operand of binary operator ")+OpName+"."));
1309 :
1310 : case ATTRTYPE_BOOL:
1311 0 : throw(ConversionException(std::string("Binary operator ")+OpName+" is not permitted on bool values."));
1312 :
1313 : case ATTRTYPE_CHAR:
1314 : case ATTRTYPE_SHORT:
1315 : case ATTRTYPE_INTEGER:
1316 : {
1317 : Operator<int> op;
1318 1 : if (OpName == '/' && b.val._int == 0) throw(ArithmeticException("Integer division by zero"));
1319 13 : return AnyScalar( op(val._int, b.val._int) );
1320 : }
1321 :
1322 : case ATTRTYPE_BYTE:
1323 : case ATTRTYPE_WORD:
1324 : case ATTRTYPE_DWORD:
1325 : {
1326 : Operator<int> op;
1327 0 : if (OpName == '/' && b.val._uint == 0) throw(ArithmeticException("Integer division by zero"));
1328 0 : return AnyScalar( op(val._int, static_cast<signed int>(b.val._uint)) );
1329 : }
1330 :
1331 : case ATTRTYPE_LONG:
1332 : {
1333 : Operator<long long> op;
1334 0 : if (OpName == '/' && b.val._long == 0) throw(ArithmeticException("Integer division by zero"));
1335 0 : return AnyScalar( op(val._int, b.val._long) );
1336 : }
1337 :
1338 : case ATTRTYPE_QWORD:
1339 : {
1340 : Operator<long long> op;
1341 0 : if (OpName == '/' && b.val._ulong == 0) throw(ArithmeticException("Integer division by zero"));
1342 0 : return AnyScalar( op(static_cast<long long>(val._int), static_cast<long long>(b.val._ulong)) );
1343 : }
1344 :
1345 : case ATTRTYPE_FLOAT:
1346 : {
1347 : Operator<float> op;
1348 0 : return AnyScalar( op(static_cast<float>(val._int), b.val._float));
1349 : }
1350 :
1351 : case ATTRTYPE_DOUBLE:
1352 : {
1353 : Operator<double> op;
1354 5 : return AnyScalar( op(static_cast<double>(val._int), b.val._double) );
1355 : }
1356 :
1357 : case ATTRTYPE_STRING:
1358 : {
1359 0 : AnyScalar bc = b;
1360 :
1361 0 : if (!bc.convertType(ATTRTYPE_INTEGER))
1362 0 : throw(ConversionException(std::string("Could not convert string to integer for binary operator ")+OpName+"."));
1363 :
1364 : Operator<int> op;
1365 :
1366 0 : int bval = bc.getInteger();
1367 0 : if (OpName == '/' && bval == 0) throw(ArithmeticException("Integer division by zero"));
1368 :
1369 0 : return AnyScalar( op(val._int, bval) );
1370 : }
1371 : }
1372 0 : break;
1373 : }
1374 :
1375 : case ATTRTYPE_BYTE:
1376 : case ATTRTYPE_WORD:
1377 : case ATTRTYPE_DWORD:
1378 : {
1379 0 : switch(b.atype)
1380 : {
1381 : case ATTRTYPE_INVALID:
1382 0 : assert(0);
1383 : throw(ConversionException(std::string("Invalid type for second operand of binary operator ")+OpName+"."));
1384 :
1385 : case ATTRTYPE_BOOL:
1386 0 : throw(ConversionException(std::string("Binary operator ")+OpName+" is not permitted on bool values."));
1387 :
1388 : case ATTRTYPE_CHAR:
1389 : case ATTRTYPE_SHORT:
1390 : case ATTRTYPE_INTEGER:
1391 : {
1392 : Operator<int> op;
1393 0 : if (OpName == '/' && b.val._int == 0) throw(ArithmeticException("Integer division by zero"));
1394 0 : return AnyScalar( op(static_cast<signed int>(val._uint), b.val._int) );
1395 : }
1396 :
1397 : case ATTRTYPE_BYTE:
1398 : case ATTRTYPE_WORD:
1399 : case ATTRTYPE_DWORD:
1400 : {
1401 : Operator<unsigned int> op;
1402 0 : if (OpName == '/' && b.val._uint == 0) throw(ArithmeticException("Integer division by zero"));
1403 0 : return AnyScalar( op(val._uint, b.val._uint) );
1404 : }
1405 :
1406 : case ATTRTYPE_LONG:
1407 : {
1408 : Operator<long long> op;
1409 0 : if (OpName == '/' && b.val._long == 0) throw(ArithmeticException("Integer division by zero"));
1410 0 : return AnyScalar( op(static_cast<signed long long>(val._uint), b.val._long) );
1411 : }
1412 :
1413 : case ATTRTYPE_QWORD:
1414 : {
1415 : Operator<unsigned long long> op;
1416 0 : if (OpName == '/' && b.val._ulong == 0) throw(ArithmeticException("Integer division by zero"));
1417 0 : return AnyScalar( op(static_cast<unsigned long long>(val._uint), b.val._ulong) );
1418 : }
1419 :
1420 : case ATTRTYPE_FLOAT:
1421 : {
1422 : Operator<float> op;
1423 0 : return AnyScalar( op(static_cast<float>(val._uint), b.val._float));
1424 : }
1425 :
1426 : case ATTRTYPE_DOUBLE:
1427 : {
1428 : Operator<double> op;
1429 0 : return AnyScalar( op(static_cast<double>(val._uint), b.val._double) );
1430 : }
1431 :
1432 : case ATTRTYPE_STRING:
1433 : {
1434 0 : AnyScalar bc = b;
1435 :
1436 0 : if (!bc.convertType(ATTRTYPE_DWORD))
1437 0 : throw(ConversionException(std::string("Could not convert string to unsigned integer for binary operator ")+OpName+"."));
1438 :
1439 : Operator<unsigned int> op;
1440 :
1441 0 : int bval = bc.getInteger();
1442 0 : if (OpName == '/' && bval == 0) throw(ArithmeticException("Integer division by zero"));
1443 :
1444 0 : return AnyScalar( op(val._int, bval) );
1445 : }
1446 : }
1447 0 : break;
1448 : }
1449 :
1450 : case ATTRTYPE_LONG:
1451 : {
1452 0 : switch(b.atype)
1453 : {
1454 : case ATTRTYPE_INVALID:
1455 0 : assert(0);
1456 : throw(ConversionException(std::string("Invalid type for second operand of binary operator ")+OpName+"."));
1457 :
1458 : case ATTRTYPE_BOOL:
1459 0 : throw(ConversionException(std::string("Binary operator ")+OpName+" is not permitted on bool values."));
1460 :
1461 : case ATTRTYPE_CHAR:
1462 : case ATTRTYPE_SHORT:
1463 : case ATTRTYPE_INTEGER:
1464 : {
1465 : Operator<long long> op;
1466 0 : if (OpName == '/' && b.val._int == 0) throw(ArithmeticException("Integer division by zero"));
1467 0 : return AnyScalar( op(val._long, static_cast<long long>(b.val._int)) );
1468 : }
1469 :
1470 : case ATTRTYPE_BYTE:
1471 : case ATTRTYPE_WORD:
1472 : case ATTRTYPE_DWORD:
1473 : {
1474 : Operator<long long> op;
1475 0 : if (OpName == '/' && b.val._uint == 0) throw(ArithmeticException("Integer division by zero"));
1476 0 : return AnyScalar( op(val._long, static_cast<signed long long>(b.val._uint)) );
1477 : }
1478 :
1479 : case ATTRTYPE_LONG:
1480 : {
1481 : Operator<long long> op;
1482 0 : if (OpName == '/' && b.val._long == 0) throw(ArithmeticException("Integer division by zero"));
1483 0 : return AnyScalar( op(val._long, b.val._long) );
1484 : }
1485 :
1486 : case ATTRTYPE_QWORD:
1487 : {
1488 : Operator<long long> op;
1489 0 : if (OpName == '/' && b.val._ulong == 0) throw(ArithmeticException("Integer division by zero"));
1490 0 : return AnyScalar( op(val._long, static_cast<signed long long>(b.val._ulong)) );
1491 : }
1492 :
1493 : case ATTRTYPE_FLOAT:
1494 : {
1495 : Operator<float> op;
1496 0 : return AnyScalar( op(static_cast<float>(val._long), b.val._float));
1497 : }
1498 :
1499 : case ATTRTYPE_DOUBLE:
1500 : {
1501 : Operator<double> op;
1502 0 : return AnyScalar( op(static_cast<double>(val._long), b.val._double) );
1503 : }
1504 :
1505 : case ATTRTYPE_STRING:
1506 : {
1507 0 : AnyScalar bc = b;
1508 :
1509 0 : if (!bc.convertType(ATTRTYPE_LONG))
1510 0 : throw(ConversionException(std::string("Could not convert string to long for binary operator ")+OpName+"."));
1511 :
1512 : Operator<long long> op;
1513 :
1514 0 : long long bval = bc.getLong();
1515 0 : if (OpName == '/' && bval == 0) throw(ArithmeticException("Integer division by zero"));
1516 :
1517 0 : return AnyScalar( op(val._long, bval) );
1518 : }
1519 : }
1520 0 : break;
1521 : }
1522 :
1523 : case ATTRTYPE_QWORD:
1524 : {
1525 0 : switch(b.atype)
1526 : {
1527 : case ATTRTYPE_INVALID:
1528 0 : assert(0);
1529 : throw(ConversionException(std::string("Invalid type for second operand of binary operator ")+OpName+"."));
1530 :
1531 : case ATTRTYPE_BOOL:
1532 0 : throw(ConversionException(std::string("Binary operator ")+OpName+" is not permitted on bool values."));
1533 :
1534 : case ATTRTYPE_CHAR:
1535 : case ATTRTYPE_SHORT:
1536 : case ATTRTYPE_INTEGER:
1537 : {
1538 : Operator<long long> op;
1539 0 : if (OpName == '/' && b.val._int == 0) throw(ArithmeticException("Integer division by zero"));
1540 0 : return AnyScalar( op(static_cast<signed long long>(val._ulong), b.val._int) );
1541 : }
1542 :
1543 : case ATTRTYPE_BYTE:
1544 : case ATTRTYPE_WORD:
1545 : case ATTRTYPE_DWORD:
1546 : {
1547 : Operator<unsigned long long> op;
1548 0 : if (OpName == '/' && b.val._uint == 0) throw(ArithmeticException("Integer division by zero"));
1549 0 : return AnyScalar( op(val._ulong, static_cast<unsigned long long>(b.val._uint)) );
1550 : }
1551 :
1552 : case ATTRTYPE_LONG:
1553 : {
1554 : Operator<long long> op;
1555 0 : if (OpName == '/' && b.val._long == 0) throw(ArithmeticException("Integer division by zero"));
1556 0 : return AnyScalar( op(static_cast<signed long long>(val._ulong), b.val._long) );
1557 : }
1558 :
1559 : case ATTRTYPE_QWORD:
1560 : {
1561 : Operator<unsigned long long> op;
1562 0 : if (OpName == '/' && b.val._ulong == 0) throw(ArithmeticException("Integer division by zero"));
1563 0 : return AnyScalar( op(val._ulong, b.val._ulong) );
1564 : }
1565 :
1566 : case ATTRTYPE_FLOAT:
1567 : {
1568 : Operator<float> op;
1569 0 : return AnyScalar( op(static_cast<float>(val._ulong), b.val._float));
1570 : }
1571 :
1572 : case ATTRTYPE_DOUBLE:
1573 : {
1574 : Operator<double> op;
1575 0 : return AnyScalar( op(static_cast<double>(val._ulong), b.val._double) );
1576 : }
1577 :
1578 : case ATTRTYPE_STRING:
1579 : {
1580 0 : AnyScalar bc = b;
1581 :
1582 0 : if (!bc.convertType(ATTRTYPE_QWORD))
1583 0 : throw(ConversionException(std::string("Could not convert string to unsigned long long for binary operator ")+OpName+"."));
1584 :
1585 : Operator<unsigned long long> op;
1586 :
1587 0 : long long bval = bc.getLong();
1588 0 : if (OpName == '/' && bval == 0) throw(ArithmeticException("Integer division by zero"));
1589 :
1590 0 : return AnyScalar( op(val._ulong, bval) );
1591 : }
1592 : }
1593 0 : break;
1594 : }
1595 :
1596 : case ATTRTYPE_FLOAT:
1597 : {
1598 0 : switch(b.atype)
1599 : {
1600 : case ATTRTYPE_INVALID:
1601 0 : assert(0);
1602 : throw(ConversionException(std::string("Invalid type for second operand of binary operator ")+OpName+"."));
1603 :
1604 : case ATTRTYPE_BOOL:
1605 0 : throw(ConversionException(std::string("Binary operator ")+OpName+" is not permitted on bool values."));
1606 :
1607 : case ATTRTYPE_CHAR:
1608 : case ATTRTYPE_SHORT:
1609 : case ATTRTYPE_INTEGER:
1610 : {
1611 : Operator<float> op;
1612 0 : return AnyScalar( op(val._float, static_cast<float>(b.val._int)) );
1613 : }
1614 :
1615 : case ATTRTYPE_BYTE:
1616 : case ATTRTYPE_WORD:
1617 : case ATTRTYPE_DWORD:
1618 : {
1619 : Operator<float> op;
1620 0 : return AnyScalar( op(val._float, static_cast<float>(b.val._uint)) );
1621 : }
1622 :
1623 : case ATTRTYPE_LONG:
1624 : {
1625 : Operator<float> op;
1626 0 : return AnyScalar( op(val._float, static_cast<float>(b.val._long)) );
1627 : }
1628 :
1629 : case ATTRTYPE_QWORD:
1630 : {
1631 : Operator<float> op;
1632 0 : return AnyScalar( op(val._float, static_cast<float>(b.val._ulong)) );
1633 : }
1634 :
1635 : case ATTRTYPE_FLOAT:
1636 : {
1637 : Operator<float> op;
1638 0 : return AnyScalar( op(val._float, b.val._float));
1639 : }
1640 :
1641 : case ATTRTYPE_DOUBLE:
1642 : {
1643 : Operator<double> op;
1644 0 : return AnyScalar( op(static_cast<double>(val._float), b.val._double) );
1645 : }
1646 :
1647 : case ATTRTYPE_STRING:
1648 : {
1649 0 : AnyScalar bc = b;
1650 :
1651 0 : if (!bc.convertType(ATTRTYPE_FLOAT))
1652 0 : throw(ConversionException(std::string("Could not convert string to float for binary operator ")+OpName+"."));
1653 :
1654 : Operator<float> op;
1655 :
1656 0 : return AnyScalar( op(val._float, bc.val._float) );
1657 : }
1658 : }
1659 :
1660 0 : break;
1661 : }
1662 :
1663 : case ATTRTYPE_DOUBLE:
1664 : {
1665 3 : switch(b.atype)
1666 : {
1667 : case ATTRTYPE_INVALID:
1668 0 : assert(0);
1669 : throw(ConversionException(std::string("Invalid type for second operand of binary operator ")+OpName+"."));
1670 :
1671 : case ATTRTYPE_BOOL:
1672 0 : throw(ConversionException(std::string("Binary operator ")+OpName+" is not permitted on bool values."));
1673 :
1674 : case ATTRTYPE_CHAR:
1675 : case ATTRTYPE_SHORT:
1676 : case ATTRTYPE_INTEGER:
1677 : {
1678 : Operator<double> op;
1679 2 : return AnyScalar( op(val._double, static_cast<double>(b.val._int)) );
1680 : }
1681 :
1682 : case ATTRTYPE_BYTE:
1683 : case ATTRTYPE_WORD:
1684 : case ATTRTYPE_DWORD:
1685 : {
1686 : Operator<double> op;
1687 0 : return AnyScalar( op(val._double, static_cast<double>(b.val._uint)) );
1688 : }
1689 :
1690 : case ATTRTYPE_LONG:
1691 : {
1692 : Operator<double> op;
1693 0 : return AnyScalar( op(val._double, static_cast<double>(b.val._long)) );
1694 : }
1695 :
1696 : case ATTRTYPE_QWORD:
1697 : {
1698 : Operator<double> op;
1699 0 : return AnyScalar( op(val._double, static_cast<double>(b.val._ulong)) );
1700 : }
1701 :
1702 : case ATTRTYPE_FLOAT:
1703 : {
1704 : Operator<double> op;
1705 0 : return AnyScalar( op(val._double, static_cast<double>(b.val._float)));
1706 : }
1707 :
1708 : case ATTRTYPE_DOUBLE:
1709 : {
1710 : Operator<double> op;
1711 1 : return AnyScalar( op(val._double, b.val._double) );
1712 : }
1713 :
1714 : case ATTRTYPE_STRING:
1715 : {
1716 0 : AnyScalar bc = b;
1717 :
1718 0 : if (!bc.convertType(ATTRTYPE_DOUBLE))
1719 0 : throw(ConversionException(std::string("Could not convert string to double for binary operator ")+OpName+"."));
1720 :
1721 : Operator<double> op;
1722 :
1723 0 : return AnyScalar( op(val._double, bc.getDouble()) );
1724 : }
1725 : }
1726 :
1727 0 : break;
1728 : }
1729 :
1730 : // if this is a string, then the other type defines the conversion
1731 : case ATTRTYPE_STRING:
1732 : {
1733 4 : switch(b.atype)
1734 : {
1735 : case ATTRTYPE_INVALID:
1736 0 : assert(0);
1737 : throw(ConversionException(std::string("Invalid type for second operand of binary operator ")+OpName+"."));
1738 :
1739 : case ATTRTYPE_BOOL:
1740 0 : throw(ConversionException(std::string("Binary operator ")+OpName+" is not permitted on bool values."));
1741 :
1742 : case ATTRTYPE_CHAR:
1743 : case ATTRTYPE_SHORT:
1744 : case ATTRTYPE_INTEGER:
1745 : {
1746 : Operator<int> op;
1747 0 : if (OpName == '/' && b.val._int == 0) throw(ArithmeticException("Integer division by zero"));
1748 0 : return AnyScalar( op(this->getInteger(), b.val._int) );
1749 : }
1750 :
1751 : case ATTRTYPE_BYTE:
1752 : case ATTRTYPE_WORD:
1753 : case ATTRTYPE_DWORD:
1754 : {
1755 : Operator<unsigned int> op;
1756 0 : if (OpName == '/' && b.val._uint == 0) throw(ArithmeticException("Integer division by zero"));
1757 0 : return AnyScalar( op(this->getUnsignedInteger(), b.val._uint) );
1758 : }
1759 :
1760 : case ATTRTYPE_LONG:
1761 : {
1762 : Operator<long long> op;
1763 0 : if (OpName == '/' && b.val._long == 0) throw(ArithmeticException("Integer division by zero"));
1764 0 : return AnyScalar( op(this->getLong(), b.val._long) );
1765 : }
1766 :
1767 : case ATTRTYPE_QWORD:
1768 : {
1769 : Operator<unsigned long long> op;
1770 0 : if (OpName == '/' && b.val._ulong == 0) throw(ArithmeticException("Integer division by zero"));
1771 0 : return AnyScalar( op(this->getUnsignedLong(), b.val._ulong) );
1772 : }
1773 :
1774 : case ATTRTYPE_FLOAT:
1775 : {
1776 : Operator<float> op;
1777 0 : return AnyScalar( op(static_cast<float>(this->getDouble()), b.val._float) );
1778 : }
1779 :
1780 : case ATTRTYPE_DOUBLE:
1781 : {
1782 : Operator<double> op;
1783 1 : return AnyScalar( op(this->getDouble(), b.val._double) );
1784 : }
1785 :
1786 : case ATTRTYPE_STRING:
1787 : if (OpName == '+')
1788 : {
1789 3 : return AnyScalar( *val._string + *b.val._string );
1790 : }
1791 :
1792 0 : throw(ConversionException(std::string("Binary operator ")+OpName+" is not allowed between two string values."));
1793 : }
1794 : break;
1795 : }
1796 : }
1797 0 : assert(0);
1798 : throw(ConversionException("Invalid binary operator call. (PROGRAM ERROR)"));
1799 : }
1800 :
1801 : // *** Force instantiation of binary_op for the four arithmetic operators
1802 :
1803 : /// Forced instantiation of binary_arith_op for AnyScalar::operator+()
1804 : template AnyScalar AnyScalar::binary_arith_op<std::plus, '+'>(const AnyScalar &b) const;
1805 :
1806 : /// Forced instantiation of binary_arith_op for AnyScalar::operator-()
1807 : template AnyScalar AnyScalar::binary_arith_op<std::minus, '-'>(const AnyScalar &b) const;
1808 :
1809 : /// Forced instantiation of binary_arith_op for AnyScalar::operator*()
1810 : template AnyScalar AnyScalar::binary_arith_op<std::multiplies, '*'>(const AnyScalar &b) const;
1811 :
1812 : /// Forced instantiation of binary_arith_op for AnyScalar::operator/()
1813 : template AnyScalar AnyScalar::binary_arith_op<std::divides, '/'>(const AnyScalar &b) const;
1814 :
1815 : template <template <typename Type> class Operator, int OpNum>
1816 : bool AnyScalar::binary_comp_op(const AnyScalar &b) const
1817 : {
1818 : static const char *OpNameArray[] = { "==", "!=", "<", ">", "<=", ">=" };
1819 :
1820 15 : switch(atype)
1821 : {
1822 : case ATTRTYPE_INVALID:
1823 0 : assert(0);
1824 : throw(ConversionException(std::string("Invalid type for first operand of binary operator ")+OpNameArray[OpNum]+"."));
1825 :
1826 : case ATTRTYPE_BOOL:
1827 : {
1828 0 : switch(b.atype)
1829 : {
1830 : case ATTRTYPE_INVALID:
1831 0 : assert(0);
1832 : throw(ConversionException(std::string("Invalid type for second operand of binary operator ")+OpNameArray[OpNum]+"."));
1833 :
1834 : case ATTRTYPE_BOOL:
1835 : {
1836 : Operator<bool> op;
1837 0 : return op(val._int, b.val._int);
1838 : }
1839 :
1840 : default:
1841 0 : throw(ConversionException(std::string("Binary operator ")+OpNameArray[OpNum]+" is not permitted on bool values."));
1842 : }
1843 : break;
1844 : }
1845 :
1846 : case ATTRTYPE_CHAR:
1847 : case ATTRTYPE_SHORT:
1848 : case ATTRTYPE_INTEGER:
1849 : {
1850 12 : switch(b.atype)
1851 : {
1852 : case ATTRTYPE_INVALID:
1853 0 : assert(0);
1854 : throw(ConversionException(std::string("Invalid type for second operand of binary operator ")+OpNameArray[OpNum]+"."));
1855 :
1856 : case ATTRTYPE_BOOL:
1857 0 : throw(ConversionException(std::string("Binary operator ")+OpNameArray[OpNum]+" is not permitted on bool values."));
1858 :
1859 : case ATTRTYPE_CHAR:
1860 : case ATTRTYPE_SHORT:
1861 : case ATTRTYPE_INTEGER:
1862 : {
1863 : Operator<int> op;
1864 12 : return op(val._int, b.val._int);
1865 : }
1866 :
1867 : case ATTRTYPE_BYTE:
1868 : case ATTRTYPE_WORD:
1869 : case ATTRTYPE_DWORD:
1870 : {
1871 : Operator<int> op;
1872 0 : return op(val._int, static_cast<signed int>(b.val._uint));
1873 : }
1874 :
1875 : case ATTRTYPE_LONG:
1876 : {
1877 : Operator<long long> op;
1878 0 : return op(val._int, b.val._long);
1879 : }
1880 :
1881 : case ATTRTYPE_QWORD:
1882 : {
1883 : Operator<long long> op;
1884 0 : return op(val._int, static_cast<signed long long>(b.val._ulong));
1885 : }
1886 :
1887 : case ATTRTYPE_FLOAT:
1888 : {
1889 : Operator<float> op;
1890 0 : return op(static_cast<float>(val._int), b.val._float);
1891 : }
1892 :
1893 : case ATTRTYPE_DOUBLE:
1894 : {
1895 : Operator<double> op;
1896 0 : return op(static_cast<double>(val._int), b.val._double);
1897 : }
1898 :
1899 : case ATTRTYPE_STRING:
1900 : {
1901 0 : AnyScalar bc = b;
1902 :
1903 0 : if (!bc.convertType(ATTRTYPE_INTEGER))
1904 0 : throw(ConversionException(std::string("Could not convert string to integer for binary operator ")+OpNameArray[OpNum]+"."));
1905 :
1906 : Operator<int> op;
1907 :
1908 0 : return op(val._int, bc.getInteger());
1909 : }
1910 : }
1911 0 : break;
1912 : }
1913 :
1914 : case ATTRTYPE_BYTE:
1915 : case ATTRTYPE_WORD:
1916 : case ATTRTYPE_DWORD:
1917 : {
1918 0 : switch(b.atype)
1919 : {
1920 : case ATTRTYPE_INVALID:
1921 0 : assert(0);
1922 : throw(ConversionException(std::string("Invalid type for second operand of binary operator ")+OpNameArray[OpNum]+"."));
1923 :
1924 : case ATTRTYPE_BOOL:
1925 0 : throw(ConversionException(std::string("Binary operator ")+OpNameArray[OpNum]+" is not permitted on bool values."));
1926 :
1927 : case ATTRTYPE_CHAR:
1928 : case ATTRTYPE_SHORT:
1929 : case ATTRTYPE_INTEGER:
1930 : {
1931 : Operator<int> op;
1932 0 : return op(static_cast<signed int>(val._uint), b.val._int);
1933 : }
1934 :
1935 : case ATTRTYPE_BYTE:
1936 : case ATTRTYPE_WORD:
1937 : case ATTRTYPE_DWORD:
1938 : {
1939 : Operator<unsigned int> op;
1940 0 : return op(val._uint, b.val._uint);
1941 : }
1942 :
1943 : case ATTRTYPE_LONG:
1944 : {
1945 : Operator<long long> op;
1946 0 : return op(static_cast<signed long long>(val._uint), b.val._long);
1947 : }
1948 :
1949 : case ATTRTYPE_QWORD:
1950 : {
1951 : Operator<unsigned long long> op;
1952 0 : return op(static_cast<unsigned long long>(val._uint), b.val._ulong);
1953 : }
1954 :
1955 : case ATTRTYPE_FLOAT:
1956 : {
1957 : Operator<float> op;
1958 0 : return op(static_cast<float>(val._uint), b.val._float);
1959 : }
1960 :
1961 : case ATTRTYPE_DOUBLE:
1962 : {
1963 : Operator<double> op;
1964 0 : return op(static_cast<double>(val._uint), b.val._double);
1965 : }
1966 :
1967 : case ATTRTYPE_STRING:
1968 : {
1969 0 : AnyScalar bc = b;
1970 :
1971 0 : if (!bc.convertType(ATTRTYPE_DWORD))
1972 0 : throw(ConversionException(std::string("Could not convert string to unsigned integer for binary operator ")+OpNameArray[OpNum]+"."));
1973 :
1974 : Operator<unsigned int> op;
1975 :
1976 0 : return op(val._int, bc.getInteger());
1977 : }
1978 : }
1979 0 : break;
1980 : }
1981 :
1982 : case ATTRTYPE_LONG:
1983 : {
1984 0 : switch(b.atype)
1985 : {
1986 : case ATTRTYPE_INVALID:
1987 0 : assert(0);
1988 : throw(ConversionException(std::string("Invalid type for second operand of binary operator ")+OpNameArray[OpNum]+"."));
1989 :
1990 : case ATTRTYPE_BOOL:
1991 0 : throw(ConversionException(std::string("Binary operator ")+OpNameArray[OpNum]+" is not permitted on bool values."));
1992 :
1993 : case ATTRTYPE_CHAR:
1994 : case ATTRTYPE_SHORT:
1995 : case ATTRTYPE_INTEGER:
1996 : {
1997 : Operator<long long> op;
1998 0 : return op(val._long, static_cast<long long>(b.val._int));
1999 : }
2000 :
2001 : case ATTRTYPE_BYTE:
2002 : case ATTRTYPE_WORD:
2003 : case ATTRTYPE_DWORD:
2004 : {
2005 : Operator<long long> op;
2006 0 : return op(val._long, static_cast<signed long long>(b.val._uint));
2007 : }
2008 :
2009 : case ATTRTYPE_LONG:
2010 : {
2011 : Operator<long long> op;
2012 0 : return op(val._long, b.val._long);
2013 : }
2014 :
2015 : case ATTRTYPE_QWORD:
2016 : {
2017 : Operator<long long> op;
2018 0 : return op(val._long, static_cast<signed long long>(b.val._ulong));
2019 : }
2020 :
2021 : case ATTRTYPE_FLOAT:
2022 : {
2023 : Operator<float> op;
2024 0 : return op(static_cast<float>(val._long), b.val._float);
2025 : }
2026 :
2027 : case ATTRTYPE_DOUBLE:
2028 : {
2029 : Operator<double> op;
2030 0 : return op(static_cast<double>(val._long), b.val._double);
2031 : }
2032 :
2033 : case ATTRTYPE_STRING:
2034 : {
2035 0 : AnyScalar bc = b;
2036 :
2037 0 : if (!bc.convertType(ATTRTYPE_LONG))
2038 0 : throw(ConversionException(std::string("Could not convert string to long long for binary operator ")+OpNameArray[OpNum]+"."));
2039 :
2040 : Operator<long long> op;
2041 :
2042 0 : return op(val._long, bc.getLong());
2043 : }
2044 : }
2045 0 : break;
2046 : }
2047 :
2048 : case ATTRTYPE_QWORD:
2049 : {
2050 0 : switch(b.atype)
2051 : {
2052 : case ATTRTYPE_INVALID:
2053 0 : assert(0);
2054 : throw(ConversionException(std::string("Invalid type for second operand of binary operator ")+OpNameArray[OpNum]+"."));
2055 :
2056 : case ATTRTYPE_BOOL:
2057 0 : throw(ConversionException(std::string("Binary operator ")+OpNameArray[OpNum]+" is not permitted on bool values."));
2058 :
2059 : case ATTRTYPE_CHAR:
2060 : case ATTRTYPE_SHORT:
2061 : case ATTRTYPE_INTEGER:
2062 : {
2063 : Operator<long long> op;
2064 0 : return op(val._ulong, static_cast<signed long long>(b.val._int));
2065 : }
2066 :
2067 : case ATTRTYPE_BYTE:
2068 : case ATTRTYPE_WORD:
2069 : case ATTRTYPE_DWORD:
2070 : {
2071 : Operator<unsigned long long> op;
2072 0 : return op(val._ulong, b.val._uint);
2073 : }
2074 :
2075 : case ATTRTYPE_LONG:
2076 : {
2077 : Operator<long long> op;
2078 0 : return op(static_cast<signed long long>(val._ulong), b.val._long);
2079 : }
2080 :
2081 : case ATTRTYPE_QWORD:
2082 : {
2083 : Operator<unsigned long long> op;
2084 0 : return op(val._ulong, b.val._ulong);
2085 : }
2086 :
2087 : case ATTRTYPE_FLOAT:
2088 : {
2089 : Operator<float> op;
2090 0 : return op(static_cast<float>(val._ulong), b.val._float);
2091 : }
2092 :
2093 : case ATTRTYPE_DOUBLE:
2094 : {
2095 : Operator<double> op;
2096 0 : return op(static_cast<double>(val._ulong), b.val._double);
2097 : }
2098 :
2099 : case ATTRTYPE_STRING:
2100 : {
2101 0 : AnyScalar bc = b;
2102 :
2103 0 : if (!bc.convertType(ATTRTYPE_QWORD))
2104 0 : throw(ConversionException(std::string("Could not convert string to unsigned long long for binary operator ")+OpNameArray[OpNum]+"."));
2105 :
2106 : Operator<unsigned long long> op;
2107 :
2108 0 : return op(val._int, bc.getUnsignedLong());
2109 : }
2110 : }
2111 0 : break;
2112 : }
2113 :
2114 : case ATTRTYPE_FLOAT:
2115 : {
2116 0 : switch(b.atype)
2117 : {
2118 : case ATTRTYPE_INVALID:
2119 0 : assert(0);
2120 : throw(ConversionException(std::string("Invalid type for second operand of binary operator ")+OpNameArray[OpNum]+"."));
2121 :
2122 : case ATTRTYPE_BOOL:
2123 0 : throw(ConversionException(std::string("Binary operator ")+OpNameArray[OpNum]+" is not permitted on bool values."));
2124 :
2125 : case ATTRTYPE_CHAR:
2126 : case ATTRTYPE_SHORT:
2127 : case ATTRTYPE_INTEGER:
2128 : {
2129 : Operator<float> op;
2130 0 : return op(val._float, static_cast<float>(b.val._int));
2131 : }
2132 :
2133 : case ATTRTYPE_BYTE:
2134 : case ATTRTYPE_WORD:
2135 : case ATTRTYPE_DWORD:
2136 : {
2137 : Operator<float> op;
2138 0 : return op(val._float, static_cast<float>(b.val._uint));
2139 : }
2140 :
2141 : case ATTRTYPE_LONG:
2142 : {
2143 : Operator<float> op;
2144 0 : return op(val._float, static_cast<float>(b.val._long));
2145 : }
2146 :
2147 : case ATTRTYPE_QWORD:
2148 : {
2149 : Operator<float> op;
2150 0 : return op(val._float, static_cast<float>(b.val._ulong));
2151 : }
2152 :
2153 : case ATTRTYPE_FLOAT:
2154 : {
2155 : Operator<float> op;
2156 0 : return op(val._float, b.val._float);
2157 : }
2158 :
2159 : case ATTRTYPE_DOUBLE:
2160 : {
2161 : Operator<double> op;
2162 0 : return op(static_cast<double>(val._float), b.val._double);
2163 : }
2164 :
2165 : case ATTRTYPE_STRING:
2166 : {
2167 0 : AnyScalar bc = b;
2168 :
2169 0 : if (!bc.convertType(ATTRTYPE_FLOAT))
2170 0 : throw(ConversionException(std::string("Could not convert string to float for binary operator ")+OpNameArray[OpNum]+"."));
2171 :
2172 : Operator<float> op;
2173 :
2174 0 : return op(val._float, bc.val._float);
2175 : }
2176 : }
2177 :
2178 0 : break;
2179 : }
2180 :
2181 : case ATTRTYPE_DOUBLE:
2182 : {
2183 3 : switch(b.atype)
2184 : {
2185 : case ATTRTYPE_INVALID:
2186 0 : assert(0);
2187 : throw(ConversionException(std::string("Invalid type for second operand of binary operator ")+OpNameArray[OpNum]+"."));
2188 :
2189 : case ATTRTYPE_BOOL:
2190 0 : throw(ConversionException(std::string("Binary operator ")+OpNameArray[OpNum]+" is not permitted on bool values."));
2191 :
2192 : case ATTRTYPE_CHAR:
2193 : case ATTRTYPE_SHORT:
2194 : case ATTRTYPE_INTEGER:
2195 : {
2196 : Operator<double> op;
2197 2 : return op(val._double, static_cast<double>(b.val._int));
2198 : }
2199 :
2200 : case ATTRTYPE_BYTE:
2201 : case ATTRTYPE_WORD:
2202 : case ATTRTYPE_DWORD:
2203 : {
2204 : Operator<double> op;
2205 0 : return op(val._double, static_cast<double>(b.val._uint));
2206 : }
2207 :
2208 : case ATTRTYPE_LONG:
2209 : {
2210 : Operator<double> op;
2211 0 : return op(val._double, static_cast<double>(b.val._long));
2212 : }
2213 :
2214 : case ATTRTYPE_QWORD:
2215 : {
2216 : Operator<double> op;
2217 0 : return op(val._double, static_cast<double>(b.val._ulong));
2218 : }
2219 :
2220 : case ATTRTYPE_FLOAT:
2221 : {
2222 : Operator<double> op;
2223 0 : return op(val._double, static_cast<double>(b.val._float));
2224 : }
2225 :
2226 : case ATTRTYPE_DOUBLE:
2227 : {
2228 : Operator<double> op;
2229 1 : return op(val._double, b.val._double);
2230 : }
2231 :
2232 : case ATTRTYPE_STRING:
2233 : {
2234 0 : AnyScalar bc = b;
2235 :
2236 0 : if (!bc.convertType(ATTRTYPE_DOUBLE))
2237 0 : throw(ConversionException(std::string("Could not convert string to double for binary operator ")+OpNameArray[OpNum]+"."));
2238 :
2239 : Operator<double> op;
2240 :
2241 0 : return op(val._double, bc.getDouble());
2242 : }
2243 : }
2244 :
2245 0 : break;
2246 : }
2247 :
2248 : // if this is a string, then the other type defines the conversion
2249 : case ATTRTYPE_STRING:
2250 : {
2251 0 : switch(b.atype)
2252 : {
2253 : case ATTRTYPE_INVALID:
2254 0 : assert(0);
2255 : throw(ConversionException(std::string("Invalid type for second operand of binary operator ")+OpNameArray[OpNum]+"."));
2256 :
2257 : case ATTRTYPE_BOOL:
2258 0 : throw(ConversionException(std::string("Binary operator ")+OpNameArray[OpNum]+" is not permitted on bool values."));
2259 :
2260 : case ATTRTYPE_CHAR:
2261 : case ATTRTYPE_SHORT:
2262 : case ATTRTYPE_INTEGER:
2263 : {
2264 : Operator<int> op;
2265 0 : return op(this->getInteger(), b.val._int);
2266 : }
2267 :
2268 : case ATTRTYPE_BYTE:
2269 : case ATTRTYPE_WORD:
2270 : case ATTRTYPE_DWORD:
2271 : {
2272 : Operator<unsigned int> op;
2273 0 : return op(this->getUnsignedInteger(), b.val._int);
2274 : }
2275 :
2276 : case ATTRTYPE_LONG:
2277 : {
2278 : Operator<long long> op;
2279 0 : return op(this->getLong(), b.val._long);
2280 : }
2281 :
2282 : case ATTRTYPE_QWORD:
2283 : {
2284 : Operator<unsigned long long> op;
2285 0 : return op(this->getUnsignedLong(), b.val._ulong);
2286 : }
2287 :
2288 : case ATTRTYPE_FLOAT:
2289 : {
2290 : Operator<float> op;
2291 0 : return op(static_cast<float>(this->getDouble()), b.val._float);
2292 : }
2293 :
2294 : case ATTRTYPE_DOUBLE:
2295 : {
2296 : Operator<double> op;
2297 0 : return op(this->getDouble(), b.val._double);
2298 : }
2299 :
2300 : case ATTRTYPE_STRING:
2301 : {
2302 : Operator<std::string> op;
2303 0 : return op(*val._string, *b.val._string);
2304 : }
2305 : }
2306 : break;
2307 : }
2308 : }
2309 0 : assert(0);
2310 : throw(ConversionException("Invalid binary operator call. (PROGRAM ERROR)"));
2311 : }
2312 :
2313 : /// Forced instantiation of binary_comp_op for AnyScalar::equal_to()
2314 : template bool AnyScalar::binary_comp_op<std::equal_to, 0>(const AnyScalar &b) const;
2315 :
2316 : /// Forced instantiation of binary_comp_op for AnyScalar::not_equal_to()
2317 : template bool AnyScalar::binary_comp_op<std::not_equal_to, 1>(const AnyScalar &b) const;
2318 :
2319 : /// Forced instantiation of binary_comp_op for AnyScalar::less()
2320 : template bool AnyScalar::binary_comp_op<std::less, 2>(const AnyScalar &b) const;
2321 :
2322 : /// Forced instantiation of binary_comp_op for AnyScalar::greater()
2323 : template bool AnyScalar::binary_comp_op<std::greater, 3>(const AnyScalar &b) const;
2324 :
2325 : /// Forced instantiation of binary_comp_op for AnyScalar::less_equal()
2326 : template bool AnyScalar::binary_comp_op<std::less_equal, 4>(const AnyScalar &b) const;
2327 :
2328 : /// Forced instantiation of binary_comp_op for AnyScalar::greater_equal()
2329 : template bool AnyScalar::binary_comp_op<std::greater_equal, 5>(const AnyScalar &b) const;
2330 0 :
2331 : } // namespace stx
|