1 : // $Id: AnyScalar.h 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.h
23 : * Definition of a typed scalar value class AnyScalar used by the parser to
24 : * represent values.
25 : */
26 :
27 : #ifndef _STX_AnyScalar_H_
28 : #define _STX_AnyScalar_H_
29 :
30 : #include <string>
31 : #include <stdexcept>
32 : #include <functional>
33 : #include <ostream>
34 : #include <assert.h>
35 :
36 : namespace stx {
37 :
38 : /** AnyScalar constructs objects holding a typed scalar value. It supports
39 : * boolean values, integer values both signed and unsigned, floating point
40 : * values and strings. The class provides operators which will compare scalars
41 : * between other scalars by converting them into a common domain. Furthermore
42 : * arithmetic operator will compose one or two scalars where the calculation is
43 : * done in the "higher" domain. */
44 :
45 : class AnyScalar
46 : {
47 : public:
48 : /// Enumeration establishing identifiers for all supported types. All
49 : /// "small" integer types are included, because the class use originally
50 : /// designed for serializing large amounts of data.
51 : enum attrtype_t
52 : {
53 : /// Flag identifier for an uninitialized object.
54 : ATTRTYPE_INVALID = 0x00,
55 :
56 : /// A boolean type holding only true and false.
57 : ATTRTYPE_BOOL = 0x01,
58 :
59 : /// Character type, not viewed as a letter or digit, but as 8 bit
60 : /// signed integer.
61 : ATTRTYPE_CHAR = 0x10,
62 :
63 : /// Short signed integer type, 2 bytes long.
64 : ATTRTYPE_SHORT = 0x11,
65 :
66 : /// Medium signed integer type, 4 bytes long.
67 : ATTRTYPE_INTEGER = 0x12,
68 :
69 : /// Long (long) signed integer type, 8 bytes long.
70 : ATTRTYPE_LONG = 0x13,
71 :
72 : /// Byte type, not viewed as a letter or digit, but as 8 bit unsigned
73 : /// integer.
74 : ATTRTYPE_BYTE = 0x20,
75 :
76 : /// Short unsigned integer type, 2 bytes long.
77 : ATTRTYPE_WORD = 0x21,
78 :
79 : /// Medium unsigned integer type, 4 bytes long.
80 : ATTRTYPE_DWORD = 0x22,
81 :
82 : /// Long (long) unsigned integer type, 8 bytes long.
83 : ATTRTYPE_QWORD = 0x23,
84 :
85 : /// Single precision floating point type, 4 bytes long.
86 : ATTRTYPE_FLOAT = 0x30,
87 :
88 : /// Double precision floating point type, 8 bytes long.
89 : ATTRTYPE_DOUBLE = 0x31,
90 :
91 : /// String type, variable length. Needs much extra care to handle
92 : /// memory allocation.
93 : ATTRTYPE_STRING = 0x40
94 : };
95 :
96 : private:
97 : /// The currently set type in the union.
98 : attrtype_t atype;
99 :
100 : /// Union type to holding the current value of an AnyScalar.
101 : union value_t
102 : {
103 : /// Used for ATTRTYPE_BOOL, ATTRTYPE_CHAR, ATTRTYPE_SHORT, ATTRTYPE_INTEGER
104 : int _int;
105 :
106 : /// Used for ATTRTYPE_BYTE, ATTRTYPE_WORD, ATTRTYPE_DWORD
107 : unsigned int _uint;
108 :
109 : /// Used for ATTRTYPE_LONG
110 : long long _long;
111 :
112 : /// Used for ATTRTYPE_QWORD
113 : unsigned long long _ulong;
114 :
115 : /// Used for ATTRTYPE_FLOAT
116 : float _float;
117 :
118 : /// Used for ATTRTYPE_DOUBLE
119 : double _double;
120 :
121 : /// Used for ATTRTYPE_STRING, make sure it get delete'ed correctly.
122 : std::string* _string;
123 : };
124 :
125 : /// Union holding the current value of set type.
126 : union value_t val;
127 :
128 : public:
129 : /// Create a new empty AnyScalar object of given type.
130 248 : explicit inline AnyScalar(attrtype_t t = ATTRTYPE_INVALID)
131 248 : : atype(t)
132 : {
133 248 : if (atype == ATTRTYPE_STRING) {
134 7 : val._string = new std::string;
135 : }
136 : else {
137 241 : val._ulong = 0;
138 : }
139 248 : }
140 :
141 : // *** Constructors for the various types
142 :
143 : /// Construct a new AnyScalar object of type ATTRTYPE_BOOL and set the given
144 : /// boolean value.
145 36 : inline AnyScalar(bool b)
146 36 : : atype(ATTRTYPE_BOOL)
147 : {
148 36 : val._int = b;
149 36 : }
150 :
151 : #ifndef SWIG // This constructor confuses SWIG into calling it with
152 : // one-character strings
153 : /// Construct a new AnyScalar object of type ATTRTYPE_CHAR and set the given
154 : /// char value.
155 6 : inline AnyScalar(char c)
156 6 : : atype(ATTRTYPE_CHAR)
157 : {
158 6 : val._int = c;
159 6 : }
160 : #endif
161 : /// Construct a new AnyScalar object of type ATTRTYPE_SHORT and set the given
162 : /// short value.
163 3 : inline AnyScalar(short s)
164 3 : : atype(ATTRTYPE_SHORT)
165 : {
166 3 : val._int = s;
167 3 : }
168 : /// Construct a new AnyScalar object of type ATTRTYPE_INTEGER and set the
169 : /// given integer value.
170 43 : inline AnyScalar(int i)
171 43 : : atype(ATTRTYPE_INTEGER)
172 : {
173 43 : val._int = i;
174 43 : }
175 : /// Construct a new AnyScalar object of type ATTRTYPE_INTEGER and set the
176 : /// given integer value.
177 : inline AnyScalar(long i)
178 : : atype(ATTRTYPE_INTEGER)
179 : {
180 : val._int = i;
181 : }
182 : /// Construct a new AnyScalar object of type ATTRTYPE_LONG and set the
183 : /// given long value.
184 0 : inline AnyScalar(long long l)
185 0 : : atype(ATTRTYPE_LONG)
186 : {
187 0 : val._long = l;
188 0 : }
189 : /// Construct a new AnyScalar object of type ATTRTYPE_BYTE and set the given
190 : /// unsigned value.
191 : inline AnyScalar(unsigned char c)
192 : : atype(ATTRTYPE_BYTE)
193 : {
194 : val._uint = c;
195 : }
196 : /// Construct a new AnyScalar object of type ATTRTYPE_WORD and set the given
197 : /// unsigned value.
198 : inline AnyScalar(unsigned short s)
199 : : atype(ATTRTYPE_WORD)
200 : {
201 : val._uint = s;
202 : }
203 : /// Construct a new AnyScalar object of type ATTRTYPE_DWORD and set the given
204 : /// unsigned value.
205 0 : inline AnyScalar(unsigned int i)
206 0 : : atype(ATTRTYPE_DWORD)
207 : {
208 0 : val._uint = i;
209 0 : }
210 : /// Construct a new AnyScalar object of type ATTRTYPE_DWORD and set the given
211 : /// unsigned value.
212 : inline AnyScalar(unsigned long i)
213 : : atype(ATTRTYPE_DWORD)
214 : {
215 : val._uint = i;
216 : }
217 : /// Construct a new AnyScalar object of type ATTRTYPE_QWORD and set the given
218 : /// unsigned value.
219 0 : inline AnyScalar(unsigned long long l)
220 0 : : atype(ATTRTYPE_QWORD)
221 : {
222 0 : val._ulong = l;
223 0 : }
224 : /// Construct a new AnyScalar object of type ATTRTYPE_FLOAT and set the given
225 : /// floating point value.
226 0 : inline AnyScalar(float f)
227 0 : : atype(ATTRTYPE_FLOAT)
228 : {
229 0 : val._float = f;
230 0 : }
231 : /// Construct a new AnyScalar object of type ATTRTYPE_DOUBLE and set the
232 : /// given floating point value.
233 36 : inline AnyScalar(double d)
234 36 : : atype(ATTRTYPE_DOUBLE)
235 : {
236 36 : val._double = d;
237 36 : }
238 : /// Construct a new AnyScalar object of type ATTRTYPE_STRING and set the
239 : /// given string value.
240 6 : inline AnyScalar(const char *s)
241 6 : : atype(ATTRTYPE_STRING)
242 : {
243 6 : if (s == NULL)
244 0 : val._string = new std::string;
245 : else
246 6 : val._string = new std::string(s);
247 6 : }
248 : /// Construct a new AnyScalar object of type ATTRTYPE_STRING and set the
249 : /// given string value.
250 3 : inline AnyScalar(const std::string &s)
251 3 : : atype(ATTRTYPE_STRING)
252 : {
253 3 : val._string = new std::string(s);
254 3 : }
255 :
256 : /// Destroy the object: free associated string memory if necessary.
257 539 : inline ~AnyScalar()
258 : {
259 539 : if (atype == ATTRTYPE_STRING) {
260 28 : delete val._string;
261 28 : val._string = NULL;
262 : }
263 539 : }
264 :
265 : /// Copy-constructor to deal with enclosed strings. Transfers type and
266 : /// value.
267 158 : inline AnyScalar(const AnyScalar &a)
268 158 : : atype(a.atype)
269 : {
270 158 : switch(atype)
271 : {
272 : case ATTRTYPE_INVALID:
273 68 : break;
274 :
275 : case ATTRTYPE_BOOL:
276 : case ATTRTYPE_CHAR:
277 : case ATTRTYPE_SHORT:
278 : case ATTRTYPE_INTEGER:
279 70 : val._int = a.val._int;
280 70 : break;
281 :
282 : case ATTRTYPE_BYTE:
283 : case ATTRTYPE_WORD:
284 : case ATTRTYPE_DWORD:
285 0 : val._uint = a.val._uint;
286 0 : break;
287 :
288 : case ATTRTYPE_LONG:
289 0 : val._long = a.val._long;
290 0 : break;
291 :
292 : case ATTRTYPE_QWORD:
293 0 : val._ulong = a.val._ulong;
294 0 : break;
295 :
296 : case ATTRTYPE_FLOAT:
297 0 : val._float = a.val._float;
298 0 : break;
299 :
300 : case ATTRTYPE_DOUBLE:
301 15 : val._double = a.val._double;
302 15 : break;
303 :
304 : case ATTRTYPE_STRING:
305 5 : val._string = new std::string(*a.val._string);
306 : break;
307 : }
308 158 : }
309 :
310 : /// Assignment operator to deal with enclosed strings. Transfers type and
311 : /// value.
312 166 : inline AnyScalar& operator=(const AnyScalar &a)
313 : {
314 : // check if we are to assign ourself
315 166 : if (this == &a) return *this;
316 :
317 166 : if (atype == ATTRTYPE_STRING) {
318 1 : delete val._string;
319 1 : val._string = NULL;
320 : }
321 :
322 166 : atype = a.atype;
323 :
324 166 : switch(atype)
325 : {
326 : case ATTRTYPE_INVALID:
327 0 : assert(0);
328 : break;
329 :
330 : case ATTRTYPE_BOOL:
331 : case ATTRTYPE_CHAR:
332 : case ATTRTYPE_SHORT:
333 : case ATTRTYPE_INTEGER:
334 125 : val._int = a.val._int;
335 125 : break;
336 :
337 : case ATTRTYPE_BYTE:
338 : case ATTRTYPE_WORD:
339 : case ATTRTYPE_DWORD:
340 0 : val._uint = a.val._uint;
341 0 : break;
342 :
343 : case ATTRTYPE_LONG:
344 0 : val._long = a.val._long;
345 0 : break;
346 :
347 : case ATTRTYPE_QWORD:
348 0 : val._ulong = a.val._ulong;
349 0 : break;
350 :
351 : case ATTRTYPE_FLOAT:
352 0 : val._float = a.val._float;
353 0 : break;
354 :
355 : case ATTRTYPE_DOUBLE:
356 35 : val._double = a.val._double;
357 35 : break;
358 :
359 : case ATTRTYPE_STRING:
360 6 : val._string = new std::string(*a.val._string);
361 : break;
362 : }
363 :
364 166 : return *this;
365 : }
366 :
367 : /// Comparison operator. Directly compares type _and_ value. Does NOT
368 : /// attempt to convert the values into a common domain.
369 : bool operator==(const AnyScalar &a) const;
370 :
371 : /// Comparison operator: Directly compares type _and_ value. Does NOT
372 : /// attempt to convert the values into a common domain.
373 1 : inline bool operator!=(const AnyScalar &a) const
374 1 : { return !(*this == a); }
375 :
376 : /// Return the type identifier of the object.
377 82 : inline attrtype_t getType() const
378 : {
379 82 : return atype;
380 : }
381 :
382 : /// Returns true if this object contains a boolean value.
383 : inline bool isBooleanType() const
384 : {
385 : return (atype == ATTRTYPE_BOOL);
386 : }
387 :
388 : /// Returns true if this object contains one of the integer types.
389 0 : inline bool isIntegerType() const
390 : {
391 : return (atype == ATTRTYPE_BOOL ||
392 : atype == ATTRTYPE_CHAR || atype == ATTRTYPE_SHORT ||
393 : atype == ATTRTYPE_INTEGER || atype == ATTRTYPE_LONG ||
394 : atype == ATTRTYPE_BYTE || atype == ATTRTYPE_WORD ||
395 0 : atype == ATTRTYPE_DWORD || atype == ATTRTYPE_QWORD);
396 : }
397 :
398 : /// Returns true if this object contains one of the floating point types.
399 0 : inline bool isFloatingType() const
400 : {
401 0 : return (atype == ATTRTYPE_FLOAT || atype == ATTRTYPE_DOUBLE);
402 : }
403 :
404 : /// Attempts to convert the current type/value into the given type. Returns
405 : /// false if the value could not be represented in the new type, the new
406 : /// type is set nonetheless. See the getXXX below on how the new value is
407 : /// computed from the old type.
408 : bool convertType(attrtype_t t);
409 :
410 : /// Changes the current type and resets the contents without attempting to
411 : /// convert the enclosed value.
412 : void resetType(attrtype_t t);
413 :
414 : // *** attrtype_t to string and string to attrtype_t functions
415 :
416 : /// Returns true if the attrtype_t is a valid type identifier.
417 : static bool isValidAttrtype(attrtype_t at);
418 :
419 : /// Returns the attrtype identifier of a string, throws ConversionException
420 : /// if s does not specify a valid type name.
421 4 : static attrtype_t stringToType(const std::string &s)
422 : {
423 4 : return stringToType(s.c_str());
424 : }
425 :
426 : /// Returns the attrtype identifier a string, throws ConversionException if
427 : /// it does not specify a valid type name.
428 : static attrtype_t stringToType(const char *s);
429 :
430 : /// Returns a const char* for each attrtype_t.
431 : static std::string getTypeString(attrtype_t at);
432 :
433 : /// Returns a string for this AnyScalar's type.
434 8 : inline std::string getTypeString() const
435 : {
436 8 : return getTypeString(atype);
437 : }
438 :
439 : // *** Type and Value Length Functions
440 :
441 : /// Return the storage length of the type in bytes. Beware that
442 : /// getTypeLength(bool) == 0.
443 4 : inline int getTypeLength() const
444 : {
445 4 : return getTypeLength(atype);
446 : }
447 :
448 : /// Return the storage length of the type in bytes. Beware that
449 : /// getTypeLength(bool) == 0.
450 : static int getTypeLength(attrtype_t t);
451 :
452 : /// Boolean check if this type is of fixed length.
453 : static bool isFixedLength(attrtype_t t)
454 : {
455 : return getTypeLength(t) >= 0;
456 : }
457 :
458 : /// Boolean check if this type is of fixed length.
459 : inline bool isFixedLength() const
460 : {
461 : return isFixedLength(atype);
462 : }
463 :
464 : /// Return the storage length of this value (mark the different to
465 : /// getTypeLength())
466 : unsigned int getValueLength() const;
467 :
468 : // *** Setters
469 :
470 : // Sets the value, converting the input to the currently set type if
471 : // necessary. Returns false if the input could not be converted into the
472 : // right type.
473 :
474 : /** Change the value of the current object to i. Converting the integer
475 : * to this object's type if necessary.
476 : *
477 : * - boolean: the integer i is cut to 0 or 1.
478 : * - char: cut to -128..127 returns false if out of range.
479 : * - short: cut to -32768..32767 return false if out of range.
480 : * - byte: cut to 0..255 returns false if out of range.
481 : * - word: cut to 0..65536 returns false if out of range.
482 : * - int: no conversion.
483 : * - dword: cut to 0..4294967295 return false if it was negative.
484 : * - long: no cutting necessary.
485 : * - qword: cut to positive number.
486 : * - float: integer stored as floating point
487 : * - double: integer stored as floating point
488 : * - string: integer is stringified.
489 : */
490 : bool setInteger(int i);
491 :
492 : /** Change the value of the current object to l. Converting the long
493 : * long integer to this object's type if necessary. If the long long does
494 : * not fully fit into the current type, then this function returns false.
495 : *
496 : * - boolean: the long i is cut to 0 or 1.
497 : * - char: cut to -128..127 returns false if out of range.
498 : * - short: cut to -32768..32767 return false if out of range.
499 : * - int: cut to -2147483646..2147483647 returns false if out of range.
500 : * - byte: cut to 0..255 returns false if out of range.
501 : * - word: cut to 0..65536 returns false if out of range.
502 : * - dword: cut to 0..4294967295 return false if out of range.
503 : * - long: no conversion
504 : * - qword: cut to positive number.
505 : * - float: long stored as floating point
506 : * - double: long stored as floating point
507 : * - string: long is stringified.
508 : */
509 : bool setLong(long long l);
510 :
511 : /** Change the value of the current object to d. Converting the floating
512 : * point to this object's type if necessary.
513 : *
514 : * - boolean: [0:0.5] is false, (0.5:1] is true. else true and return false.
515 : * - char: truncated to integer ranged -128..127 returns false if out of range.
516 : * - short: truncated to integer ranged -32768..32767 return false if out of range.
517 : * - int: truncated to integer ranged -2147483646..2147483647 returns false if out of range.
518 : * - byte: truncated to integer ranged 0..255 returns false if out of range.
519 : * - word: truncated to integer ranged 0..65536 returns false if out of range.
520 : * - dword: truncated to integer ranged 0..4294967295 return false if out of range.
521 : * - long: truncated to integer ranged -9223372036854775806..9223372036854775807
522 : * - qword: truncated to integer ranged 0..18446744073709551615
523 : * - float: truncated to single-precision
524 : * - double: no conversion
525 : * - string: double is stringified.
526 : */
527 : bool setDouble(double d);
528 :
529 : /** Change the value of the current object to s. Converting the string
530 : * to this object's type if necessary. If this string cannot be converted
531 : * to say an integer, then this function returns false.
532 : *
533 : * - boolean: "0", "f", "false", "n" and "no" are false,
534 : * "1", "t", "true", "y" and "yes" are true. else returns false.
535 : * - char: string read using strtol and truncated to -128..127
536 : returns false if out of range or unparseable.
537 : * - short: string read using strtol and truncated to -32768..32767
538 : returns false if out of range or unparseable.
539 : * - int: string read using strtol returns false if out of range or unparseable.
540 : * - long: string read using strtoll returns false if out of range or unparseable.
541 : * - byte: string read using strtoul and truncated to 0..255
542 : returns false if out of range or unparseable.
543 : * - word: string read using strtoul and truncated to 0..65535
544 : returns false if out of range or unparseable.
545 : * - dword: string read using strtoul returns false if out of range or unparseable.
546 : * - qword: string read using strtoull returns false if out of range or unparseable.
547 : * - float: string read using strtod and converted to single-precision
548 : returns false if unparseable.
549 : * - double: string read using strtod returns false if unparseable.
550 : * - string: no conversion
551 : */
552 : bool setString(const std::string &s);
553 :
554 : /// Change the value of the current object to s. This string s must be
555 : /// quoted: "str". This function resolves escape sequences like \n.
556 : bool setStringQuoted(const std::string &s);
557 :
558 :
559 : /** Change the type _and_ value of the current object to s. The current
560 : * type is set if the given string can be converted to an integer or a
561 : * floating point number. This was required because e.g. the usual input
562 : * from files or perl are all untyped strings. The following input
563 : * conversions are tested and yield the given types:
564 : *
565 : * - boolean: no boolean strings are matched!
566 : * - int: input was readable by strtoll and is small enough.
567 : * - long: input was readable by strtoll
568 : * - double: input was readble by strtod
569 : * - string: all above failed.
570 : *
571 : * @return reference to this for chaining.
572 : */
573 : AnyScalar& setAutoString(const std::string &input);
574 :
575 : // *** Getters
576 :
577 : // Return the enclosed value in different types, converting if
578 : // necessary. If the enclosed value cannot be converted these functions
579 : // throw a ConversionError exception.
580 :
581 : /** Return the value converted to a boolean. If the enclosed value could
582 : * not be converted this function throws a ConversionException.
583 : *
584 : * - boolean: no conversion
585 : * - char/short/int/long: test integer != 0
586 : * - byte/word/dword/qword: test integer != 0
587 : * - float/double: test float != 0.0
588 : * - string: "0", "f", "false", "n", "no" are false,
589 : * "1", "t", "true", "y", "yes" are true
590 : * other strings throw ConversionException.
591 : */
592 : bool getBoolean() const;
593 :
594 : /** Return the value converted to an integer. If the enclosed value could
595 : * not be converted this function throws a ConversionException.
596 : *
597 : * - boolean: returns 0 or 1.
598 : * - char/short/int: return the integer
599 : * - byte/word/dword: return the integer (possibly as a negative number)
600 : * - long: cut to -2147483646..2147483647.
601 : * - qword: cut to 0..4294967295
602 : * - float/double: machine-conversion floating point to integer
603 : * - string: Attempt to strtol the string, throws ConversionException if this fails.
604 : */
605 : int getInteger() const;
606 :
607 : /** Return the value converted to an unsigned integer. If the enclosed
608 : * value could not be converted this function throws a ConversionException.
609 : *
610 : * - boolean: returns 0 or 1.
611 : * - char/short/int: return the integer (possibly representing a negative number as positive)
612 : * - byte/word/dword: return the unsigned integer
613 : * - long: cut to 0..4294967295 (also misrepresenting because of machine-conversion)
614 : * - qword: cut to 0..4294967295
615 : * - float/double: machine-conversion floating point to unsigned integer.
616 : * - string: Attempt to strtoul the string, throws ConversionException if this fails.
617 : */
618 : unsigned int getUnsignedInteger() const;
619 :
620 : /// Alias for getInteger()
621 : inline int getInt() const
622 : {
623 : return getInteger();
624 : }
625 :
626 : /// Alias for getUnsignedInteger()
627 : inline unsigned int getUInt() const
628 : {
629 : return getUnsignedInteger();
630 : }
631 :
632 : /** Return the value converted to a long integer. If the enclosed value
633 : * could not be converted this function throws a ConversionException.
634 : *
635 : * - boolean: returns 0 or 1.
636 : * - char/short/int: return the integer (possibly representing a negative number as positive)
637 : * - byte/word/dword: return the unsigned integer
638 : * - long: no conversion
639 : * - qword: return the integer (possibly converting a large long to a negative)
640 : * - float/double: machine-conversion floating point to long long.
641 : * - string: Attempt to strtoll the string, throws ConversionException if this fails.
642 : */
643 : long long getLong() const;
644 :
645 : /** Return the value converted to an unsigned long integer. If the enclosed
646 : * value could not be converted this function throws a ConversionException.
647 : *
648 : * - boolean: returns 0 or 1.
649 : * - char/short/int: return the integer (possibly representing a negative number as positive)
650 : * - byte/word/dword: return the unsigned integer
651 : * - long: return the long (possibly interpreting a negative long as a large positive)
652 : * - qword: no conversion
653 : * - float/double: machine-conversion floating point to unsigned long long.
654 : * - string: Attempt to strtoull the string, throws ConversionException if this fails.
655 : */
656 : unsigned long long getUnsignedLong() const;
657 :
658 : /// Alias for getUnsignedLong()
659 : unsigned long long getULong() const
660 : {
661 : return getUnsignedLong();
662 : }
663 :
664 : /** Return the value converted to a double. If the enclosed value could not
665 : * be converted this function throws a ConversionException.
666 : *
667 : * - boolean: returns 0 or 1.0.
668 : * - char/short/int/long: return the integer as a float
669 : * - byte/word/dword/qword: return the unsigned integer as a float
670 : * - float: cast to double.
671 : * - double: no conversion
672 : * - string: Attempt to strtod the string, throws ConversionException if this fails.
673 : */
674 : double getDouble() const;
675 :
676 : /** Return the value converted to a string. This function never throws
677 : * ConversionException.
678 : *
679 : * - boolean: returns "false" or "true"
680 : * - char/short/int/long: return the integer as a string using boost::lexical_cast
681 : * - byte/word/dword/qword: return the unsigned integer as a string using boost::lexical_cast
682 : * - float/double: return float as a string using boost::lexical_cast
683 : * - string: return the string.
684 : */
685 : std::string getString() const;
686 :
687 : /** Return the value converted to a quoted string. This function never
688 : * throws ConversionException. It calls getString() and adds " and escape
689 : * sequences. */
690 : std::string getStringQuoted() const;
691 :
692 : // *** Unary Operators
693 :
694 : /** Unary prefix - operator. Attempts to convert the AnyScalar to a numeric
695 : * value.
696 : *
697 : * - bool: invert the boolean value
698 : * - char/short/int/long: switch sign
699 : * - byte/word/dword/qword: negated the number even tho it doesn't make sense.
700 : * - float/double: switch sign
701 : * - string: attempt to convert the string to a double and negate it!
702 : * May throw a ConversionException
703 : */
704 : AnyScalar operator-() const;
705 :
706 : // *** Binary Operators
707 :
708 : // These will convert the two operands to the largest common type of the
709 : // same field.
710 :
711 : #ifndef SWIG // obviously too strange for SWIG
712 : private:
713 : /** Binary arithmetic template operator. Converts the two AnyScalars into the
714 : * largest type of their common field. If a string cannot be converted to a
715 : * numeric of the same field as the other operand a ConversionException is
716 : * thrown.
717 :
718 : * Conversion chart: * signifies the operator
719 :
720 : - bool * (any): ConversionException. Don't consider boolean as the field F_2.
721 : - char|short|int * char|short|int: return AnyScalar is an integer.
722 : - byte|word|dword * char|short|int: returned AnyScalar is a signed integer.
723 : - byte|word|dword * byte|word|dword: returned AnyScalar is an unsigned integer.
724 : - long * char|short|int|long|byte|word|dword|qword: returned AnyScalar is a signed long (long).
725 : - qword * char|short|int|long: : returned AnyScalar is a signed long (long).
726 : - qword * byte|word|dword|qword: : returned AnyScalar is an unsigned long (long).
727 : - float|double * char|short|int|long|byte|word|dword|qword: calculate as floating point number
728 : - string * char|short|int: convert string to integer, calculate as signed integer.
729 : - string * byte|word|dword: convert string to unsigned integer, calculate as unsigned integer.
730 : - string * long: convert string to long integer, calculate as long.
731 : - string * qword: convert string to unsigned long integer, calculate as unsigned long.
732 : - string * float|double: convert string to floating point, calculate as floating point.
733 : - string * string: only valid for "+" operator as string concatenation.
734 : */
735 : template <template <typename Type> class Operator, char OpName>
736 25 : AnyScalar binary_arith_op(const AnyScalar &b) const;
737 : #endif
738 :
739 : public:
740 : /// Instantiation of binary_arith_op for "+" plus.
741 18 : inline AnyScalar operator+(const AnyScalar &b) const
742 : {
743 18 : return binary_arith_op<std::plus, '+'>(b);
744 : }
745 :
746 : /// Instantiation of binary_arith_op for "-" minus.
747 1 : inline AnyScalar operator-(const AnyScalar &b) const
748 : {
749 1 : return binary_arith_op<std::minus, '-'>(b);
750 : }
751 :
752 : /// Instantiation of binary_arith_op for "*" multiplication.
753 5 : inline AnyScalar operator*(const AnyScalar &b) const
754 : {
755 5 : return binary_arith_op<std::multiplies, '*'>(b);
756 : }
757 :
758 : /// Instantiation of binary_arith_op for "/" division.
759 1 : inline AnyScalar operator/(const AnyScalar &b) const
760 : {
761 1 : return binary_arith_op<std::divides, '/'>(b);
762 : }
763 :
764 : /// Alias for operator+ in script languages
765 : inline AnyScalar add(const AnyScalar &b) const
766 : {
767 : return (*this + b);
768 : }
769 :
770 : /// Alias for operator- in script languages
771 : inline AnyScalar subtract(const AnyScalar &b) const
772 : {
773 : return (*this - b);
774 : }
775 :
776 : /// Alias for operator* in script languages
777 : inline AnyScalar multiply(const AnyScalar &b) const
778 : {
779 : return (*this * b);
780 : }
781 :
782 : /// Alias for operator/ in script languages
783 : inline AnyScalar divide(const AnyScalar &b) const
784 : {
785 : return (*this / b);
786 : }
787 :
788 : #ifndef SWIG // obviously too strange for SWIG
789 : private:
790 : /** Binary comparison template operator. Converts the two AnyScalars into the
791 : * largest type of their common field. If a string cannot be converted to a
792 : * numeric of the same field as the other operand a ConversionException is
793 : * thrown. Operator is the STL operator class. OpNum is an identifier for
794 : * the operator name string within the template.
795 :
796 : * Conversion chart: * signifies the operator
797 :
798 : - bool * bool: usual comparison
799 : - bool * (any): ConversionException. Don't consider boolean as the field F_2.
800 :
801 : - char|short|int * char|short|int: compare as signed integers.
802 : - byte|word|dword * char|short|int: compare as signed integers.
803 : - byte|word|dword * byte|word|dword: compare as unsigned integers.
804 : - long * char|short|int|long|byte|word|dword|qword: compare as signed long integer
805 : - qword * char|short|int|long: : compare as signed long integer
806 : - qword * byte|word|dword|qword: : compare an unsigned long (long).
807 : - float|double * char|short|int|long|byte|word|dword|qword: compare as floating point numbers
808 : - string * char|short|int: convert string to integer, compare as signed integer.
809 : - string * byte|word|dword: convert string to unsigned integer, compare as unsigned integer.
810 : - string * long: convert string to long integer, compare as long.
811 : - string * qword: convert string to unsigned long integer, compare as unsigned long.
812 : - string * float|double: convert string to floating point, compare as floating point.
813 : - string * string: usual string comparison operators.
814 : */
815 : template <template <typename Type> class Operator, int OpNum>
816 15 : bool binary_comp_op(const AnyScalar &b) const;
817 : #endif
818 :
819 : // *** Don't use the operators themselves, because operator== is defined
820 : // *** differently above.
821 : public:
822 : /// Instantiation of binary_comp_op for "==" equality.
823 5 : inline bool equal_to(const AnyScalar &b) const
824 : {
825 5 : return binary_comp_op<std::equal_to, 0>(b);
826 : }
827 :
828 : /// Instantiation of binary_comp_op for "!=" inequality.
829 1 : inline bool not_equal_to(const AnyScalar &b) const
830 : {
831 1 : return binary_comp_op<std::not_equal_to, 1>(b);
832 : }
833 :
834 : /// Instantiation of binary_comp_op for "<" less-than.
835 1 : inline bool less(const AnyScalar &b) const
836 : {
837 1 : return binary_comp_op<std::less, 2>(b);
838 : }
839 :
840 : /// Instantiation of binary_comp_op for ">" greater-than.
841 2 : inline bool greater(const AnyScalar &b) const
842 : {
843 2 : return binary_comp_op<std::greater, 3>(b);
844 : }
845 :
846 : /// Instantiation of binary_comp_op for "<=" less-or-equal-than.
847 3 : inline bool less_equal(const AnyScalar &b) const
848 : {
849 3 : return binary_comp_op<std::less_equal, 4>(b);
850 : }
851 :
852 : /// Instantiation of binary_comp_op for ">=" greater-or-equal-than.
853 3 : inline bool greater_equal(const AnyScalar &b) const
854 : {
855 3 : return binary_comp_op<std::greater_equal, 5>(b);
856 : }
857 : };
858 :
859 : /// Make AnyScalar outputtable to ostream
860 : static inline std::ostream& operator<< (std::ostream &stream, const AnyScalar &as)
861 : {
862 : return stream << as.getString();
863 : }
864 :
865 : } // namespace stx
866 :
867 : #endif // VGS_AnyScalar_H
|