source: XMLIO_V2/external/include/Poco/SimpleHashTable.h @ 80

Last change on this file since 80 was 80, checked in by ymipsl, 14 years ago

ajout lib externe

  • Property svn:eol-style set to native
File size: 9.8 KB
Line 
1//
2// SimpleHashTable.h
3//
4// $Id: //poco/1.3/Foundation/include/Poco/SimpleHashTable.h#2 $
5//
6// Library: Foundation
7// Package: Hashing
8// Module:  SimpleHashTable
9//
10// Definition of the SimpleHashTable class.
11//
12// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
13// and Contributors.
14//
15// Permission is hereby granted, free of charge, to any person or organization
16// obtaining a copy of the software and accompanying documentation covered by
17// this license (the "Software") to use, reproduce, display, distribute,
18// execute, and transmit the Software, and to prepare derivative works of the
19// Software, and to permit third-parties to whom the Software is furnished to
20// do so, all subject to the following:
21//
22// The copyright notices in the Software and this entire statement, including
23// the above license grant, this restriction and the following disclaimer,
24// must be included in all copies of the Software, in whole or in part, and
25// all derivative works of the Software, unless such copies or derivative
26// works are solely in the form of machine-executable object code generated by
27// a source language processor.
28//
29// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
32// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
33// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
34// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
35// DEALINGS IN THE SOFTWARE.
36//
37
38
39#ifndef Foundation_SimpleHashTable_INCLUDED
40#define Foundation_SimpleHashTable_INCLUDED
41
42
43#include "Poco/Foundation.h"
44#include "Poco/Exception.h"
45#include "Poco/HashFunction.h"
46#include "Poco/HashStatistic.h"
47#include <vector>
48#include <map>
49#include <cstddef>
50#include <algorithm>
51
52
53namespace Poco {
54
55
56//@ deprecated
57template <class Key, class Value, class KeyHashFunction = HashFunction<Key> >
58class SimpleHashTable
59        /// A SimpleHashTable stores a key value pair that can be looked up via a hashed key.
60        ///
61        /// In comparision to a HashTable, this class handles collisions by sequentially searching the next
62        /// free location. This also means that the maximum size of this table is limited, i.e. if the hash table
63        /// is full, it will throw an exception and that this class does not support remove operations.
64        /// On the plus side it is faster than the HashTable.
65        ///
66        /// This class is NOT thread safe.
67{
68public:
69        class HashEntry
70        {
71        public:
72                Key   key;
73                Value value;
74                HashEntry(const Key k, const Value v): key(k), value(v)
75                {
76                }
77        };
78
79        typedef std::vector<HashEntry*> HashTableVector;
80
81        SimpleHashTable(UInt32 capacity = 251): _entries(capacity, 0), _size(0), _capacity(capacity)
82                /// Creates the SimpleHashTable.
83        {
84        }
85
86        SimpleHashTable(const SimpleHashTable& ht):
87                _size(ht._size),
88                _capacity(ht._capacity)
89        {
90                _entries.reserve(ht._capacity);
91                for (typename HashTableVector::iterator it = ht._entries.begin(); it != ht._entries.end(); ++it)
92                {
93                        if (*it) 
94                                _entries.push_back(new HashEntry(*it));
95                        else
96                                _entries.push_back(0);
97                }
98        }
99
100        ~SimpleHashTable()
101                /// Destroys the SimpleHashTable.
102        {
103                clear();
104        }
105
106        SimpleHashTable& operator = (const SimpleHashTable& ht)
107        {
108                if (this != &ht)
109                {
110                        SimpleHashTable tmp(ht);
111                        swap(tmp);
112                }
113                return *this;
114        }
115       
116        void swap(SimpleHashTable& ht)
117        {
118                using std::swap;
119                swap(_entries, ht._entries);
120                swap(_size, ht._size);
121                swap(_capacity, ht._capacity);
122        }
123
124        void clear()
125        {
126                for (typename HashTableVector::iterator it = _entries.begin(); it != _entries.end(); ++it)
127                {
128                        delete *it;
129                        *it = 0;
130                }
131                _size = 0;
132        }
133
134        UInt32 insert(const Key& key, const Value& value)
135                /// Returns the hash value of the inserted item.
136                /// Throws an exception if the entry was already inserted
137        {
138                UInt32 hsh = hash(key);
139                insertRaw(key, hsh, value);
140                return hsh;
141        }
142
143        Value& insertRaw(const Key& key, UInt32 hsh, const Value& value)
144                /// Returns the hash value of the inserted item.
145                /// Throws an exception if the entry was already inserted
146        {
147                UInt32 pos = hsh;
148                if (!_entries[pos])
149                        _entries[pos] = new HashEntry(key, value);
150                else
151                {
152                        UInt32 origHash = hsh;
153                        while (_entries[hsh % _capacity])
154                        {
155                                if (_entries[hsh % _capacity]->key == key)
156                                        throw ExistsException();
157                                if (hsh - origHash > _capacity)
158                                        throw PoolOverflowException("SimpleHashTable full");
159                                hsh++;
160                        }
161                        pos = hsh % _capacity;
162                        _entries[pos] = new HashEntry(key, value);
163                }
164                _size++;
165                return _entries[pos]->value;
166        }
167
168        UInt32 update(const Key& key, const Value& value)
169                /// Returns the hash value of the inserted item.
170                /// Replaces an existing entry if it finds one
171        {
172                UInt32 hsh = hash(key);
173                updateRaw(key, hsh, value);
174                return hsh;
175        }
176
177        void updateRaw(const Key& key, UInt32 hsh, const Value& value)
178                /// Returns the hash value of the inserted item.
179                /// Replaces an existing entry if it finds one
180        {
181                if (!_entries[hsh])
182                        _entries[hsh] = new HashEntry(key, value);
183                else
184                {
185                        UInt32 origHash = hsh;
186                        while (_entries[hsh % _capacity])
187                        {
188                                if (_entries[hsh % _capacity]->key == key)
189                                {
190                                        _entries[hsh % _capacity]->value = value;
191                                        return;
192                                }
193                                if (hsh - origHash > _capacity)
194                                        throw PoolOverflowException("SimpleHashTable full");
195                                hsh++;
196                        }
197                        _entries[hsh % _capacity] = new HashEntry(key, value);
198                }
199                _size++;
200        }
201
202        UInt32 hash(const Key& key) const
203        {
204                return _hash(key, _capacity);
205        }
206
207        const Value& get(const Key& key) const
208                /// Throws an exception if the value does not exist
209        {
210                UInt32 hsh = hash(key);
211                return getRaw(key, hsh);
212        }
213
214        const Value& getRaw(const Key& key, UInt32 hsh) const
215                /// Throws an exception if the value does not exist
216        {
217                UInt32 origHash = hsh;
218                while (true)
219                {
220                        if (_entries[hsh % _capacity])
221                        {
222                                if (_entries[hsh % _capacity]->key == key)
223                                {
224                                        return _entries[hsh % _capacity]->value;
225                                }
226                        }
227                        else
228                                throw InvalidArgumentException("value not found");
229                        if (hsh - origHash > _capacity)
230                                throw InvalidArgumentException("value not found");
231                        hsh++;
232                }
233        }
234
235        Value& get(const Key& key)
236                /// Throws an exception if the value does not exist
237        {
238                UInt32 hsh = hash(key);
239                return const_cast<Value&>(getRaw(key, hsh));
240        }
241       
242        const Value& operator [] (const Key& key) const
243        {
244                return get(key);
245        }
246       
247        Value& operator [] (const Key& key)
248        {
249                UInt32 hsh = hash(key);
250                UInt32 origHash = hsh;
251                while (true)
252                {
253                        if (_entries[hsh % _capacity])
254                        {
255                                if (_entries[hsh % _capacity]->key == key)
256                                {
257                                        return _entries[hsh % _capacity]->value;
258                                }
259                        }
260                        else return insertRaw(key, hsh, Value());
261                        if (hsh - origHash > _capacity)
262                                return insertRaw(key, hsh, Value());
263                        hsh++;
264                }
265        }
266
267        const Key& getKeyRaw(const Key& key, UInt32 hsh)
268                /// Throws an exception if the key does not exist. returns a reference to the internally
269                /// stored key. Useful when someone does an insert and wants for performance reason only to store
270                /// a pointer to the key in another collection
271        {
272                UInt32 origHash = hsh;
273                while (true)
274                {
275                        if (_entries[hsh % _capacity])
276                        {
277                                if (_entries[hsh % _capacity]->key == key)
278                                {
279                                        return _entries[hsh % _capacity]->key;
280                                }
281                        }
282                        else
283                                throw InvalidArgumentException("key not found");
284
285                        if (hsh - origHash > _capacity)
286                                throw InvalidArgumentException("key not found");
287                        hsh++;
288                }
289        }
290
291        bool get(const Key& key, Value& v) const
292                /// Sets v to the found value, returns false if no value was found
293        {
294                UInt32 hsh = hash(key);
295                return getRaw(key, hsh, v);
296        }
297
298        bool getRaw(const Key& key, UInt32 hsh, Value& v) const
299                /// Sets v to the found value, returns false if no value was found
300        {
301                UInt32 origHash = hsh;
302                while (true)
303                {
304                        if (_entries[hsh % _capacity])
305                        {
306                                if (_entries[hsh % _capacity]->key == key)
307                                {
308                                        v = _entries[hsh % _capacity]->value;
309                                        return true;
310                                }
311                        }
312                        else
313                                return false;
314                        if (hsh - origHash > _capacity)
315                                return false;
316                        hsh++;
317                }
318        }
319
320        bool exists(const Key& key) const
321        {
322                UInt32 hsh = hash(key);
323                return existsRaw(key, hsh);
324        }
325
326        bool existsRaw(const Key& key, UInt32 hsh) const
327        {
328                UInt32 origHash = hsh;
329                while (true)
330                {
331                        if (_entries[hsh % _capacity])
332                        {
333                                if (_entries[hsh % _capacity]->key == key)
334                                {
335                                        return true;
336                                }
337                        }
338                        else
339                                return false;
340                        if (hsh - origHash > _capacity)
341                                return false;
342                        hsh++;
343                }
344        }
345
346        std::size_t size() const
347                /// Returns the number of elements already inserted into the SimpleHashTable
348        {
349                return _size;
350        }
351       
352        UInt32 capacity() const
353        {
354                return _capacity;
355        }
356
357        void resize(UInt32 newSize)
358                /// Resizes the hashtable, rehashes all existing entries. Expensive!
359        {
360                if (_capacity != newSize)
361                {
362                        SimpleHashTable tmp(newSize);
363                        swap(tmp);
364                        for (typename HashTableVector::const_iterator it = tmp._entries.begin(); it != tmp._entries.end(); ++it)
365                        {
366                                if (*it)
367                                {
368                                        insertRaw((*it)->key, hash((*it)->key), (*it)->value);
369                                }
370                        }
371                }
372        }
373
374        HashStatistic currentState(bool details = false) const
375                /// Returns the current internal state
376        {
377                UInt32 numberOfEntries = (UInt32)_size;
378                UInt32 numZeroEntries = 0;
379                UInt32 maxEntriesPerHash = 0;
380                std::vector<UInt32> detailedEntriesPerHash;
381        #ifdef _DEBUG
382                UInt32 totalSize = 0;
383        #endif
384                for (int i=0; i < _capacity; ++i)
385                {
386                        if (_entries[i])
387                        {
388                                maxEntriesPerHash = 1;
389                                UInt32 size = 1;
390                                if (details)
391                                        detailedEntriesPerHash.push_back(size);
392        #ifdef DEBUG
393                                totalSize += size;
394        #endif
395                        }
396                        else
397                        {
398                                numZeroEntries++;
399                                if (details)
400                                        detailedEntriesPerHash.push_back(0);
401                        }
402                }
403                poco_assert_dbg(totalSize == numberOfEntries);
404
405                return HashStatistic(_capacity, numberOfEntries, numZeroEntries, maxEntriesPerHash, detailedEntriesPerHash);
406        }
407
408private:
409        HashTableVector _entries;
410        std::size_t     _size;
411        UInt32          _capacity;
412        KeyHashFunction _hash;
413};
414
415
416} // namespace Poco
417
418
419#endif // Foundation_HashTable_INCLUDED
Note: See TracBrowser for help on using the repository browser.