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
36namespace 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//
53template <typename KeyValuePair, typename KeyComparator = DefaultComparator<typename KeyValuePair::first_type> >
54class GenericMap : public AutoStorage
55{
56public:
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
252private:
253 ValuesTree tree;
254 size_t mCount;
255};
256
257typedef GenericMap<Pair<Full<string, string> > > StringMap;
258
259}
260
261#endif
262