source: XMLIO_V2/external/src/POCO/Foundation.save/Poco/HashTable.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// HashTable.h
3//
4// $Id: //poco/1.3/Foundation/include/Poco/HashTable.h#5 $
5//
6// Library: Foundation
7// Package: Hashing
8// Module:  HashTable
9//
10// Definition of the HashTable 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_HashTable_INCLUDED
40#define Foundation_HashTable_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 <cstring>
51
52
53namespace Poco {
54
55
56//@ deprecated
57template <class Key, class Value, class KeyHashFunction = HashFunction<Key> >
58class HashTable
59        /// A HashTable stores a key value pair that can be looked up via a hashed key.
60        ///
61        /// Collision handling is done via overflow maps(!). With small hash tables performance of this
62        /// data struct will be closer to that a map than a hash table, i.e. slower. On the plus side,
63        /// this class offers remove operations. Also HashTable full errors are not possible. If a fast
64        /// HashTable implementation is needed and the remove operation is not required, use SimpleHashTable
65        /// instead.
66        ///
67        /// This class is NOT thread safe.
68{
69public:
70        typedef std::map<Key, Value> HashEntryMap;
71        typedef HashEntryMap**       HashTableVector;
72
73        typedef typename HashEntryMap::const_iterator ConstIterator;
74        typedef typename HashEntryMap::iterator Iterator;
75
76        HashTable(UInt32 initialSize = 251): 
77                _entries(0), 
78                _size(0), 
79                _maxCapacity(initialSize)
80                /// Creates the HashTable.
81        {
82                _entries = new HashEntryMap*[initialSize];
83                memset(_entries, '\0', sizeof(HashEntryMap*)*initialSize);
84        }
85
86        HashTable(const HashTable& ht):
87                _entries(new HashEntryMap*[ht._maxCapacity]),
88                _size(ht._size),
89                _maxCapacity(ht._maxCapacity)
90        {
91                for (UInt32 i = 0; i < _maxCapacity; ++i)
92                {
93                        if (ht._entries[i])
94                                _entries[i] = new HashEntryMap(ht._entries[i]->begin(), ht._entries[i]->end());
95                        else
96                                _entries[i] = 0;
97                }
98        }
99
100        ~HashTable()
101                /// Destroys the HashTable.
102        {
103                clear();
104        }
105
106        HashTable& operator = (const HashTable& ht)
107        {
108                if (this != &ht)
109                {
110                        clear();
111                        _maxCapacity = ht._maxCapacity;
112                        poco_assert_dbg (_entries == 0);
113                        _entries = new HashEntryMap*[_maxCapacity];
114                        _size = ht._size;
115
116                        for (UInt32 i = 0; i < _maxCapacity; ++i)
117                        {
118                                if (ht._entries[i])
119                                        _entries[i] = new HashEntryMap(ht._entries[i]->begin(), ht._entries[i]->end());
120                                else
121                                        _entries[i] = 0;
122                        }
123                }
124                return *this;
125        }
126
127        void clear()
128        {
129                if (!_entries)
130                        return;
131                for (UInt32 i = 0; i < _maxCapacity; ++i)
132                {
133                        if (_entries[i])
134                                delete _entries[i];
135                }
136                delete[] _entries;
137                _entries     = 0;
138                _size        = 0;
139                _maxCapacity = 0;
140        }
141
142        UInt32 insert(const Key& key, const Value& value)
143                /// Returns the hash value of the inserted item.
144                /// Throws an exception if the entry was already inserted
145        {
146                UInt32 hsh = hash(key);
147                insertRaw(key, hsh, value);
148                return hsh;
149        }
150
151        Value& insertRaw(const Key& key, UInt32 hsh, const Value& value)
152                /// Returns the hash value of the inserted item.
153                /// Throws an exception if the entry was already inserted
154        {
155                if (!_entries[hsh])
156                        _entries[hsh] = new HashEntryMap();
157                std::pair<typename HashEntryMap::iterator, bool> res(_entries[hsh]->insert(std::make_pair(key, value)));
158                if (!res.second)
159                        throw InvalidArgumentException("HashTable::insert, key already exists.");
160                _size++;
161                return res.first->second;
162        }
163
164        UInt32 update(const Key& key, const Value& value)
165                /// Returns the hash value of the inserted item.
166                /// Replaces an existing entry if it finds one
167        {
168                UInt32 hsh = hash(key);
169                updateRaw(key, hsh, value);
170                return hsh;
171        }
172
173        void updateRaw(const Key& key, UInt32 hsh, const Value& value)
174                /// Returns the hash value of the inserted item.
175                /// Replaces an existing entry if it finds one
176        {
177                if (!_entries[hsh])
178                        _entries[hsh] = new HashEntryMap();
179                std::pair<Iterator, bool> res = _entries[hsh]->insert(std::make_pair(key, value));
180                if (res.second == false)
181                        res.first->second = value;
182                else
183                        _size++;
184        }
185
186        void remove(const Key& key)
187        {
188                UInt32 hsh = hash(key);
189                removeRaw(key, hsh);
190        }
191
192        void removeRaw(const Key& key, UInt32 hsh)
193                /// Performance version, allows to specify the hash value
194        {
195                if (_entries[hsh])
196                {
197                        _size -= _entries[hsh]->erase(key);
198                }
199        }
200
201        UInt32 hash(const Key& key) const
202        {
203                return _hash(key, _maxCapacity);
204        }
205
206        const Value& get(const Key& key) const
207                /// Throws an exception if the value does not exist
208        {
209                UInt32 hsh = hash(key);
210                return getRaw(key, hsh);
211        }
212
213        const Value& getRaw(const Key& key, UInt32 hsh) const
214                /// Throws an exception if the value does not exist
215        {
216                if (!_entries[hsh])
217                        throw InvalidArgumentException("key not found");
218
219                ConstIterator it = _entries[hsh]->find(key);
220                if (it == _entries[hsh]->end())
221                        throw InvalidArgumentException("key not found");
222
223                return it->second;
224        }
225
226        Value& get(const Key& key)
227                /// Throws an exception if the value does not exist
228        {
229                UInt32 hsh = hash(key);
230                return const_cast<Value&>(getRaw(key, hsh));
231        }
232
233        const Value& operator [] (const Key& key) const
234        {
235                return get(key);
236        }
237       
238        Value& operator [] (const Key& key)
239        {
240                UInt32 hsh = hash(key);
241
242                if (!_entries[hsh])
243                        return insertRaw(key, hsh, Value());
244                       
245                ConstIterator it = _entries[hsh]->find(key);
246                if (it == _entries[hsh]->end())
247                        return insertRaw(key, hsh, Value());
248
249                return it->second;
250        }
251       
252        const Key& getKeyRaw(const Key& key, UInt32 hsh)
253                /// Throws an exception if the key does not exist. returns a reference to the internally
254                /// stored key. Useful when someone does an insert and wants for performance reason only to store
255                /// a pointer to the key in another collection
256        {
257                if (!_entries[hsh])
258                        throw InvalidArgumentException("key not found");
259                ConstIterator it = _entries[hsh]->find(key);
260                if (it == _entries[hsh]->end())
261                        throw InvalidArgumentException("key not found");
262                return it->first;
263        }
264
265        bool get(const Key& key, Value& v) const
266                /// Sets v to the found value, returns false if no value was found
267        {
268                UInt32 hsh = hash(key);
269                return getRaw(key, hsh, v);
270        }
271
272        bool getRaw(const Key& key, UInt32 hsh, Value& v) const
273                /// Sets v to the found value, returns false if no value was found
274        {
275                if (!_entries[hsh])
276                        return false;
277
278                ConstIterator it = _entries[hsh]->find(key);
279                if (it == _entries[hsh]->end())
280                        return false;
281
282                v = it->second;
283                return true;
284        }
285
286        bool exists(const Key& key)
287        {
288                UInt32 hsh = hash(key);
289                return existsRaw(key, hsh);
290        }
291
292        bool existsRaw(const Key& key, UInt32 hsh)
293        {
294                return _entries[hsh] && (_entries[hsh]->end() != _entries[hsh]->find(key));
295        }
296
297        std::size_t size() const
298                /// Returns the number of elements already inserted into the HashTable
299        {
300                return _size;
301        }
302       
303        UInt32 maxCapacity() const
304        {
305                return _maxCapacity;
306        }
307
308        void resize(UInt32 newSize)
309                /// Resizes the hashtable, rehashes all existing entries. Expensive!
310        {
311                if (_maxCapacity != newSize)
312                {
313                        HashTableVector cpy = _entries;
314                        _entries = 0;
315                        UInt32 oldSize = _maxCapacity;
316                        _maxCapacity = newSize;
317                        _entries = new HashEntryMap*[_maxCapacity];
318                        memset(_entries, '\0', sizeof(HashEntryMap*)*_maxCapacity);
319
320                        if (_size == 0)
321                        {
322                                // no data was yet inserted
323                                delete[] cpy;
324                                return;
325                        }
326                        _size = 0;
327                        for (UInt32 i = 0; i < oldSize; ++i)
328                        {
329                                if (cpy[i])
330                                {
331                                        ConstIterator it = cpy[i]->begin();
332                                        ConstIterator itEnd = cpy[i]->end();
333                                        for (; it != itEnd; ++it)
334                                        {
335                                                insert(it->first, it->second);
336                                        }
337                                        delete cpy[i];
338                                }
339                        }
340                        delete[] cpy;
341                }
342        }
343
344        HashStatistic currentState(bool details = false) const
345                /// Returns the current internal state
346        {
347                UInt32 numberOfEntries = (UInt32)_size;
348                UInt32 numZeroEntries = 0;
349                UInt32 maxEntriesPerHash = 0;
350                std::vector<UInt32> detailedEntriesPerHash;
351        #ifdef DEBUG
352                UInt32 totalSize = 0;
353        #endif
354                for (UInt32 i = 0; i < _maxCapacity; ++i)
355                {
356                        if (_entries[i])
357                        {
358                                UInt32 size = (UInt32)_entries[i]->size();
359                                poco_assert_dbg(size != 0);
360                                if (size > maxEntriesPerHash)
361                                        maxEntriesPerHash = size;
362                                if (details)
363                                        detailedEntriesPerHash.push_back(size);
364        #ifdef DEBUG
365                                totalSize += size;
366        #endif
367                        }
368                        else
369                        {
370                                numZeroEntries++;
371                                if (details)
372                                        detailedEntriesPerHash.push_back(0);
373                        }
374                }
375        #ifdef DEBUG
376                poco_assert_dbg(totalSize == numberOfEntries);
377        #endif
378                return HashStatistic(_maxCapacity, numberOfEntries, numZeroEntries, maxEntriesPerHash, detailedEntriesPerHash);
379        }
380
381private:
382        HashTableVector _entries;
383        std::size_t     _size;
384        UInt32          _maxCapacity;
385        KeyHashFunction _hash;
386};
387
388
389} // namespace Poco
390
391
392#endif // Foundation_HashTable_INCLUDED
Note: See TracBrowser for help on using the repository browser.