Qore Programming Language  1.12.0
QoreHashIterator.h
1 /* -*- mode: c++; indent-tabs-mode: nil -*- */
2 /*
3  QoreHashIterator.h
4 
5  Qore Programming Language
6 
7  Copyright (C) 2003 - 2022 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_QOREHASHITERATOR_H
33 
34 #define _QORE_QOREHASHITERATOR_H
35 
36 extern QoreClass* QC_HASHITERATOR;
37 extern QoreClass* QC_HASHKEYITERATOR;
38 extern QoreClass* QC_HASHPAIRITERATOR;
39 extern QoreClass* QC_HASHREVERSEITERATOR;
40 
41 // the c++ object
42 class QoreHashIterator : public QoreIteratorBase, public ConstHashIterator {
43 protected:
44  // reusable hash for pair iterator performance enhancement; provides an approx 70% speed improvement
45  mutable QoreHashNode* pairHash;
46 
47  DLLLOCAL virtual ~QoreHashIterator() {
48  assert(!pairHash);
49  assert(!h);
50  }
51 
52  DLLLOCAL int checkPtr(ExceptionSink* xsink) const {
53  if (!valid()) {
54  xsink->raiseException("ITERATOR-ERROR", "the %s is not pointing at a valid element; make sure %s::next() returns True before calling this method", getName(), getName());
55  return -1;
56  }
57  return 0;
58  }
59 
60  DLLLOCAL QoreHashIterator(QoreHashNode* h) : ConstHashIterator(h), pairHash(0) {
61  }
62 
63 public:
64  DLLLOCAL QoreHashIterator(const QoreHashNode* h) : ConstHashIterator(h->hashRefSelf()), pairHash(0) {
65  }
66 
67  DLLLOCAL QoreHashIterator() : ConstHashIterator(0), pairHash(0) {
68  }
69 
70  DLLLOCAL QoreHashIterator(const QoreHashIterator& old) : ConstHashIterator(*this), pairHash(0) {
71  }
72 
74  DLLLOCAL virtual void deref(ExceptionSink* xsink) {
75  if (ROdereference()) {
76  if (h) {
77  const_cast<QoreHashNode*>(h)->deref(xsink);
78 #ifdef DEBUG
79  h = nullptr;
80 #endif
81  }
82  if (pairHash) {
83  pairHash->deref(xsink);
84 #ifdef DEBUG
85  pairHash = nullptr;
86 #endif
87  }
88  delete this;
89  }
90  }
91 
92  DLLLOCAL QoreValue getReferencedValue(ExceptionSink* xsink) const {
93  if (checkPtr(xsink))
94  return QoreValue();
96  }
97 
98  DLLLOCAL QoreValue getReferencedKeyValue(ExceptionSink* xsink) const {
99  if (checkPtr(xsink))
100  return QoreValue();
102  }
103 
104  DLLLOCAL QoreHashNode* getReferencedValuePair(ExceptionSink* xsink) const {
105  if (checkPtr(xsink))
106  return nullptr;
107  // create or re-use the pair hash if possible
108  if (!pairHash)
109  pairHash = new QoreHashNode(autoTypeInfo);
110  else if (!pairHash->is_unique()) {
111  pairHash->deref(xsink);
112  pairHash = new QoreHashNode(autoTypeInfo);
113  }
114  pairHash->setKeyValue("key", new QoreStringNode(ConstHashIterator::getKey()), xsink);
115  pairHash->setKeyValue("value", ConstHashIterator::getReferenced(), xsink);
116  return pairHash->hashRefSelf();
117  }
118 
119  DLLLOCAL QoreStringNode* getKey(ExceptionSink* xsink) const {
120  if (checkPtr(xsink))
121  return nullptr;
123  }
124 
125  DLLLOCAL bool empty() const {
126  return !h || h->empty();
127  }
128 
129  DLLLOCAL bool next() {
130  if (!h)
131  return false;
132  return ConstHashIterator::next();
133  }
134 
135  DLLLOCAL bool prev() {
136  if (!h)
137  return false;
138  return ConstHashIterator::prev();
139  }
140 
141  DLLLOCAL virtual const char* getName() const { return "HashIterator"; }
142 
143  DLLLOCAL virtual const QoreTypeInfo* getElementType() const {
144  return h->getValueTypeInfo();
145  }
146 };
147 
148 // internal reverse iterator class implementation only for the getName() function - the iterators remain
149 // forwards and are used in the reverse sense by the Qore language class implementation below
150 class QoreHashReverseIterator : public QoreHashIterator {
151 public:
152  DLLLOCAL QoreHashReverseIterator(const QoreHashNode* h) : QoreHashIterator(h) {
153  }
154 
155  DLLLOCAL QoreHashReverseIterator() {
156  }
157 
158  DLLLOCAL QoreHashReverseIterator(const QoreHashReverseIterator& old) : QoreHashIterator(old) {
159  }
160 
161  DLLLOCAL virtual const char* getName() const {
162  return "HashReverseIterator";
163  }
164 };
165 
166 #endif // _QORE_QOREHASHITERATOR_H
virtual DLLLOCAL void deref()
decrements the reference count of the object without the possibility of throwing a Qore-language exce...
Definition: AbstractPrivateData.h:65
DLLEXPORT void deref(ExceptionSink *xsink)
decrements the reference count and calls derefImpl() if there_can_be_only_one is false,...
constant iterator class for QoreHashNode, to be only created on the stack
Definition: QoreHashNode.h:577
DLLEXPORT bool valid() const
returns true if the iterator is currently pointing at a valid element
DLLEXPORT bool prev()
moves to the previous element, returns false when there are no more elements to iterate
DLLEXPORT QoreValue getReferenced() const
returns the value of the current key with an incremented reference count
DLLEXPORT const char * getKey() const
returns the current key
DLLEXPORT bool next()
moves to the next element, returns false when there are no more elements to iterate
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:48
DLLEXPORT AbstractQoreNode * raiseException(const char *err, const char *fmt,...)
appends a Qore-language exception to the list
defines a Qore-language class
Definition: QoreClass.h:249
This is the hash or associative list container type in Qore, dynamically allocated only,...
Definition: QoreHashNode.h:50
DLLEXPORT int setKeyValue(const char *key, QoreValue value, ExceptionSink *xsink)
sets the value of "key" to "value"
DLLEXPORT const QoreTypeInfo * getValueTypeInfo() const
returns the value type declaration (only possible if there is no hashdecl set)
DLLEXPORT bool empty() const
returns true if the hash has no members, false if not
DLLEXPORT QoreHashNode * hashRefSelf() const
returns "this" with an incremented reference count
abstract base class for iterator private data
Definition: QoreIteratorBase.h:68
DLLEXPORT bool ROdereference() const
atomically decrements the reference count
DLLEXPORT bool is_unique() const
returns true if the reference count is 1
Qore's string value type, reference counted, dynamically-allocated only.
Definition: QoreStringNode.h:50
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:275