btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / headers / private / userlandfs / shared / HashMap.h
blob4a3495afc0a5bed9397af2b6d5988f32616922c3
1 /*
2 * Copyright 2004-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5 #ifndef HASH_MAP_H
6 #define HASH_MAP_H
8 //#include <Debug.h>
10 #include <util/OpenHashTable.h>
12 #include "AutoLocker.h"
13 #include "Locker.h"
16 // HashMapElement
17 template<typename Key, typename Value>
18 class HashMapElement {
19 private:
20 typedef HashMapElement<Key, Value> Element;
22 public:
23 HashMapElement()
25 fKey(),
26 fValue()
30 HashMapElement(const Key& key, const Value& value)
32 fKey(key),
33 fValue(value)
37 Key fKey;
38 Value fValue;
39 HashMapElement* fNext;
43 // HashMapTableDefinition
44 template<typename Key, typename Value>
45 struct HashMapTableDefinition {
46 typedef Key KeyType;
47 typedef HashMapElement<Key, Value> ValueType;
49 size_t HashKey(const KeyType& key) const
50 { return key.GetHashCode(); }
51 size_t Hash(const ValueType* value) const
52 { return HashKey(value->fKey); }
53 bool Compare(const KeyType& key, const ValueType* value) const
54 { return value->fKey == key; }
55 ValueType*& GetLink(ValueType* value) const
56 { return value->fNext; }
60 // HashMap
61 template<typename Key, typename Value>
62 class HashMap {
63 public:
64 class Entry {
65 public:
66 Entry() {}
67 Entry(const Key& key, Value value) : key(key), value(value) {}
69 Key key;
70 Value value;
73 class Iterator {
74 private:
75 typedef HashMapElement<Key, Value> Element;
76 public:
77 Iterator(const Iterator& other)
79 fMap(other.fMap),
80 fIterator(other.fIterator),
81 fElement(other.fElement)
85 bool HasNext() const
87 return fIterator.HasNext();
90 Entry Next()
92 fElement = fIterator.Next();
93 if (fElement == NULL)
94 return Entry();
96 return Entry(fElement->fKey, fElement->fValue);
99 Entry Remove()
101 if (fElement == NULL)
102 return Entry();
104 Entry result(fElement->fKey, fElement->fValue);
106 fMap->fTable.RemoveUnchecked(fElement);
107 delete fElement;
108 fElement = NULL;
110 return result;
113 Iterator& operator=(const Iterator& other)
115 fMap = other.fMap;
116 fIterator = other.fIterator;
117 fElement = other.fElement;
118 return *this;
121 private:
122 Iterator(HashMap<Key, Value>* map)
124 fMap(map),
125 fIterator(map->fTable.GetIterator()),
126 fElement(NULL)
130 private:
131 friend class HashMap<Key, Value>;
132 typedef BOpenHashTable<HashMapTableDefinition<Key, Value> >
133 ElementTable;
135 HashMap<Key, Value>* fMap;
136 typename ElementTable::Iterator fIterator;
137 Element* fElement;
140 HashMap();
141 ~HashMap();
143 status_t InitCheck() const;
145 status_t Put(const Key& key, const Value& value);
146 Value Remove(const Key& key);
147 void Clear();
148 Value Get(const Key& key) const;
150 bool ContainsKey(const Key& key) const;
152 int32 Size() const;
154 Iterator GetIterator();
156 protected:
157 typedef BOpenHashTable<HashMapTableDefinition<Key, Value> > ElementTable;
158 typedef HashMapElement<Key, Value> Element;
159 friend class Iterator;
161 protected:
162 ElementTable fTable;
166 // SynchronizedHashMap
167 template<typename Key, typename Value>
168 class SynchronizedHashMap : public Locker {
169 public:
170 typedef typename HashMap<Key, Value>::Entry Entry;
171 typedef typename HashMap<Key, Value>::Iterator Iterator;
173 SynchronizedHashMap() : Locker("synchronized hash map") {}
174 ~SynchronizedHashMap() { Lock(); }
176 status_t InitCheck() const
178 return fMap.InitCheck();
181 status_t Put(const Key& key, const Value& value)
183 MapLocker locker(this);
184 if (!locker.IsLocked())
185 return B_ERROR;
186 return fMap.Put(key, value);
189 Value Remove(const Key& key)
191 MapLocker locker(this);
192 if (!locker.IsLocked())
193 return Value();
194 return fMap.Remove(key);
197 void Clear()
199 MapLocker locker(this);
200 return fMap.Clear();
203 Value Get(const Key& key) const
205 const Locker* lock = this;
206 MapLocker locker(const_cast<Locker*>(lock));
207 if (!locker.IsLocked())
208 return Value();
209 return fMap.Get(key);
212 bool ContainsKey(const Key& key) const
214 const Locker* lock = this;
215 MapLocker locker(const_cast<Locker*>(lock));
216 if (!locker.IsLocked())
217 return false;
218 return fMap.ContainsKey(key);
221 int32 Size() const
223 const Locker* lock = this;
224 MapLocker locker(const_cast<Locker*>(lock));
225 return fMap.Size();
228 Iterator GetIterator()
230 return fMap.GetIterator();
233 // for debugging only
234 const HashMap<Key, Value>& GetUnsynchronizedMap() const { return fMap; }
235 HashMap<Key, Value>& GetUnsynchronizedMap() { return fMap; }
237 protected:
238 typedef AutoLocker<Locker> MapLocker;
240 HashMap<Key, Value> fMap;
243 // HashKey32
244 template<typename Value>
245 struct HashKey32 {
246 HashKey32() {}
247 HashKey32(const Value& value) : value(value) {}
249 uint32 GetHashCode() const
251 return (uint32)value;
254 HashKey32<Value> operator=(const HashKey32<Value>& other)
256 value = other.value;
257 return *this;
260 bool operator==(const HashKey32<Value>& other) const
262 return (value == other.value);
265 bool operator!=(const HashKey32<Value>& other) const
267 return (value != other.value);
270 Value value;
274 // HashKey64
275 template<typename Value>
276 struct HashKey64 {
277 HashKey64() {}
278 HashKey64(const Value& value) : value(value) {}
280 uint32 GetHashCode() const
282 uint64 v = (uint64)value;
283 return (uint32)(v >> 32) ^ (uint32)v;
286 HashKey64<Value> operator=(const HashKey64<Value>& other)
288 value = other.value;
289 return *this;
292 bool operator==(const HashKey64<Value>& other) const
294 return (value == other.value);
297 bool operator!=(const HashKey64<Value>& other) const
299 return (value != other.value);
302 Value value;
306 // HashKeyPointer
307 template<typename Value>
308 struct HashKeyPointer {
309 HashKeyPointer() {}
310 HashKeyPointer(const Value& value) : value(value) {}
312 uint32 GetHashCode() const
314 #if __HAIKU_ARCH_BITS == 32
315 return (uint32)(addr_t)value;
316 #elif __HAIKU_ARCH_BITS == 64
317 uint64 v = (uint64)(addr_t)value;
318 return (uint32)(v >> 32) ^ (uint32)v;
319 #else
320 #error unknown bitness
321 #endif
324 HashKeyPointer<Value> operator=(const HashKeyPointer<Value>& other)
326 value = other.value;
327 return *this;
330 bool operator==(const HashKeyPointer<Value>& other) const
332 return (value == other.value);
335 bool operator!=(const HashKeyPointer<Value>& other) const
337 return (value != other.value);
340 Value value;
344 // HashMap
346 // constructor
347 template<typename Key, typename Value>
348 HashMap<Key, Value>::HashMap()
350 fTable()
352 fTable.Init();
356 // destructor
357 template<typename Key, typename Value>
358 HashMap<Key, Value>::~HashMap()
360 Clear();
364 // InitCheck
365 template<typename Key, typename Value>
366 status_t
367 HashMap<Key, Value>::InitCheck() const
369 return (fTable.TableSize() > 0 ? B_OK : B_NO_MEMORY);
373 // Put
374 template<typename Key, typename Value>
375 status_t
376 HashMap<Key, Value>::Put(const Key& key, const Value& value)
378 Element* element = fTable.Lookup(key);
379 if (element) {
380 // already contains the key: just set the new value
381 element->fValue = value;
382 return B_OK;
385 // does not contain the key yet: create an element and add it
386 element = new(std::nothrow) Element(key, value);
387 if (!element)
388 return B_NO_MEMORY;
390 status_t error = fTable.Insert(element);
391 if (error != B_OK)
392 delete element;
394 return error;
398 // Remove
399 template<typename Key, typename Value>
400 Value
401 HashMap<Key, Value>::Remove(const Key& key)
403 Element* element = fTable.Lookup(key);
404 if (element == NULL)
405 return Value();
407 fTable.Remove(element);
408 Value value = element->fValue;
409 delete element;
411 return value;
415 // Clear
416 template<typename Key, typename Value>
417 void
418 HashMap<Key, Value>::Clear()
420 // clear the table and delete the elements
421 Element* element = fTable.Clear(true);
422 while (element != NULL) {
423 Element* next = element->fNext;
424 delete element;
425 element = next;
430 // Get
431 template<typename Key, typename Value>
432 Value
433 HashMap<Key, Value>::Get(const Key& key) const
435 if (Element* element = fTable.Lookup(key))
436 return element->fValue;
437 return Value();
441 // ContainsKey
442 template<typename Key, typename Value>
443 bool
444 HashMap<Key, Value>::ContainsKey(const Key& key) const
446 return fTable.Lookup(key) != NULL;
450 // Size
451 template<typename Key, typename Value>
452 int32
453 HashMap<Key, Value>::Size() const
455 return fTable.CountElements();
459 // GetIterator
460 template<typename Key, typename Value>
461 typename HashMap<Key, Value>::Iterator
462 HashMap<Key, Value>::GetIterator()
464 return Iterator(this);
468 #endif // HASH_MAP_H