Qore Programming Language - C/C++ Library  1.0.8
QoreValue.h
1 /* -*- mode: c++; indent-tabs-mode: nil -*- */
2 /*
3  QoreValue.h
4 
5  Qore Programming Language
6 
7  Copyright (C) 2003 - 2021 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;
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  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<>
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 
256  DLLEXPORT bool isScalar() const;
257 
259  DLLEXPORT operator bool() const;
260 
261 protected:
263  DLLEXPORT AbstractQoreNode* takeNodeIntern();
264 };
265 
267 struct QoreValue : public QoreSimpleValue {
268  friend class ValueHolder;
269  friend class ValueOptionalRefHolder;
270  template<typename> friend struct detail::QoreValueCastHelper;
271 
272 public:
274  DLLEXPORT QoreValue();
275 
277  DLLEXPORT QoreValue(bool b);
278 
280  DLLEXPORT QoreValue(int i);
281 
283  DLLEXPORT QoreValue(unsigned int i);
284 
286  DLLEXPORT QoreValue(long i);
287 
289  DLLEXPORT QoreValue(unsigned long i);
290 
292  DLLEXPORT QoreValue(unsigned long long i);
293 
295  DLLEXPORT QoreValue(int64 i);
296 
298  DLLEXPORT QoreValue(double f);
299 
301  DLLEXPORT QoreValue(AbstractQoreNode* n);
302 
304 
310  DLLEXPORT QoreValue(const AbstractQoreNode* n);
311 
313  DLLEXPORT QoreValue(const QoreSimpleValue& v);
314 
316  DLLEXPORT QoreValue(const QoreValue& old);
317 
319  DLLEXPORT void swap(QoreValue& val);
320 
322  DLLEXPORT void ref() const;
323 
325  DLLEXPORT QoreValue refSelf() const;
326 
328 
331  DLLEXPORT AbstractQoreNode* assign(const QoreValue n);
332 
334 
338 
340 
343  DLLEXPORT AbstractQoreNode* assign(int64 n);
344 
346 
349  DLLEXPORT AbstractQoreNode* assign(double n);
350 
352 
355  DLLEXPORT AbstractQoreNode* assign(bool n);
356 
358 
362  DLLEXPORT AbstractQoreNode* assignNothing();
363 
365  DLLEXPORT bool isEqualSoft(const QoreValue v, ExceptionSink* xsink) const;
366 
368  DLLEXPORT bool isEqualHard(const QoreValue v) const;
369 
371  DLLEXPORT bool isEqualValue(const QoreValue v);
372 
374  DLLEXPORT void sanitize();
375 
377  DLLEXPORT QoreValue& operator=(const QoreValue& n);
378 
380  DLLEXPORT QoreValue& operator=(const QoreSimpleValue& n);
381 
383  DLLEXPORT void discard(ExceptionSink* xsink);
384 
386  DLLEXPORT int getAsString(QoreString& str, int format_offset, ExceptionSink *xsink) const;
387 
389  DLLEXPORT QoreString* getAsString(bool& del, int foff, ExceptionSink* xsink) const;
390 
392  DLLEXPORT QoreValue eval(ExceptionSink* xsink) const;
393 
395  DLLEXPORT QoreValue eval(bool& needs_deref, ExceptionSink* xsink) const;
396 
398  //DLLEXPORT QoreValue refSelf() const;
399 
401  DLLEXPORT AbstractQoreNode* takeIfNode();
402 
404 
406  DLLEXPORT const QoreTypeInfo* getTypeInfo() const;
407 
409 
411  DLLEXPORT const QoreTypeInfo* getFullTypeInfo() const;
412 
414 
416  DLLEXPORT const char* getFullTypeName() const;
417 
419 
425  DLLEXPORT const char* getFullTypeName(bool with_namespaces) const;
426 
428  DLLEXPORT bool hasNode() const;
429 
431  DLLEXPORT bool isReferenceCounted() const;
432 
434  DLLEXPORT bool derefCanThrowException() const;
435 };
436 
439 protected:
444 
445 public:
447  DLLLOCAL ValueHolderBase(ExceptionSink* xs) : xsink(xs) {
448  }
449 
451  DLLLOCAL ValueHolderBase(QoreValue n_v, ExceptionSink* xs) : v(n_v), xsink(xs) {
452  }
453 
455  DLLLOCAL QoreValue* operator->() { return &v; }
456 
458  DLLLOCAL const QoreValue* operator->() const { return &v; }
459 
461  DLLLOCAL QoreValue& operator*() { return v; }
462 
464  DLLLOCAL const QoreValue& operator*() const { return v; }
465 };
466 
468 class ValueHolder : public ValueHolderBase {
469 public:
472  }
473 
475  DLLLOCAL ValueHolder(QoreValue n_v, ExceptionSink* xs) : ValueHolderBase(n_v, xs) {
476  }
477 
479  DLLEXPORT ~ValueHolder();
480 
482  DLLEXPORT QoreValue getReferencedValue();
483 
485  DLLEXPORT QoreValue release();
486 
488  DLLLOCAL QoreValue& operator=(QoreValue nv) {
489  v.discard(xsink);
490  v = nv;
491  return v;
492  }
493 
495  DLLLOCAL operator bool() const {
496  return (bool)v;
497  }
498 };
499 
502 private:
503  // not implemented
504  DLLLOCAL QoreValue& operator=(QoreValue& nv);
505 
506 protected:
509 
510 public:
512  DLLLOCAL ValueOptionalRefHolder(QoreValue n_v, bool nd, ExceptionSink* xs) : ValueHolderBase(n_v, xs), needs_deref(nd) {
513  }
514 
517  }
518 
519  DLLEXPORT ~ValueOptionalRefHolder();
520 
522  DLLLOCAL bool isTemp() const { return needs_deref; }
523 
525  DLLLOCAL void clearTemp() {
526  if (needs_deref)
527  needs_deref = false;
528  }
529 
531  DLLLOCAL operator bool() const {
532  return (bool)v;
533  }
534 
536  DLLLOCAL void setValue(QoreValue nv) {
537  if (needs_deref) {
538  v.discard(xsink);
539  needs_deref = false;
540  }
541  v = nv;
542  }
543 
545  DLLLOCAL void setValue(QoreValue nv, bool temp) {
546  if (needs_deref)
547  v.discard(xsink);
548  if (needs_deref != temp)
549  needs_deref = temp;
550  v = nv;
551  }
552 
553  // ensures that the held value is referenced
556  DLLEXPORT void ensureReferencedValue();
557 
559  template<typename T>
560  DLLLOCAL T* takeReferencedNode() {
561  T* rv = v.take<T>();
562  if (needs_deref)
563  needs_deref = false;
564  else
565  rv->ref();
566 
567  return rv;
568  }
569 
571  DLLEXPORT QoreValue getReferencedValue();
572 
574  DLLLOCAL AbstractQoreNode* takeNode(bool& nd) {
575  if (v.type == QV_Node) {
576  nd = needs_deref;
577  return v.takeNodeIntern();
578  }
579  nd = true;
580  return v.takeNode();
581  }
582 
584  DLLLOCAL QoreValue takeValue(bool& nd) {
585  if (v.type == QV_Node) {
586  nd = needs_deref;
587  return v.takeNodeIntern();
588  }
589  nd = false;
590  return v;
591  }
592 
594  DLLLOCAL void takeValueFrom(ValueOptionalRefHolder& val) {
595  if (needs_deref)
596  v.discard(xsink);
597  v = val.takeValue(needs_deref);
598  }
599 
601  DLLEXPORT QoreValue takeReferencedValue();
602 };
603 
606 public:
608  DLLEXPORT ValueEvalRefHolder(const AbstractQoreNode* exp, ExceptionSink* xs);
609 
611 
613  DLLEXPORT ValueEvalRefHolder(const QoreValue exp, ExceptionSink* xs);
614 
616 
618  DLLEXPORT ValueEvalRefHolder(ExceptionSink* xs);
619 
621 
623  DLLEXPORT int eval(const AbstractQoreNode* exp);
624 
626 
628  DLLEXPORT int eval(const QoreValue exp);
629 
630 protected:
632 
634  DLLLOCAL int evalIntern(const AbstractQoreNode* exp);
635 
637 
639  DLLLOCAL int evalIntern(const QoreValue exp);
640 };
641 
643 DLLEXPORT extern const char* qoreBoolTypeName;
645 DLLEXPORT extern const char* qoreIntTypeName;
647 DLLEXPORT extern const char* qoreFloatTypeName;
648 
649 #endif
DLLEXPORT QoreValue()
creates with no value (i.e. QoreNothingNode)
DLLEXPORT void swap(QoreValue &val)
exchanges the values
DLLEXPORT ~ValueHolder()
dereferences any contained node
DLLEXPORT QoreValue getReferencedValue()
returns a referenced value; caller owns the reference; the current object is left undisturbed ...
double f
for double values
Definition: QoreValue.h:59
DLLLOCAL int evalIntern(const AbstractQoreNode *exp)
evaluates the argument, returns -1 for error, 0 = OK
DLLEXPORT bool isEqualSoft(const QoreValue v, ExceptionSink *xsink) const
returns trus if the argument value is equal to the current value with type conversions ...
base class for holding a QoreValue object
Definition: QoreValue.h:438
DLLEXPORT bool isReferenceCounted() const
returns true if the value holds a referenced-counted node
#define QV_Int
for integer values
Definition: QoreValue.h:44
this is the union that stores values in QoreValue
Definition: QoreValue.h:56
DLLEXPORT AbstractQoreNode * assignNothing()
sets the value of the object to QoreNothingNode and returns any node value held previously ...
DLLEXPORT QoreValue release()
returns a QoreValue object and leaves the current object empty; the caller owns any reference contain...
DLLLOCAL ValueHolder(ExceptionSink *xs)
creates an empty object
Definition: QoreValue.h:471
allows storing a value and setting a boolean flag that indicates if the value should be dereference i...
Definition: QoreValue.h:501
DLLLOCAL T * takeReferencedNode()
returns the stored node value and leaves the current object empty
Definition: QoreValue.h:560
evaluates an AbstractQoreNode and dereferences the stored value in the destructor ...
Definition: QoreValue.h:605
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 ...
The base class for all value and parse types in Qore expression trees.
Definition: AbstractQoreNode.h:57
DLLEXPORT const char * getFullTypeName() const
returns a string type description of the full type of the value contained (ex: "nothing" for a null A...
DLLEXPORT QoreValue & operator=(const QoreValue &n)
assigns a new value
DLLLOCAL bool isTemp() const
returns true if the value is temporary (needs dereferencing)
Definition: QoreValue.h:522
static void discard(AbstractQoreNode *n, ExceptionSink *xsink)
to deref an AbstractQoreNode (when the pointer may be 0)
Definition: QoreLib.h:324
DLLLOCAL ValueOptionalRefHolder(QoreValue n_v, bool nd, ExceptionSink *xs)
creates the object with the given values
Definition: QoreValue.h:512
DLLLOCAL AbstractQoreNode * takeNode(bool &nd)
returns the stored AbstractQoreNode pointer and sets the dereference flag as an output variable ...
Definition: QoreValue.h:574
bool needs_deref
flag indicating if the value should be dereferenced in the destructor or not
Definition: QoreValue.h:508
DLLEXPORT void ref() const
references the contained value if type == QV_Node
Qore&#39;s string type supported by the QoreEncoding class.
Definition: QoreString.h:81
ExceptionSink * xsink
for possible Qore-language exceptions
Definition: QoreValue.h:443
used in QoreValue::get()
Definition: QoreValue.h:67
#define QV_Node
for heap-allocated values
Definition: QoreValue.h:46
namespace for implementation details of QoreValue functions
Definition: QoreValue.h:64
DLLEXPORT bool derefCanThrowException() const
returns true if a dereference could theoretically throw an exception (an object is reachable from thi...
DLLEXPORT const QoreTypeInfo * getFullTypeInfo() const
returns the exact type of the value; i.e. the class type for classes, hashdecl type for hashdecls ...
DLLEXPORT AbstractQoreNode * takeIfNode()
returns a referenced value; leaving the "this" untouched; the caller owns the reference returned ...
DLLEXPORT void sanitize()
converts any node pointers to efficient representations if possible and dereferences the node value c...
DLLEXPORT QoreValue getReferencedValue()
returns a referenced value; caller owns the reference; the current object is not disturbed ...
DLLLOCAL QoreValue takeValue(bool &nd)
returns the stored value and sets the dereference flag as an output variable
Definition: QoreValue.h:584
#define QV_Bool
for boolean values
Definition: QoreValue.h:43
DLLLOCAL void setValue(QoreValue nv)
assigns a new non-temporary value
Definition: QoreValue.h:536
QoreValue v
the value held
Definition: QoreValue.h:441
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:594
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...
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:267
AbstractQoreNode * n
for all heap-allocated values
Definition: QoreValue.h:60
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:48
DLLEXPORT AbstractQoreNode * assign(const QoreValue n)
sets the value of the object and returns any node value held previously
DLLEXPORT const QoreTypeInfo * getTypeInfo() const
returns the type of the value
DLLEXPORT QoreValue takeReferencedValue()
returns a QoreValue after incrementing the reference count of any node value stored if necessary ...
DLLLOCAL QoreValue & operator*()
returns the value being managed
Definition: QoreValue.h:461
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
DLLLOCAL QoreValue & operator=(QoreValue nv)
assigns the object, any currently-held value is dereferenced before the assignment ...
Definition: QoreValue.h:488
int64 i
for integer values
Definition: QoreValue.h:58
DLLLOCAL ValueHolderBase(ExceptionSink *xs)
creates an ampty object
Definition: QoreValue.h:447
#define QV_Float
for floating-point values
Definition: QoreValue.h:45
int16_t qore_type_t
used to identify unique Qore data and parse types (descendents of AbstractQoreNode) ...
Definition: common.h:70
DLLEXPORT QoreValue eval(ExceptionSink *xsink) const
evaluates the node and returns the result
DLLEXPORT ValueEvalRefHolder(const AbstractQoreNode *exp, ExceptionSink *xs)
evaluates the exp argument
bool b
for boolean values
Definition: QoreValue.h:57
DLLLOCAL QoreValue * operator->()
returns the value being managed
Definition: QoreValue.h:455
DLLEXPORT int eval(const AbstractQoreNode *exp)
evaluates the argument, returns -1 for error, 0 = OK
DLLEXPORT bool isEqualHard(const QoreValue v) const
returns trus if the argument value is equal to the current value without any type conversions ...
holds an object and dereferences it in the destructor
Definition: QoreValue.h:468
DLLEXPORT bool hasNode() const
returns true if the object contains a non-null AbstractQoreNode pointer (ie type == QV_Node && v...
DLLLOCAL void clearTemp()
sets needs_deref = false
Definition: QoreValue.h:525
DLLEXPORT QoreValue refSelf() const
references the contained value if type == QV_Node, returns itself
DLLEXPORT void ensureReferencedValue()
DLLEXPORT void discard(ExceptionSink *xsink)
dereferences any contained AbstractQoreNode pointer and sets to 0; does not modify other values ...