1 | /* |
2 | * PROGRAM: Client/Server Common Code |
3 | * MODULE: StringMap.h |
4 | * DESCRIPTION: Secure handling of clumplet buffers |
5 | * |
6 | * The contents of this file are subject to the Initial |
7 | * Developer's Public License Version 1.0 (the "License"); |
8 | * you may not use this file except in compliance with the |
9 | * License. You may obtain a copy of the License at |
10 | * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. |
11 | * |
12 | * Software distributed under the License is distributed AS IS, |
13 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. |
14 | * See the License for the specific language governing rights |
15 | * and limitations under the License. |
16 | * |
17 | * The Original Code was created by Nickolay Samofatov |
18 | * for the Firebird Open Source RDBMS project. |
19 | * |
20 | * Copyright (c) 2004 Nickolay Samofatov <nickolay@broadviewsoftware.com> |
21 | * and all contributors signed below. |
22 | * |
23 | * All Rights Reserved. |
24 | * Contributor(s): ______________________________________. |
25 | * |
26 | * |
27 | */ |
28 | |
29 | #ifndef STRINGMAP_H |
30 | #define STRINGMAP_H |
31 | |
32 | #include "../common/classes/fb_string.h" |
33 | #include "../common/classes/fb_pair.h" |
34 | #include "../common/classes/tree.h" |
35 | |
36 | namespace Firebird { |
37 | |
38 | // |
39 | // Generic map which allows to have POD and non-POD keys and values. |
40 | // The class is memory pools friendly. |
41 | // |
42 | // Usage |
43 | // |
44 | // POD key (integer), non-POD value (string): |
45 | // GenericMap<Pair<Right<int, string> > > |
46 | // |
47 | // non-POD key (string), POD value (integer): |
48 | // GenericMap<Pair<Left<string, int> > > |
49 | // |
50 | // non-POD key (string), non-POD value (string): |
51 | // GenericMap<Pair<Full<string, string> > > |
52 | // |
53 | template <typename KeyValuePair, typename KeyComparator = DefaultComparator<typename KeyValuePair::first_type> > |
54 | class GenericMap : public AutoStorage |
55 | { |
56 | public: |
57 | typedef typename KeyValuePair::first_type KeyType; |
58 | typedef typename KeyValuePair::second_type ValueType; |
59 | |
60 | typedef BePlusTree<KeyValuePair*, KeyType, MemoryPool, FirstObjectKey<KeyValuePair>, KeyComparator> ValuesTree; |
61 | typedef typename ValuesTree::Accessor TreeAccessor; |
62 | typedef typename ValuesTree::ConstAccessor ConstTreeAccessor; |
63 | |
64 | class Accessor |
65 | { |
66 | public: |
67 | explicit Accessor(GenericMap* map) : m_Accessor(&map->tree) {} |
68 | |
69 | KeyValuePair* current() const { return m_Accessor.current(); } |
70 | |
71 | bool getFirst() { return m_Accessor.getFirst(); } |
72 | bool getNext() { return m_Accessor.getNext(); } |
73 | |
74 | private: |
75 | Accessor(const Accessor&); |
76 | Accessor& operator=(const Accessor&); |
77 | |
78 | TreeAccessor m_Accessor; |
79 | }; |
80 | |
81 | class ConstAccessor |
82 | { |
83 | public: |
84 | explicit ConstAccessor(const GenericMap* map) : m_Accessor(&map->tree) {} |
85 | |
86 | const KeyValuePair* current() const { return m_Accessor.current(); } |
87 | |
88 | bool getFirst() { return m_Accessor.getFirst(); } |
89 | bool getNext() { return m_Accessor.getNext(); } |
90 | |
91 | private: |
92 | ConstAccessor(const ConstAccessor&); |
93 | ConstAccessor& operator=(const ConstAccessor&); |
94 | |
95 | ConstTreeAccessor m_Accessor; |
96 | }; |
97 | |
98 | friend class Accessor; |
99 | friend class ConstAccessor; |
100 | |
101 | GenericMap() : tree(&getPool()), mCount(0) { } |
102 | |
103 | explicit GenericMap(MemoryPool& a_pool) |
104 | : AutoStorage(a_pool), tree(&getPool()), mCount(0) |
105 | { } |
106 | |
107 | ~GenericMap() |
108 | { |
109 | clear(); |
110 | } |
111 | |
112 | void assign(GenericMap& v) |
113 | { |
114 | clear(); |
115 | |
116 | Accessor accessor(&v); |
117 | |
118 | for (bool found = accessor.getFirst(); found; found = accessor.getNext()) |
119 | { |
120 | const KeyValuePair* const current_pair = accessor.current(); |
121 | put(current_pair->first, current_pair->second); |
122 | } |
123 | } |
124 | |
125 | void takeOwnership(GenericMap& from) |
126 | { |
127 | fb_assert(this != &from); |
128 | |
129 | clear(); |
130 | |
131 | tree = from.tree; |
132 | mCount = from.mCount; |
133 | |
134 | TreeAccessor treeAccessor(&from.tree); |
135 | |
136 | if (treeAccessor.getFirst()) |
137 | { |
138 | while (true) |
139 | { |
140 | bool haveMore = treeAccessor.fastRemove(); |
141 | if (!haveMore) |
142 | break; |
143 | } |
144 | } |
145 | |
146 | from.mCount = 0; |
147 | } |
148 | |
149 | // Clear the map |
150 | void clear() |
151 | { |
152 | TreeAccessor treeAccessor(&tree); |
153 | |
154 | if (treeAccessor.getFirst()) |
155 | { |
156 | while (true) |
157 | { |
158 | KeyValuePair* temp = treeAccessor.current(); |
159 | bool haveMore = treeAccessor.fastRemove(); |
160 | delete temp; |
161 | if (!haveMore) |
162 | break; |
163 | } |
164 | } |
165 | |
166 | mCount = 0; |
167 | } |
168 | |
169 | // Returns true if value existed |
170 | bool remove(const KeyType& key) |
171 | { |
172 | TreeAccessor treeAccessor(&tree); |
173 | |
174 | if (treeAccessor.locate(key)) |
175 | { |
176 | KeyValuePair* var = treeAccessor.current(); |
177 | treeAccessor.fastRemove(); |
178 | delete var; |
179 | mCount--; |
180 | return true; |
181 | } |
182 | |
183 | return false; |
184 | } |
185 | |
186 | // Returns true if value existed previously |
187 | bool put(const KeyType& key, const ValueType& value) |
188 | { |
189 | TreeAccessor treeAccessor(&tree); |
190 | |
191 | if (treeAccessor.locate(key)) |
192 | { |
193 | treeAccessor.current()->second = value; |
194 | return true; |
195 | } |
196 | |
197 | KeyValuePair* var = FB_NEW(getPool()) KeyValuePair(getPool(), key, value); |
198 | tree.add(var); |
199 | mCount++; |
200 | return false; |
201 | } |
202 | |
203 | // Returns pointer to the added empty value or null when key already exists |
204 | ValueType* put(const KeyType& key) |
205 | { |
206 | TreeAccessor treeAccessor(&tree); |
207 | |
208 | if (treeAccessor.locate(key)) { |
209 | return NULL; |
210 | } |
211 | |
212 | KeyValuePair* var = FB_NEW(getPool()) KeyValuePair(getPool()); |
213 | var->first = key; |
214 | tree.add(var); |
215 | mCount++; |
216 | return &var->second; |
217 | } |
218 | |
219 | // Returns true if value is found |
220 | bool get(const KeyType& key, ValueType& value) |
221 | { |
222 | TreeAccessor treeAccessor(&tree); |
223 | |
224 | if (treeAccessor.locate(key)) |
225 | { |
226 | value = treeAccessor.current()->second; |
227 | return true; |
228 | } |
229 | |
230 | return false; |
231 | } |
232 | |
233 | // Returns pointer to the found value or null otherwise |
234 | ValueType* get(const KeyType& key) |
235 | { |
236 | TreeAccessor treeAccessor(&tree); |
237 | |
238 | if (treeAccessor.locate(key)) { |
239 | return &treeAccessor.current()->second; |
240 | } |
241 | |
242 | return NULL; |
243 | } |
244 | |
245 | bool exist(const KeyType& key) |
246 | { |
247 | return TreeAccessor(&tree).locate(key); |
248 | } |
249 | |
250 | size_t count() const { return mCount; } |
251 | |
252 | private: |
253 | ValuesTree tree; |
254 | size_t mCount; |
255 | }; |
256 | |
257 | typedef GenericMap<Pair<Full<string, string> > > StringMap; |
258 | |
259 | } |
260 | |
261 | #endif |
262 | |