| Qore Programming Language - C/C++ Library 0.9.10

QoreValue.h
1 /* -*- mode: c++; indent-tabs-mode: nil -*- */
2 /*
3 QoreValue.h
4
5 Qore Programming Language
6
7 Copyright (C) 2003 - 2020 Qore Technologies, s.r.o.
8
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the "Software"),
11 to deal in the Software without restriction, including without limitation
12 the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 and/or sell copies of the Software, and to permit persons to whom the
14 Software is furnished to do so, subject to the following conditions:
15
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 DEALINGS IN THE SOFTWARE.
26
27 Note that the Qore library is released under a choice of three open-source
28 licenses: MIT (as above), LGPL 2+, or GPL 2+; see README-LICENSE for more
29 information.
30 */
31
32 #ifndef _QORE_QOREVALUE_H
33 #define _QORE_QOREVALUE_H
34
35 #include <cassert>
36
37 typedef unsigned char valtype_t;
38
40
43 #define QV_Bool (valtype_t)0
44 #define QV_Int (valtype_t)1
45 #define QV_Float (valtype_t)2
46 #define QV_Node (valtype_t)3
47 #define QV_Ref (valtype_t)4
48
49
50 // forward references
51 class AbstractQoreNode;
52 class QoreString;
53 struct QoreValue;
54
56 union qore_value_u {
57 bool b;
58 int64 i;
59 double f;
60 AbstractQoreNode* n;
61 };
62
64 namespace detail {
66 template<typename Type>
67 struct QoreValueCastHelper {
68 typedef Type * Result;
69
70 template<typename QV>
71 static Result cast(QV *qv, valtype_t type) {
72 assert(type == QV_Node);
73 assert(!qv->v.n || dynamic_cast<Result>(qv->v.n));
74 return reinterpret_cast<Result>(qv->v.n);
75 }
76 };
77
79 template<>
80 struct QoreValueCastHelper<bool> {
81 typedef bool Result;
82
83 template<typename QV>
84 static bool cast(QV *qv, valtype_t type) {
85 return qv->getAsBool();
86 }
87 };
88
90 template<>
91 struct QoreValueCastHelper<double> {
92 typedef double Result;
93
94 template<typename QV>
95 static double cast(QV *qv, valtype_t type) {
96 return qv->getAsFloat();
97 }
98 };
99
101 template<>
102 struct QoreValueCastHelper<int64> {
103 typedef int64 Result;
104
105 template<typename QV>
106 static int64 cast(QV *qv, valtype_t type) {
107 return qv->getAsBigInt();
108 }
109 };
110 } // namespace detail
111
112 class QoreSimpleValue {
113 public:
115 qore_value_u v;
117 valtype_t type;
118
120 DLLLOCAL void set(int64 i) {
121 type = QV_Int;
122 v.i = i;
123 }
124
126 DLLLOCAL void set(double f) {
127 type = QV_Float;
128 v.f = f;
129 }
130
132 DLLLOCAL void set(bool b) {
133 type = QV_Bool;
134 v.b = b;
135 }
136
138 DLLEXPORT void set(QoreSimpleValue val);
139
141 DLLEXPORT void set(AbstractQoreNode* n);
142
144 DLLLOCAL QoreSimpleValue& assign(QoreSimpleValue& val) {
145 set(val);
146 return *this;
147 }
148
150 DLLLOCAL QoreSimpleValue& assign(int64 i) {
151 set(i);
152 return *this;
153 }
154
156 DLLLOCAL QoreSimpleValue& assign(double f) {
157 set(f);
158 return *this;
159 }
160
162 DLLLOCAL QoreSimpleValue& assign(bool b) {
163 set(b);
164 return *this;
165 }
166
168 DLLLOCAL QoreSimpleValue& assign(AbstractQoreNode* n) {
169 set(n);
170 return *this;
171 }
172
174 DLLEXPORT qore_type_t getType() const;
175
177 DLLEXPORT const char* getTypeName() const;
178
180
182 DLLEXPORT AbstractQoreNode* takeNode();
183
185 DLLEXPORT AbstractQoreNode* getInternalNode();
186
188 DLLEXPORT const AbstractQoreNode* getInternalNode() const;
189
191 DLLEXPORT void clear();
192
194 DLLEXPORT void discard(ExceptionSink* xsink);
195
197
199 template<typename T>
200 DLLLOCAL T* take() {
201 assert(type == QV_Node);
202 assert(dynamic_cast<T*>(v.n));
203 T* rv = reinterpret_cast<T*>(v.n);
204 v.n = 0;
205 return rv;
206 }
207
209
212 template<typename T>
213 DLLLOCAL typename detail::QoreValueCastHelper<T>::Result get() {
214 return detail::QoreValueCastHelper<T>::cast(this, type);
215 }
216
218
221 template<typename T>
222 DLLLOCAL typename detail::QoreValueCastHelper<const T>::Result get() const {
223 return detail::QoreValueCastHelper<const T>::cast(this, type);
224 }
225
227 DLLEXPORT bool getAsBool() const;
228
230 DLLEXPORT int64 getAsBigInt() const;
231
233 DLLEXPORT double getAsFloat() const;
234
236 DLLEXPORT bool hasEffect() const;
237
239 DLLEXPORT bool isNothing() const;
240
242 DLLEXPORT bool isNull() const;
243
245 DLLEXPORT bool isNullOrNothing() const;
246
248 DLLEXPORT bool isValue() const;
249
251 DLLEXPORT bool needsEval() const;
252
254 DLLEXPORT operator bool() const;
255
256 protected:
258 DLLEXPORT AbstractQoreNode* takeNodeIntern();
259 };
260
262 struct QoreValue : public QoreSimpleValue {
263 friend class ValueHolder;
264 friend class ValueOptionalRefHolder;
265 template<typename> friend struct detail::QoreValueCastHelper;
266
267 public:
269 DLLEXPORT QoreValue();
270
272 DLLEXPORT QoreValue(bool b);
273
275 DLLEXPORT QoreValue(int i);
276
278 DLLEXPORT QoreValue(unsigned int i);
279
281 DLLEXPORT QoreValue(long i);
282
284 DLLEXPORT QoreValue(unsigned long i);
285
287 DLLEXPORT QoreValue(unsigned long long i);
288
290 DLLEXPORT QoreValue(int64 i);
291
293 DLLEXPORT QoreValue(double f);
294
296 DLLEXPORT QoreValue(AbstractQoreNode* n);
297
299
305 DLLEXPORT QoreValue(const AbstractQoreNode* n);
306
308 DLLEXPORT QoreValue(const QoreSimpleValue& v);
309
311 DLLEXPORT QoreValue(const QoreValue& old);
312
314 DLLEXPORT void swap(QoreValue& val);
315
317 DLLEXPORT void ref() const;
318
320 DLLEXPORT QoreValue refSelf() const;
321
323
326 DLLEXPORT AbstractQoreNode* assign(AbstractQoreNode* n);
327
329
332 DLLEXPORT AbstractQoreNode* assignAndSanitize(const QoreValue n);
333
335
338 DLLEXPORT AbstractQoreNode* assign(int64 n);
339
341
344 DLLEXPORT AbstractQoreNode* assign(double n);
345
347
350 DLLEXPORT AbstractQoreNode* assign(bool n);
351
353
357 DLLEXPORT AbstractQoreNode* assignNothing();
358
360 DLLEXPORT bool isEqualSoft(const QoreValue v, ExceptionSink* xsink) const;
361
363 DLLEXPORT bool isEqualHard(const QoreValue v) const;
364
366 DLLEXPORT bool isEqualValue(const QoreValue v);
367
369 DLLEXPORT void sanitize();
370
372 DLLEXPORT QoreValue& operator=(const QoreValue& n);
373
375 DLLEXPORT QoreValue& operator=(const QoreSimpleValue& n);
376
378 DLLEXPORT void discard(ExceptionSink* xsink);
379
381 DLLEXPORT int getAsString(QoreString& str, int format_offset, ExceptionSink *xsink) const;
382
384 DLLEXPORT QoreString* getAsString(bool& del, int foff, ExceptionSink* xsink) const;
385
387 DLLEXPORT QoreValue eval(ExceptionSink* xsink) const;
388
390 DLLEXPORT QoreValue eval(bool& needs_deref, ExceptionSink* xsink) const;
391
393 //DLLEXPORT QoreValue refSelf() const;
394
396 DLLEXPORT AbstractQoreNode* takeIfNode();
397
399
401 DLLEXPORT const QoreTypeInfo* getTypeInfo() const;
402
404
406 DLLEXPORT const QoreTypeInfo* getFullTypeInfo() const;
407
409 DLLEXPORT const char* getFullTypeName() const;
410
412 DLLEXPORT bool hasNode() const;
413
415 DLLEXPORT bool isReferenceCounted() const;
416
418 DLLEXPORT bool derefCanThrowException() const;
419 };
420
422 class ValueHolderBase {
423 protected:
425 QoreValue v;
427 ExceptionSink* xsink;
428
429 public:
431 DLLLOCAL ValueHolderBase(ExceptionSink* xs) : xsink(xs) {
432 }
433
435 DLLLOCAL ValueHolderBase(QoreValue n_v, ExceptionSink* xs) : v(n_v), xsink(xs) {
436 }
437
439 DLLLOCAL QoreValue* operator->() { return &v; }
440
442 DLLLOCAL const QoreValue* operator->() const { return &v; }
443
445 DLLLOCAL QoreValue& operator*() { return v; }
446
448 DLLLOCAL const QoreValue& operator*() const { return v; }
449 };
450
452 class ValueHolder : public ValueHolderBase {
453 public:
455 DLLLOCAL ValueHolder(ExceptionSink* xs) : ValueHolderBase(xs) {
456 }
457
459 DLLLOCAL ValueHolder(QoreValue n_v, ExceptionSink* xs) : ValueHolderBase(n_v, xs) {
460 }
461
463 DLLEXPORT ~ValueHolder();
464
466 DLLEXPORT QoreValue getReferencedValue();
467
469 DLLEXPORT QoreValue release();
470
472 DLLLOCAL QoreValue& operator=(QoreValue nv) {
473 v.discard(xsink);
474 v = nv;
475 return v;
476 }
477
479 DLLLOCAL operator bool() const {
480 return (bool)v;
481 }
482 };
483
485 class ValueOptionalRefHolder : public ValueHolderBase {
486 private:
487 // not implemented
488 DLLLOCAL QoreValue& operator=(QoreValue& nv);
489
490 protected:
492 bool needs_deref;
493
494 public:
496 DLLLOCAL ValueOptionalRefHolder(QoreValue n_v, bool nd, ExceptionSink* xs) : ValueHolderBase(n_v, xs), needs_deref(nd) {
497 }
498
500 DLLLOCAL ValueOptionalRefHolder(ExceptionSink* xs) : ValueHolderBase(xs), needs_deref(false) {
501 }
502
503 DLLEXPORT ~ValueOptionalRefHolder();
504
506 DLLLOCAL bool isTemp() const { return needs_deref; }
507
509 DLLLOCAL void clearTemp() {
510 if (needs_deref)
511 needs_deref = false;
512 }
513
515 DLLLOCAL operator bool() const {
516 return (bool)v;
517 }
518
520 DLLLOCAL void setValue(QoreValue nv) {
521 if (needs_deref) {
522 v.discard(xsink);
523 needs_deref = false;
524 }
525 v = nv;
526 }
527
529 DLLLOCAL void setValue(QoreValue nv, bool temp) {
530 if (needs_deref)
531 v.discard(xsink);
532 if (needs_deref != temp)
533 needs_deref = temp;
534 v = nv;
535 }
536
537 // ensures that the held value is referenced
540 DLLEXPORT void ensureReferencedValue();
541
543 template<typename T>
544 DLLLOCAL T* takeReferencedNode() {
545 T* rv = v.take<T>();
546 if (needs_deref)
547 needs_deref = false;
548 else
549 rv->ref();
550
551 return rv;
552 }
553
555 DLLEXPORT QoreValue getReferencedValue();
556
558 DLLLOCAL AbstractQoreNode* takeNode(bool& nd) {
559 if (v.type == QV_Node) {
560 nd = needs_deref;
561 return v.takeNodeIntern();
562 }
563 nd = true;
564 return v.takeNode();
565 }
566
568 DLLLOCAL QoreValue takeValue(bool& nd) {
569 if (v.type == QV_Node) {
570 nd = needs_deref;
571 return v.takeNodeIntern();
572 }
573 nd = false;
574 return v;
575 }
576
578 DLLLOCAL void takeValueFrom(ValueOptionalRefHolder& val) {
579 if (needs_deref)
580 v.discard(xsink);
581 v = val.takeValue(needs_deref);
582 }
583
585 DLLEXPORT QoreValue takeReferencedValue();
586
587 // FIXME: remove with new API/ABI
589 DLLLOCAL void sanitize();
590 };
591
593 class ValueEvalRefHolder : public ValueOptionalRefHolder {
594 public:
596 DLLEXPORT ValueEvalRefHolder(const AbstractQoreNode* exp, ExceptionSink* xs);
597
599
601 DLLEXPORT ValueEvalRefHolder(const QoreValue exp, ExceptionSink* xs);
602
604
606 DLLEXPORT ValueEvalRefHolder(ExceptionSink* xs);
607
609
611 DLLEXPORT int eval(const AbstractQoreNode* exp);
612
614
616 DLLEXPORT int eval(const QoreValue exp);
617
618 protected:
620
622 DLLLOCAL int evalIntern(const AbstractQoreNode* exp);
623
625
627 DLLLOCAL int evalIntern(const QoreValue exp);
628 };
629
631 DLLEXPORT extern const char* qoreBoolTypeName;
633 DLLEXPORT extern const char* qoreIntTypeName;
635 DLLEXPORT extern const char* qoreFloatTypeName;
636
637 #endif
QoreValue::getFullTypeInfo
DLLEXPORT const QoreTypeInfo * getFullTypeInfo() const
returns the exact type of the value; i.e. the class type for classes, hashdecl type for hashdecls
ValueEvalRefHolder
evaluates an AbstractQoreNode and dereferences the stored value in the destructor
Definition: QoreValue.h:593
ValueOptionalRefHolder::takeReferencedNode
DLLLOCAL T * takeReferencedNode()
returns the stored node value and leaves the current object empty
Definition: QoreValue.h:544
qore_value_u::f
double f
for double values
Definition: QoreValue.h:59
detail::QoreValueCastHelper
used in QoreValue::get()
Definition: QoreValue.h:67
ValueOptionalRefHolder::takeReferencedValue
DLLEXPORT QoreValue takeReferencedValue()
returns a QoreValue after incrementing the reference count of any node value stored if necessary
ValueOptionalRefHolder::takeNode
DLLLOCAL AbstractQoreNode * takeNode(bool &nd)
returns the stored AbstractQoreNode pointer and sets the dereference flag as an output variable
Definition: QoreValue.h:558
ValueOptionalRefHolder::ensureReferencedValue
DLLEXPORT void ensureReferencedValue()
QoreValue::assignNothing
DLLEXPORT AbstractQoreNode * assignNothing()
sets the value of the object to QoreNothingNode and returns any node value held previously
QoreValue
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:262
ValueHolder::getReferencedValue
DLLEXPORT QoreValue getReferencedValue()
returns a referenced value; caller owns the reference; the current object is left undisturbed
ValueOptionalRefHolder::needs_deref
bool needs_deref
flag indicating if the value should be dereferenced in the destructor or not
Definition: QoreValue.h:492
ValueHolder::~ValueHolder
DLLEXPORT ~ValueHolder()
dereferences any contained node
detail
namespace for implementation details of QoreValue functions
Definition: QoreValue.h:64
ValueEvalRefHolder::ValueEvalRefHolder
DLLEXPORT ValueEvalRefHolder(const AbstractQoreNode *exp, ExceptionSink *xs)
evaluates the exp argument
QoreValue::swap
DLLEXPORT void swap(QoreValue &val)
exchanges the values
ValueEvalRefHolder::eval
DLLEXPORT int eval(const AbstractQoreNode *exp)
evaluates the argument, returns -1 for error, 0 = OK
QoreValue::assign
DLLEXPORT AbstractQoreNode * assign(AbstractQoreNode *n)
the QoreValue object takes the reference of the argument
QoreValue::eval
DLLEXPORT QoreValue eval(ExceptionSink *xsink) const
evaluates the node and returns the result
int64
long long int64
64bit integer type, cannot use int64_t here since it breaks the API on some 64-bit systems due to equ...
Definition: common.h:260
QoreValue::assignAndSanitize
DLLEXPORT AbstractQoreNode * assignAndSanitize(const QoreValue n)
sets the value of the object and returns any node value held previously
QoreValue::isEqualSoft
DLLEXPORT bool isEqualSoft(const QoreValue v, ExceptionSink *xsink) const
returns trus if the argument value is equal to the current value with type conversions
ValueHolderBase::xsink
ExceptionSink * xsink
for possible Qore-language exceptions
Definition: QoreValue.h:427
ValueHolder::ValueHolder
DLLLOCAL ValueHolder(ExceptionSink *xs)
creates an empty object
Definition: QoreValue.h:455
QoreValue::hasNode
DLLEXPORT bool hasNode() const
returns true if the object contains a non-null AbstractQoreNode pointer (ie type == QV_Node && v....
QoreString
Qore's string type supported by the QoreEncoding class.
Definition: QoreString.h:81
QoreValue::refSelf
DLLEXPORT QoreValue refSelf() const
references the contained value if type == QV_Node, returns itself
qore_value_u::i
int64 i
for integer values
Definition: QoreValue.h:58
QoreValue::isReferenceCounted
DLLEXPORT bool isReferenceCounted() const
returns true if the value holds a referenced-counted node
ValueHolder::operator=
DLLLOCAL QoreValue & operator=(QoreValue nv)
assigns the object, any currently-held value is dereferenced before the assignment
Definition: QoreValue.h:472
qore_value_u::b
bool b
for boolean values
Definition: QoreValue.h:57
QoreValue::discard
DLLEXPORT void discard(ExceptionSink *xsink)
dereferences any contained AbstractQoreNode pointer and sets to 0; does not modify other values
QoreValue::getAsString
DLLEXPORT int getAsString(QoreString &str, int format_offset, ExceptionSink *xsink) const
appends the string value of the contained node to the string argument with optional formatting
qore_value_u::n
AbstractQoreNode * n
for all heap-allocated values
Definition: QoreValue.h:60
QoreValue::derefCanThrowException
DLLEXPORT bool derefCanThrowException() const
returns true if a dereference could theoretically throw an exception (an object is reachable from thi...
ValueEvalRefHolder::evalIntern
DLLLOCAL int evalIntern(const AbstractQoreNode *exp)
evaluates the argument, returns -1 for error, 0 = OK
QoreValue::takeIfNode
DLLEXPORT AbstractQoreNode * takeIfNode()
returns a referenced value; leaving the "this" untouched; the caller owns the reference returned
ExceptionSink
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:48
QoreValue::sanitize
DLLEXPORT void sanitize()
converts any node pointers to efficient representations if possible and dereferences the node value c...
qore_value_u
this is the union that stores values in QoreValue
Definition: QoreValue.h:56
ValueOptionalRefHolder::ValueOptionalRefHolder
DLLLOCAL ValueOptionalRefHolder(QoreValue n_v, bool nd, ExceptionSink *xs)
creates the object with the given values
Definition: QoreValue.h:496
ValueOptionalRefHolder::sanitize
DLLLOCAL void sanitize()
converts pointers to efficient representations and manages the reference count
QoreValue::isEqualValue
DLLEXPORT bool isEqualValue(const QoreValue v)
returns true of the argument is exactly the same value as the current value, meaning also that if bot...
ValueHolder::release
DLLEXPORT QoreValue release()
returns a QoreValue object and leaves the current object empty; the caller owns any reference contain...
ValueOptionalRefHolder::clearTemp
DLLLOCAL void clearTemp()
sets needs_deref = false
Definition: QoreValue.h:509
QoreValue::QoreValue
DLLEXPORT QoreValue()
creates with no value (i.e. QoreNothingNode)
ValueOptionalRefHolder
allows storing a value and setting a boolean flag that indicates if the value should be dereference i...
Definition: QoreValue.h:485
QoreValue::getTypeInfo
DLLEXPORT const QoreTypeInfo * getTypeInfo() const
returns the type of the value
ValueOptionalRefHolder::getReferencedValue
DLLEXPORT QoreValue getReferencedValue()
returns a referenced value; caller owns the reference; the current object is not disturbed
ValueHolderBase::v
QoreValue v
the value held
Definition: QoreValue.h:425
ValueHolderBase::ValueHolderBase
DLLLOCAL ValueHolderBase(ExceptionSink *xs)
creates an ampty object
Definition: QoreValue.h:431
ValueOptionalRefHolder::takeValue
DLLLOCAL QoreValue takeValue(bool &nd)
returns the stored value and sets the dereference flag as an output variable
Definition: QoreValue.h:568
ValueOptionalRefHolder::takeValueFrom
DLLLOCAL void takeValueFrom(ValueOptionalRefHolder &val)
returns the stored value which must be dereferenced if it is a node object (i.e. type == QV_Node)
Definition: QoreValue.h:578
ValueHolder
holds an object and dereferences it in the destructor
Definition: QoreValue.h:452
QoreValue::isEqualHard
DLLEXPORT bool isEqualHard(const QoreValue v) const
returns trus if the argument value is equal to the current value without any type conversions
ValueHolderBase
base class for holding a QoreValue object
Definition: QoreValue.h:422
ValueOptionalRefHolder::isTemp
DLLLOCAL bool isTemp() const
returns true if the value is temporary (needs dereferencing)
Definition: QoreValue.h:506
ValueOptionalRefHolder::setValue
DLLLOCAL void setValue(QoreValue nv)
assigns a new non-temporary value
Definition: QoreValue.h:520
QoreValue::ref
DLLEXPORT void ref() const
references the contained value if type == QV_Node
AbstractQoreNode
The base class for all value and parse types in Qore expression trees.
Definition: AbstractQoreNode.h:54
qore_type_t
int16_t qore_type_t
used to identify unique Qore data and parse types (descendents of AbstractQoreNode)
Definition: common.h:70
ValueHolderBase::operator*
DLLLOCAL QoreValue & operator*()
returns the value being managed
Definition: QoreValue.h:445
discard
static void discard(AbstractQoreNode *n, ExceptionSink *xsink)
to deref an AbstractQoreNode (when the pointer may be 0)
Definition: QoreLib.h:324
QoreValue::getFullTypeName
DLLEXPORT const char * getFullTypeName() const
returns a string type description of the full type of the value contained (ex: "nothing" for a null A...
ValueHolderBase::operator->
DLLLOCAL QoreValue * operator->()
returns the value being managed
Definition: QoreValue.h:439
QoreValue::operator=
DLLEXPORT QoreValue & operator=(const QoreValue &n)
assigns a new value