32 #ifndef _QORE_QOREHASHNODEINTERN_H
34 #define _QORE_QOREHASHNODEINTERN_H
44 DLLLOCAL HashMember(
const char* n_key) : key(n_key) {
47 DLLLOCAL ~HashMember() {
51 typedef std::list<HashMember*> qhlist_t;
53 #ifdef HAVE_QORE_HASH_MAP
55 #include <qore/hash_map_include.h>
56 #include "qore/intern/xxhash.h"
58 typedef HASH_MAP<const char*, qhlist_t::iterator, qore_hash_str, eqstr> hm_hm_t;
60 typedef 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()) {
95 DLLLOCAL
bool prev(qhlist_t& ml) {
97 if (ml.begin() != ml.end()) {
112 DLLLOCAL
void reset() {
121 class qore_hash_private {
123 qhlist_t member_list;
127 const QoreTypeInfo* complexTypeInfo =
nullptr;
128 unsigned obj_count = 0;
133 DLLLOCAL qore_hash_private() {
138 DLLLOCAL ~qore_hash_private() {
139 assert(member_list.empty());
142 DLLLOCAL
QoreValue getKeyValueIntern(
const char* key)
const;
146 DLLLOCAL
QoreValue getKeyValueExistenceIntern(
const char* key,
bool& exists)
const;
148 DLLLOCAL
int checkKey(
const char* key,
ExceptionSink* xsink)
const;
150 DLLLOCAL
QoreValue getReferencedKeyValueIntern(
const char* key)
const {
152 return getReferencedKeyValueIntern(key, exists);
155 DLLLOCAL
QoreValue getReferencedKeyValueIntern(
const char* key,
bool& exists)
const {
158 hm_hm_t::const_iterator i = hm.find(key);
161 return (*(i->second))->val.refSelf();
168 DLLLOCAL
int64 getKeyAsBigInt(
const char* key,
bool &found)
const {
170 hm_hm_t::const_iterator i = hm.find(key);
174 return (*(i->second))->val.getAsBigInt();
181 DLLLOCAL
bool getKeyAsBool(
const char* key,
bool& found)
const {
183 hm_hm_t::const_iterator i = hm.find(key);
187 return (*(i->second))->val.getAsBool();
194 DLLLOCAL
bool existsKey(
const char* key)
const {
196 return hm.find(key) != hm.end();
199 DLLLOCAL
bool existsKeyValue(
const char* key)
const {
201 hm_hm_t::const_iterator i = hm.find(key);
204 return !(*(i->second))->val.isNothing();
207 DLLLOCAL HashMember* findMember(
const char* key) {
209 hm_hm_t::iterator i = hm.find(key);
210 return i != hm.end() ? (*(i->second)) :
nullptr;
213 DLLLOCAL HashMember* findCreateMember(
const char* key) {
215 HashMember* om = findMember(key);
219 om =
new HashMember(key);
220 assert(om->val.isNothing());
221 member_list.push_back(om);
224 qhlist_t::iterator i = member_list.end();
226 hm[om->key.c_str()] = i;
232 DLLLOCAL
QoreValue& getValueRef(
const char* key) {
233 return findCreateMember(key)->val;
238 DLLLOCAL
void internDeleteKey(qhlist_t::iterator i) {
241 member_list.erase(i);
247 DLLLOCAL
void deleteKey(
const char* key,
ExceptionSink *xsink) {
250 hm_hm_t::iterator i = hm.find(key);
255 qhlist_t::iterator li = i->second;
265 reinterpret_cast<QoreObject*
>(n)->doDelete(xsink);
273 DLLLOCAL
void removeKey(
const char* key,
ExceptionSink *xsink) {
274 takeKeyValueIntern(key).discard(xsink);
277 DLLLOCAL
QoreValue takeKeyValueIntern(
const char* key) {
280 hm_hm_t::iterator i = hm.find(key);
285 qhlist_t::iterator li = i->second;
297 DLLLOCAL
QoreValue takeKeyValueIntern(
const char* key,
bool& exists) {
300 hm_hm_t::iterator i = hm.find(key);
308 qhlist_t::iterator li = i->second;
320 DLLLOCAL
const char* getFirstKey()
const {
321 return member_list.empty() ? nullptr : member_list.front()->key.c_str();
324 DLLLOCAL
const char* getLastKey()
const {
325 return member_list.empty() ? nullptr : member_list.back()->key.c_str();
330 DLLLOCAL
void merge(
const qore_hash_private& h0,
ExceptionSink* xsink);
335 DLLLOCAL
int getLValue(
const char* key, LValueHelper& lvh,
bool for_remove,
ExceptionSink* xsink);
337 DLLLOCAL
void getTypeName(
QoreString& str)
const {
340 else if (complexTypeInfo)
341 str.
concat(QoreTypeInfo::getName(complexTypeInfo));
352 h->
priv->hashdecl = hashdecl;
354 h->
priv->complexTypeInfo = complexTypeInfo;
358 DLLLOCAL
QoreHashNode* getEmptyCopy(
bool is_value)
const {
361 h->
priv->hashdecl = hashdecl;
363 h->
priv->complexTypeInfo = complexTypeInfo;
367 DLLLOCAL
QoreHashNode* copyCheckNewType(
const qore_hash_private& other)
const {
369 if (hashdecl || other.hashdecl) {
370 if (!hashdecl || !other.hashdecl || !hashdecl->
equal(other.hashdecl)) {
371 rv->
priv->hashdecl =
nullptr;
372 rv->
priv->complexTypeInfo = autoHashTypeInfo;
375 const QoreTypeInfo* orig_ctype, * ctype;
376 orig_ctype = ctype = QoreTypeInfo::getUniqueReturnComplexHash(complexTypeInfo);
377 const QoreTypeInfo* newElementType = QoreTypeInfo::getUniqueReturnComplexHash(other.complexTypeInfo);
378 if ((!ctype || ctype == anyTypeInfo) && (!newElementType || newElementType == anyTypeInfo)) {
379 rv->
priv->complexTypeInfo =
nullptr;
380 }
else if (QoreTypeInfo::matchCommonType(ctype, newElementType)) {
381 rv->
priv->complexTypeInfo = ctype == orig_ctype ? complexTypeInfo : qore_get_complex_hash_type(ctype);
383 rv->
priv->complexTypeInfo = autoHashTypeInfo;
389 DLLLOCAL
QoreHashNode* copy(
const QoreTypeInfo* newComplexTypeInfo)
const {
391 h->
priv->complexTypeInfo = newComplexTypeInfo;
392 copyIntern(*h->
priv);
399 if (!strip || (!complexTypeInfo && !hashdecl)) {
401 copyIntern(*h->
priv);
406 for (
auto& i : member_list) {
407 hash_assignment_priv ha(*h, i->key.c_str());
408 QoreValue v = copy_strip_complex_types(i->val);
410 assert(ha.swap(v).isNothing());
419 DLLLOCAL
void copyIntern(qore_hash_private& h)
const {
421 for (
auto& i : member_list) {
422 hash_assignment_priv ha(h, i->key.c_str());
424 assert(ha.swap(i->val.refSelf()).isNothing());
426 ha.swap(i->val.refSelf());
436 return *xsink ? nullptr : rv.release();
442 for (qhlist_t::const_iterator i = member_list.begin(), e = member_list.end(); i != e; ++i) {
443 h->
priv->setKeyValue((*i)->key, (*i)->val.refSelf(), xsink);
452 hash_assignment_priv ha(*
this, key);
454 ha.assign(val, sdh, xsink);
458 hash_assignment_priv ha(*
this, key.c_str());
460 ha.assign(val, sdh, xsink);
463 DLLLOCAL
void setKeyValueIntern(
const char* key,
QoreValue v) {
464 hash_assignment_priv ha(*
this, key);
471 hash_assignment_priv ha(*
this, key);
472 ha.assign(val, xsink);
476 hash_assignment_priv ha(*
this, key.c_str());
477 ha.assign(val, xsink);
481 hash_assignment_priv ha(*
this, key,
false, o);
482 ha.assign(val, xsink);
485 DLLLOCAL
bool derefImpl(
ExceptionSink* xsink,
bool reverse =
false) {
487 for (qhlist_t::reverse_iterator i = member_list.rbegin(), e = member_list.rend(); i != e; ++i) {
488 (*i)->val.discard(xsink);
492 for (qhlist_t::iterator i = member_list.begin(), e = member_list.end(); i != e; ++i) {
493 (*i)->val.discard(xsink);
504 DLLLOCAL
QoreValue swapKeyValueIfExists(
const char* key,
QoreValue val, qore_object_private* o,
bool& exists) {
505 hash_assignment_priv ha(*
this, key,
true, o);
514 DLLLOCAL
QoreValue swapKeyValue(
const char* key,
QoreValue val, qore_object_private* o) {
517 hash_assignment_priv ha(*
this, key,
false, o);
522 derefImpl(xsink, reverse);
525 DLLLOCAL
size_t size()
const {
526 return member_list.size();
529 DLLLOCAL
bool empty()
const {
530 return member_list.empty();
533 DLLLOCAL
void incScanCount(
int dt) {
536 assert(obj_count || dt > 0);
541 DLLLOCAL
const QoreTypeInfo* getValueTypeInfo()
const {
542 return complexTypeInfo ? QoreTypeInfo::getComplexHashValueType(complexTypeInfo) : nullptr;
545 DLLLOCAL
const QoreTypeInfo* getTypeInfo()
const {
549 return complexTypeInfo;
558 if (!h->
priv->hashdecl && !h->
priv->complexTypeInfo)
562 return h->
priv->copy(
true);
567 rv->
priv->hashdecl = hd;
571 DLLLOCAL
static qore_hash_private* get(
QoreHashNode& h) {
575 DLLLOCAL
static const qore_hash_private* get(
const QoreHashNode& h) {
580 DLLLOCAL
static int parseInitHashInitialization(
const QoreProgramLocation* loc, QoreParseContext& parse_context,
581 QoreParseListNode* args,
QoreValue& arg,
int& err);
583 DLLLOCAL
static int parseInitComplexHashInitialization(
const QoreProgramLocation* loc, QoreParseContext& parse_context,
584 QoreParseListNode* args);
586 DLLLOCAL
static int parseCheckComplexHashInitialization(
const QoreProgramLocation* loc,
587 const QoreTypeInfo* valueTypeInfo,
const QoreTypeInfo* argTypeInfo,
QoreValue exp,
588 const char* context_action,
bool strict_check =
true);
590 DLLLOCAL
static int parseCheckTypedAssignment(
const QoreProgramLocation* loc,
QoreValue arg,
591 const QoreTypeInfo* vti,
const char* context_action,
bool strict_check =
true);
593 DLLLOCAL
static QoreHashNode* newComplexHash(
const QoreTypeInfo* typeInfo,
const QoreParseListNode* args,
599 DLLLOCAL
static unsigned getScanCount(
const QoreHashNode& h) {
600 assert(!h.
priv->is_obj);
601 return h.
priv->obj_count;
604 DLLLOCAL
static void incScanCount(
const QoreHashNode& h,
int dt) {
605 assert(!h.
priv->is_obj);
606 h.
priv->incScanCount(dt);
610 return h->
priv->member_list.empty() ?
QoreValue() : h->priv->member_list.front()->val;
614 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:48
iterator class for QoreHashNode, to be only created on the stack
Definition: QoreHashNode.h:447
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:69
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...
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:476
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:275