Qore Programming Language  1.12.0
QC_TreeMap.h
1 /* -*- mode: c++; indent-tabs-mode: nil -*- */
2 /*
3  QC_TreeMap.h
4 
5  Qore Programming Language
6 
7  Copyright (C) 2003 - 2022 Qore Technologoes, 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_QC_TREEMAP_H
33 #define _QORE_QC_TREEMAP_H
34 
35 #include <qore/Qore.h>
36 #include <map>
37 #include <string>
38 
39 DLLEXPORT extern qore_classid_t CID_TREEMAP;
40 DLLLOCAL extern QoreClass* QC_TREEMAP;
41 
42 DLLLOCAL QoreClass* initTreeMapClass(QoreNamespace& ns);
43 
44 static inline bool isPathEnd(char c) {
45  return c == '/' || c == '?';
46 }
47 
48 static inline size_t getFirstPathSegmentLength(const std::string& path) {
49  size_t prefixLen = path.find_first_of("/?");
50  return prefixLen == std::string::npos ? path.length() : prefixLen;
51 }
52 
53 static inline bool isPrefix(const std::string& prefix, const std::string& str) {
54  return str.length() >= prefix.length() && !str.compare(0, prefix.length(), prefix);
55 }
56 
57 static inline bool isPathPrefix(const std::string& prefix, const std::string& path) {
58  return isPrefix(prefix, path) && (path.length() == prefix.length() || isPathEnd(path[prefix.length()]));
59 }
60 
61 class TreeMapData : public AbstractPrivateData {
62 public:
63  DLLLOCAL TreeMapData() {
64  }
65 
66  DLLLOCAL virtual void deref(ExceptionSink* xsink) {
67  if (ROdereference()) {
68  for (Map::iterator i = data.begin(), e = data.end(); i != e; ++i) {
69  i->second.discard(xsink);
70  }
71  delete this;
72  }
73  }
74 
75  DLLLOCAL void put(const QoreStringNode* key, const QoreValue value, ExceptionSink* xsink) {
76  TempEncodingHelper keyStr(key, QCS_DEFAULT, xsink);
77  if (keyStr) {
78  QoreAutoRWWriteLocker al(rwl);
79 
80  Map::mapped_type &refToMap = data[keyStr->c_str()];
81  refToMap.discard(xsink);
82  refToMap = value.refSelf();
83  }
84  }
85 
86  // return value must be dereferenced by the caller
87  DLLLOCAL QoreValue get(const QoreStringNode* key, const ReferenceNode* unmatched, ExceptionSink* xsink) const {
88  TempEncodingHelper keyStr(key, QCS_DEFAULT, xsink);
89  if (!keyStr) {
90  return QoreValue();
91  }
92 
93  QoreAutoRWReadLocker al(rwl);
94  if (!data.empty()) {
95  std::string path(keyStr->c_str());
96 
97  Map::const_iterator b = data.begin();
98  Map::const_iterator it = data.upper_bound(path);
99 
100  size_t prefixLen = getFirstPathSegmentLength(path);
101  while (it != b && !(--it)->first.compare(0, prefixLen, path, 0, prefixLen)) {
102  if (isPathPrefix(it->first, path)) {
103  if (unmatched) {
104  size_t l = it->first.length();
105  if (isPathEnd(path[l])) {
106  l++;
107  }
108  QoreTypeSafeReferenceHelper ref(unmatched, xsink);
109  if (!ref)
110  return QoreValue();
111  SimpleRefHolder<QoreStringNode> path(key->substr(l, xsink));
112  if (*xsink || ref.assign(path.release()))
113  return QoreValue();
114  }
115  return it->second.refSelf();
116  }
117  }
118  }
119  if (unmatched) {
120  QoreTypeSafeReferenceHelper ref(unmatched, xsink);
121  if (!ref)
122  return QoreValue();
123  if (ref.assign(&Nothing))
124  return QoreValue();
125  }
126  return QoreValue();
127  }
128 
129  DLLLOCAL QoreHashNode* getAll() const {
130  QoreAutoRWReadLocker al(rwl);
131 
132  if (data.empty())
133  return nullptr;
134 
135  ReferenceHolder<QoreHashNode> h(new QoreHashNode(autoTypeInfo), nullptr);
136  for (Map::const_iterator i = data.begin(), e = data.end(); i != e; ++i)
137  h->setKeyValue(i->first.c_str(), i->second.refSelf(), nullptr);
138  return h.release();
139  }
140 
141  // return value must be dereferenced
142  DLLLOCAL QoreValue take(const QoreStringNode* key, ExceptionSink* xsink) {
143  TempEncodingHelper keyStr(key, QCS_DEFAULT, xsink);
144  if (!keyStr) {
145  return QoreValue();
146  }
147 
148  QoreAutoRWWriteLocker al(rwl);
149  Map::iterator i = data.find(keyStr->c_str());
150  if (i == data.end())
151  return QoreValue();
152 
153  QoreValue rv = i->second;
154  data.erase(i);
155  return rv;
156  }
157 
158 private:
159  typedef std::map<std::string, QoreValue> Map;
160  Map data;
161  mutable QoreRWLock rwl;
162 };
163 
164 #endif
DLLEXPORT const QoreEncoding * QCS_DEFAULT
the default encoding for the Qore library
DLLEXPORT QoreNothingNode Nothing
the global and unique NOTHING object in Qore
the base class for all data to be used as private data of Qore objects
Definition: AbstractPrivateData.h:44
DLLLOCAL void ref() const
increments the reference count of the object
Definition: AbstractPrivateData.h:51
virtual DLLLOCAL void deref()
decrements the reference count of the object without the possibility of throwing a Qore-language exce...
Definition: AbstractPrivateData.h:65
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:48
provides a safe and exception-safe way to hold read locks in Qore, only to be used on the stack,...
Definition: QoreRWLock.h:105
provides a safe and exception-safe way to hold write locks in Qore, only to be used on the stack,...
Definition: QoreRWLock.h:144
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
contains constants, classes, and subnamespaces in QoreProgram objects
Definition: QoreNamespace.h:65
provides a simple POSIX-threads-based read-write lock
Definition: QoreRWLock.h:47
DLLEXPORT bool ROdereference() const
atomically decrements the reference count
Qore's string value type, reference counted, dynamically-allocated only.
Definition: QoreStringNode.h:50
DLLEXPORT QoreStringNode * substr(qore_offset_t offset, ExceptionSink *xsink) const
returns a new string consisting of all the characters from the current string starting with character...
helper class to manage variable references passed to functions and class methods, stack only,...
Definition: QoreTypeSafeReferenceHelper.h:57
parse type: reference to a lvalue expression
Definition: ReferenceNode.h:45
use this class to manage strings where the character encoding must be specified and may be different ...
Definition: QoreString.h:1104
unsigned qore_classid_t
used for the unique class ID for QoreClass objects
Definition: common.h:79
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:275
DLLEXPORT QoreValue refSelf() const
references the contained value if type == QV_Node, returns itself