32#ifndef _QORE_QOREHASHNODEINTERN_H
34#define _QORE_QOREHASHNODEINTERN_H
44 DLLLOCAL HashMember(
const char* n_key) : key(n_key) {
47 DLLLOCAL ~HashMember() {
51typedef std::list<HashMember*> qhlist_t;
53#ifdef HAVE_QORE_HASH_MAP
55#include <qore/hash_map_include.h>
56#include "qore/intern/xxhash.h"
58typedef HASH_MAP<const char*, qhlist_t::iterator, qore_hash_str, eqstr> hm_hm_t;
60typedef std::map<const char*, qhlist_t::iterator, ltstr> hm_hm_t;
69 DLLLOCAL qhi_priv() : val(false) {
72 DLLLOCAL qhi_priv(
const qhi_priv& old) : i(old.i), val(old.val) {
75 DLLLOCAL
bool valid()
const {
79 DLLLOCAL
bool next(qhlist_t& ml) {
82 if (ml.begin() != ml.end()) {
94 DLLLOCAL
bool prev(qhlist_t& ml) {
96 if (ml.begin() != ml.end()) {
110 DLLLOCAL
void reset() {
119class qore_hash_private {
121 qhlist_t member_list;
125 const QoreTypeInfo* complexTypeInfo =
nullptr;
126 unsigned obj_count = 0;
131 DLLLOCAL qore_hash_private() {
136 DLLLOCAL ~qore_hash_private() {
137 assert(member_list.empty());
140 DLLLOCAL
QoreValue getKeyValueIntern(
const char* key)
const;
144 DLLLOCAL
QoreValue getKeyValueExistenceIntern(
const char* key,
bool& exists)
const;
146 DLLLOCAL
int checkKey(
const char* key,
ExceptionSink* xsink)
const;
148 DLLLOCAL
QoreValue getReferencedKeyValueIntern(
const char* key)
const {
150 return getReferencedKeyValueIntern(key, exists);
153 DLLLOCAL
QoreValue getReferencedKeyValueIntern(
const char* key,
bool& exists)
const {
156 hm_hm_t::const_iterator i = hm.find(key);
159 return (*(i->second))->val.refSelf();
166 DLLLOCAL
int64 getKeyAsBigInt(
const char* key,
bool &found)
const {
168 hm_hm_t::const_iterator i = hm.find(key);
172 return (*(i->second))->val.getAsBigInt();
179 DLLLOCAL
bool getKeyAsBool(
const char* key,
bool& found)
const {
181 hm_hm_t::const_iterator i = hm.find(key);
185 return (*(i->second))->val.getAsBool();
192 DLLLOCAL
bool existsKey(
const char* key)
const {
194 return hm.find(key) != hm.end();
197 DLLLOCAL
bool existsKeyValue(
const char* key)
const {
199 hm_hm_t::const_iterator i = hm.find(key);
202 return !(*(i->second))->val.isNothing();
205 DLLLOCAL HashMember* findMember(
const char* key) {
207 hm_hm_t::iterator i = hm.find(key);
208 return i != hm.end() ? (*(i->second)) :
nullptr;
211 DLLLOCAL HashMember* findCreateMember(
const char* key) {
213 HashMember* om = findMember(key);
217 om =
new HashMember(key);
218 assert(om->val.isNothing());
219 member_list.push_back(om);
222 qhlist_t::iterator i = member_list.end();
224 hm[om->key.c_str()] = i;
230 DLLLOCAL
QoreValue& getValueRef(
const char* key) {
231 return findCreateMember(key)->val;
236 DLLLOCAL
void internDeleteKey(qhlist_t::iterator i) {
239 member_list.erase(i);
245 DLLLOCAL
void deleteKey(
const char* key,
ExceptionSink *xsink) {
248 hm_hm_t::iterator i = hm.find(key);
253 qhlist_t::iterator li = i->second;
263 reinterpret_cast<QoreObject*
>(n)->doDelete(xsink);
271 DLLLOCAL
void removeKey(
const char* key,
ExceptionSink *xsink) {
272 takeKeyValueIntern(key).discard(xsink);
275 DLLLOCAL
QoreValue takeKeyValueIntern(
const char* key) {
278 hm_hm_t::iterator i = hm.find(key);
283 qhlist_t::iterator li = i->second;
295 DLLLOCAL
QoreValue takeKeyValueIntern(
const char* key,
bool& exists) {
298 hm_hm_t::iterator i = hm.find(key);
306 qhlist_t::iterator li = i->second;
318 DLLLOCAL
const char* getFirstKey()
const {
319 return member_list.empty() ? nullptr : member_list.front()->key.c_str();
322 DLLLOCAL
const char* getLastKey()
const {
323 return member_list.empty() ? nullptr : member_list.back()->key.c_str();
328 DLLLOCAL
void merge(
const qore_hash_private& h0,
ExceptionSink* xsink);
333 DLLLOCAL
int getLValue(
const char* key, LValueHelper& lvh,
bool for_remove,
ExceptionSink* xsink);
335 DLLLOCAL
void getTypeName(
QoreString& str)
const {
338 else if (complexTypeInfo)
339 str.
concat(QoreTypeInfo::getName(complexTypeInfo));
350 h->
priv->hashdecl = hashdecl;
352 h->
priv->complexTypeInfo = complexTypeInfo;
356 DLLLOCAL
QoreHashNode* getEmptyCopy(
bool is_value)
const {
359 h->
priv->hashdecl = hashdecl;
361 h->
priv->complexTypeInfo = complexTypeInfo;
365 DLLLOCAL
QoreHashNode* copyCheckNewType(
const qore_hash_private& other)
const {
367 if (hashdecl || other.hashdecl) {
368 if (!hashdecl || !other.hashdecl || !hashdecl->
equal(other.hashdecl)) {
369 rv->
priv->hashdecl =
nullptr;
370 rv->
priv->complexTypeInfo = autoHashTypeInfo;
373 const QoreTypeInfo* orig_ctype, * ctype;
374 orig_ctype = ctype = QoreTypeInfo::getUniqueReturnComplexHash(complexTypeInfo);
375 const QoreTypeInfo* newElementType = QoreTypeInfo::getUniqueReturnComplexHash(other.complexTypeInfo);
376 if ((!ctype || ctype == anyTypeInfo) && (!newElementType || newElementType == anyTypeInfo)) {
377 rv->
priv->complexTypeInfo =
nullptr;
378 }
else if (QoreTypeInfo::matchCommonType(ctype, newElementType)) {
379 rv->
priv->complexTypeInfo = ctype == orig_ctype ? complexTypeInfo : qore_get_complex_hash_type(ctype);
381 rv->
priv->complexTypeInfo = autoHashTypeInfo;
387 DLLLOCAL
QoreHashNode* copy(
const QoreTypeInfo* newComplexTypeInfo)
const {
389 h->
priv->complexTypeInfo = newComplexTypeInfo;
390 copyIntern(*h->
priv);
397 if (!strip || (!complexTypeInfo && !hashdecl)) {
399 copyIntern(*h->
priv);
404 for (
auto& i : member_list) {
405 hash_assignment_priv ha(*h, i->key.c_str());
406 QoreValue v = copy_strip_complex_types(i->val);
408 assert(ha.swap(v).isNothing());
417 DLLLOCAL
void copyIntern(qore_hash_private& h)
const {
419 for (
auto& i : member_list) {
420 hash_assignment_priv ha(h, i->key.c_str());
422 assert(ha.swap(i->val.refSelf()).isNothing());
424 ha.swap(i->val.refSelf());
434 return *xsink ? nullptr : rv.release();
440 for (qhlist_t::const_iterator i = member_list.begin(), e = member_list.end(); i != e; ++i) {
441 h->
priv->setKeyValue((*i)->key, (*i)->val.refSelf(), xsink);
450 hash_assignment_priv ha(*
this, key);
452 ha.assign(val, sdh, xsink);
456 hash_assignment_priv ha(*
this, key.c_str());
458 ha.assign(val, sdh, xsink);
461 DLLLOCAL
void setKeyValueIntern(
const char* key,
QoreValue v) {
462 hash_assignment_priv ha(*
this, key);
469 hash_assignment_priv ha(*
this, key);
470 ha.assign(val, xsink);
474 hash_assignment_priv ha(*
this, key.c_str());
475 ha.assign(val, xsink);
479 hash_assignment_priv ha(*
this, key,
false, o);
480 ha.assign(val, xsink);
483 DLLLOCAL
bool derefImpl(
ExceptionSink* xsink,
bool reverse =
false) {
485 for (qhlist_t::reverse_iterator i = member_list.rbegin(), e = member_list.rend(); i != e; ++i) {
486 (*i)->val.discard(xsink);
490 for (qhlist_t::iterator i = member_list.begin(), e = member_list.end(); i != e; ++i) {
491 (*i)->val.discard(xsink);
502 DLLLOCAL
QoreValue swapKeyValueIfExists(
const char* key,
QoreValue val, qore_object_private* o,
bool& exists) {
503 hash_assignment_priv ha(*
this, key,
true, o);
512 DLLLOCAL
QoreValue swapKeyValue(
const char* key,
QoreValue val, qore_object_private* o) {
515 hash_assignment_priv ha(*
this, key,
false, o);
520 derefImpl(xsink, reverse);
523 DLLLOCAL
size_t size()
const {
524 return member_list.size();
527 DLLLOCAL
bool empty()
const {
528 return member_list.empty();
531 DLLLOCAL
void incScanCount(
int dt) {
534 assert(obj_count || dt > 0);
539 DLLLOCAL
const QoreTypeInfo* getValueTypeInfo()
const {
540 return complexTypeInfo ? QoreTypeInfo::getComplexHashValueType(complexTypeInfo) : nullptr;
543 DLLLOCAL
const QoreTypeInfo* getTypeInfo()
const {
547 return complexTypeInfo;
556 if (!h->
priv->hashdecl && !h->
priv->complexTypeInfo)
560 return h->
priv->copy(
true);
565 rv->
priv->hashdecl = hd;
569 DLLLOCAL
static qore_hash_private* get(
QoreHashNode& h) {
573 DLLLOCAL
static const qore_hash_private* get(
const QoreHashNode& h) {
578 DLLLOCAL
static int parseInitHashInitialization(
const QoreProgramLocation* loc, QoreParseContext& parse_context,
579 QoreParseListNode* args,
QoreValue& arg,
int& err);
581 DLLLOCAL
static int parseInitComplexHashInitialization(
const QoreProgramLocation* loc, QoreParseContext& parse_context,
582 QoreParseListNode* args);
584 DLLLOCAL
static int parseCheckComplexHashInitialization(
const QoreProgramLocation* loc,
585 const QoreTypeInfo* valueTypeInfo,
const QoreTypeInfo* argTypeInfo,
QoreValue exp,
586 const char* context_action,
bool strict_check =
true);
588 DLLLOCAL
static int parseCheckTypedAssignment(
const QoreProgramLocation* loc,
QoreValue arg,
589 const QoreTypeInfo* vti,
const char* context_action,
bool strict_check =
true);
591 DLLLOCAL
static QoreHashNode* newComplexHash(
const QoreTypeInfo* typeInfo,
const QoreParseListNode* args,
597 DLLLOCAL
static unsigned getScanCount(
const QoreHashNode& h) {
598 assert(!h.
priv->is_obj);
599 return h.
priv->obj_count;
602 DLLLOCAL
static void incScanCount(
const QoreHashNode& h,
int dt) {
603 assert(!h.
priv->is_obj);
604 h.
priv->incScanCount(dt);
608 return h->
priv->member_list.empty() ?
QoreValue() : h->priv->member_list.front()->val;
612 return h->
priv->member_list.empty() ?
QoreValue() : h->priv->member_list.back()->val;
The base class for all value and parse types in Qore expression trees.
Definition: AbstractQoreNode.h:57
DLLLOCAL qore_type_t getType() const
returns the data type
Definition: AbstractQoreNode.h:175
DLLEXPORT void deref(ExceptionSink *xsink)
decrements the reference count and calls derefImpl() if there_can_be_only_one is false,...
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:50
iterator class for QoreHashNode, to be only created on the stack
Definition: QoreHashNode.h:444
This is the hash or associative list container type in Qore, dynamically allocated only,...
Definition: QoreHashNode.h:50
class qore_hash_private * priv
private implementation of the class
Definition: QoreHashNode.h:396
This is the list container type in Qore, dynamically allocated only, reference counted.
Definition: QoreListNode.h:52
the implementation of Qore's object data type, reference counted, dynamically-allocated only
Definition: QoreObject.h:60
Qore's string type supported by the QoreEncoding class.
Definition: QoreString.h:93
DLLEXPORT void concat(const QoreString *str, ExceptionSink *xsink)
concatenates a string and converts encodings if necessary
DLLEXPORT int sprintf(const char *fmt,...)
this will concatentate a formatted string to the existing string according to the format string and t...
a templated class to manage a reference count of an object that can throw a Qore-language exception w...
Definition: ReferenceHolder.h:52
Helps dereference values outside of locks.
Definition: QoreLibIntern.h:543
typed hash declaration
Definition: TypedHashDecl.h:44
DLLEXPORT const char * getName() const
returns the name of the typed hash
DLLEXPORT bool equal(const TypedHashDecl *other) const
returns true if the hashdecl passed as an arugment is equal to this hashdecl
DLLEXPORT const QoreTypeInfo * getTypeInfo(bool or_nothing=false) const
returns the type info object for the hashdecl
holds an object and dereferences it in the destructor
Definition: QoreValue.h:487
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
const qore_type_t NT_OBJECT
type value for QoreObject
Definition: node_types.h:52
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:276