Qore Programming Language  0.9.16
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 hashdecl QoreValue;
54 
56 union qore_value_u {
57  bool b;
58  int64 i;
59  double f;
61 };
62 
64 namespace detail {
66  template<typename Type>
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  hashdecl 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  hashdecl 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<>
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 {
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 hashdecl QoreValue : public QoreSimpleValue {
263  friend class ValueHolder;
264  friend class ValueOptionalRefHolder;
265  template<typename> friend hashdecl 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 
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 
423 protected:
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:
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 
486 private:
487  // not implemented
488  DLLLOCAL QoreValue& operator=(QoreValue& nv);
489 
490 protected:
493 
494 public:
496  DLLLOCAL ValueOptionalRefHolder(QoreValue n_v, bool nd, ExceptionSink* xs) : ValueHolderBase(n_v, xs), needs_deref(nd) {
497  }
498 
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 
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
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
QoreValue::getFullTypeInfo
const DLLEXPORT QoreTypeInfo * getFullTypeInfo() const
returns the exact type of the value; i.e. the class type for classes, hashdecl type for hashdecls
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
QoreValue::getTypeInfo
const DLLEXPORT QoreTypeInfo * getTypeInfo() const
returns the type of the value
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
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
QoreValue::getFullTypeName
const DLLEXPORT char * getFullTypeName() const
returns a string type description of the full type of the value contained (ex: "nothing" for a null A...
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
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