The following are the basic data types in Qore, implemented as C++ classes descended from AbstractQoreNode, and their type codes, accessed via AbstractQoreNode::getType():
Additionally, the following classes are exposed in the library:
if (node->getType() == NT_DATE) { DateTimeNode *dt = reinterpret_cast<DateTimeNode *>(node); // .. do something with dt }
This is faster than using dynamic_cast<> as follows (which is also a perfectly legal method for getting a pointer/testing the data type as well, just a little slower due to the dynamic_cast<>):
DateTimeNode *dt = dynamic_cast<DateTimeNode *>(node); if (dt) { // do something with dt... }
They are all descendents of SimpleQoreNode, meaning that dereferencing their objects cannot cause a Qore-language exception to be thrown (hence all support the SimpleQoreNode::deref() function), therefore the SimpleRefHolder class can be used to manage temporary references to objects of these types.
For example:
{ // here getQoreBigIntNode() returns a QoreBigIntNode value with an incremented reference count SimpleRefHolder<QoreBigIntNode> qint(getQoreBigIntNode()); printf("the result is: %lld\n", qint->val); // when qint goes out of scope, the reference count is decremented by calling SimpleQoreNode::deref() }
For the QoreBoolNode class, you can use these objects by referring to the global True and False objects, or by calling get_bool_node() as follows in the example function:
static AbstractQoreNode *f_convert_first_argument_to_bool(const QoreListNode *params, ExceptionSink *xsink) { const AbstractQoreNode *p = get_param(params, 0); return get_bool_node(p ? p->getAsBool() : false); }
Or, some even simpler functions:
static AbstractQoreNode *f_return_true(const QoreListNode *params, ExceptionSink *xsink) { return &True; // QoreBoolNode objects are not reference counted (reference counting operations are ignored) } static AbstractQoreNode *f_return_false(const QoreListNode *params, ExceptionSink *xsink) { return &False; // QoreBoolNode objects are not reference counted (reference counting operations are ignored) }
Similarly, for QoreNullNode there is the global Null object or the inline function null() that returns a pointer to this object. The inline function is_null() can be used to test for a Qore SQL Null value.
QoreNothingNode has the gobal Nothing object and the inline function nothing() that returns a pointer to it as well.
NOTHING
, therefore the inline function is_nothing() should always be used to test for NOTHING
. Therefore the following code is incorrect:// get_qore_value() returns an "AbstractQoreNode *" AbstractQoreNode *p = get_qore_value(); if (!p) { // incorrect! NOTHING in Qore can be represented by a 0 or a pointer to the Nothing value }
The code should look like this instead:
// get_qore_value() returns an "AbstractQoreNode *" AbstractQoreNode *p = get_qore_value(); if (is_nothing(p)) { // correct test for nothing }
The ReferenceHolder class can be used to manage temporary reference counts as follows:
{ // here a QoreHashNode value is returned with an incremented reference count // note that xsink must be "ExceptionSink *" ReferenceHolder<QoreHashNode> qhash(getQoreHashNode(), xsink); printf("there are %ld elements in the hash\n", qhash->size()); // when qhash goes out of scope, the reference count is decremented }
QoreObject is special in that the implementation for objects in Qore mirrors that of Java, in that objects are pased by reference when used as function or method arguments, unlike other types. However, like Java, the reference to the object is passed, and not the variable, so, while an object passed as an argument to a function can be modified by that function (modifications are made to the original object), in order to write a swap method, for example, you would need to pass the variables by reference (or the lvalue expression by reference, as the case may be) to the swap function. Unlike Java, Qore does support passing arguments by reference.
Here is an example of the use of ReferenceHelper:
static AbstractQoreNode *f_chomp(const QoreListNode *params, ExceptionSink *xsink) { const AbstractQoreNode *p = get_param(params, 0); if (!p) return 0; qore_type_t ptype = p->getType(); // ... some code not relevant to this example removed // note that the function test_reference_param() can be used // to test for a reference argument directly if (ptype != NT_REFERENCE) return 0; const ReferenceNode *r = reinterpret_cast<const ReferenceNode *>(p); // ReferenceHelper will take care of locking any objects that need to // be locked for accessing the variable (if necessary). The locks // are released when the ReferenceHelper object goes out of scope AutoVLock vl(xsink); ReferenceHelper ref(r, vl, xsink); if (!ref || ref.getType() != NT_STRING) return 0; QoreStringNode *str = reinterpret_cast<QoreStringNode *>(ref.getUnique(xsink)); if (*xsink) return 0; str->chomp(); return str->refSelf(); }