Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
HashTable.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* HashTable.h (C) 2000-2023 */
9/* */
10/* Hash Table. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_UTILS_HASHTABLE_H
13#define ARCANE_UTILS_HASHTABLE_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#include "arcane/utils/MultiBuffer.h"
18#include "arcane/utils/Array.h"
19#include "arcane/utils/HashFunction.h"
20
21/*---------------------------------------------------------------------------*/
22/*---------------------------------------------------------------------------*/
23
24namespace Arcane
25{
26
27/*---------------------------------------------------------------------------*/
28/*---------------------------------------------------------------------------*/
29
36class ARCANE_UTILS_EXPORT HashTableBase
37{
38 public:
39
46 HashTableBase(Integer table_size, bool use_prime)
47 : m_count(0)
48 , m_nb_bucket(use_prime ? nearestPrimeNumber(table_size) : table_size)
49 {
50 }
51 virtual ~HashTableBase() {}
52
53 public:
54
60 Integer nearestPrimeNumber(Integer n);
61
62 public:
63
65 Integer count() const
66 {
67 return m_count;
68 }
69
70 protected:
71
72 void _throwNotFound ARCANE_NORETURN() const;
73
74 protected:
75
78};
79
80/*---------------------------------------------------------------------------*/
81/*---------------------------------------------------------------------------*/
98template <typename KeyType, typename TraitsType>
100: public HashTableBase
101{
102 public:
103
104 typedef typename TraitsType::KeyTypeConstRef KeyTypeConstRef;
105 typedef typename TraitsType::KeyTypeValue KeyTypeValue;
106
107 public:
108
109 struct HashData
110 {
111 public:
112
113 friend class HashTableBaseT<KeyType, TraitsType>;
114
115 public:
116
117 HashData()
118 : m_key(KeyType())
119 , m_next(0)
120 {}
121
122 public:
123
129 void changeKey(const KeyType& new_key)
130 {
131 m_key = new_key;
132 }
133
134 protected:
135
136 KeyTypeValue m_key;
137 HashData* m_next;
138 };
139
140 public:
141
148 HashTableBaseT(Integer table_size, bool use_prime)
149 : HashTableBase(table_size, use_prime)
150 , m_buckets(m_nb_bucket)
151 {
152 m_buckets.fill(0);
153 }
154
155 public:
156
158 bool hasKey(KeyTypeConstRef id) const
159 {
160 KeyType hf = _hash(id);
161 for (HashData* i = m_buckets[hf]; i; i = i->m_next) {
162 if (i->m_key == id)
163 return true;
164 }
165 return false;
166 }
167
169 void clear()
170 {
171 m_buckets.fill(0);
172 m_count = 0;
173 }
174
176 void resize(Integer new_table_size, bool use_prime = false)
177 {
178 m_nb_bucket = new_table_size;
179 if (new_table_size == 0) {
180 clear();
181 return;
182 }
183 if (use_prime)
184 new_table_size = nearestPrimeNumber(new_table_size);
185 //todo: remove the allocation of this array
186 UniqueArray<HashData*> old_buckets(m_buckets.clone());
187 m_buckets.resize(new_table_size);
188 m_buckets.fill(0);
189 for (Integer z = 0, zs = old_buckets.size(); z < zs; ++z) {
190 for (HashData* i = old_buckets[z]; i; i = i->m_next) {
191 _baseAdd(_hash(i->m_key), i->m_key, i);
192 }
193 }
194 }
195
197 void rehash()
198 {
199 //todo: remove the allocation of this array
200 UniqueArray<HashData*> old_buckets(m_buckets.clone());
201 m_buckets.fill(0);
202
203 for (Integer z = 0, zs = old_buckets.size(); z < zs; ++z) {
204 for (HashData* i = old_buckets[z]; i;) {
205 HashData* current = i;
206 i = i->m_next; // Must be done here, because i->m_next changes with _baseAdd
207 _baseAdd(_hash(current->m_key), current->m_key, current);
208 }
209 }
210 }
211
212 protected:
213
214 inline Integer _hash(KeyTypeConstRef id) const
215 {
216 return TraitsType::hashFunction(id) % m_nb_bucket;
217 }
218 inline HashData* _baseLookupBucket(Integer bucket, KeyTypeConstRef id) const
219 {
220 for (HashData* i = m_buckets[bucket]; i; i = i->m_next) {
221 if (i->m_key == id)
222 return i;
223 }
224 return 0;
225 }
226 inline HashData* _baseRemoveBucket(Integer bucket, KeyTypeConstRef id)
227 {
228 HashData* i = m_buckets[bucket];
229 if (i) {
230 if (i->m_key == id) {
231 m_buckets[bucket] = i->m_next;
232 --m_count;
233 return i;
234 }
235 for (; i->m_next; i = i->m_next) {
236 if (i->m_next->m_key == id) {
237 HashData* r = i->m_next;
238 i->m_next = i->m_next->m_next;
239 --m_count;
240 return r;
241 }
242 }
243 }
244 _throwNotFound();
245 }
246 inline HashData* _baseLookup(KeyTypeConstRef id) const
247 {
248 return _baseLookupBucket(_hash(id), id);
249 }
250 inline HashData* _baseRemove(KeyTypeConstRef id)
251 {
252 return _baseRemoveBucket(_hash(id), id);
253 }
254 inline void _baseAdd(Integer bucket, KeyTypeConstRef id, HashData* hd)
255 {
256 HashData* buck = m_buckets[bucket];
257 hd->m_key = id;
258 hd->m_next = buck;
259 m_buckets[bucket] = hd;
260 ++m_count;
261 }
262
263 protected:
264
265 UniqueArray<HashData*> m_buckets;
266};
267
268/*---------------------------------------------------------------------------*/
269/*---------------------------------------------------------------------------*/
270
271} // namespace Arcane
272
273/*---------------------------------------------------------------------------*/
274/*---------------------------------------------------------------------------*/
275
276#endif
Integer size() const
Number of elements in the vector.
void rehash()
Repositions data after key value change.
Definition HashTable.h:197
HashTableBaseT(Integer table_size, bool use_prime)
Creates a table of size table_size.
Definition HashTable.h:148
void resize(Integer new_table_size, bool use_prime=false)
Resizes the hash table.
Definition HashTable.h:176
bool hasKey(KeyTypeConstRef id) const
true if a value with the key id is present
Definition HashTable.h:158
void clear()
Clears all elements from the table.
Definition HashTable.h:169
Base class for a simple hash table for entities.
Definition HashTable.h:37
HashTableBase(Integer table_size, bool use_prime)
Creates a table of size table_size.
Definition HashTable.h:46
Integer m_nb_bucket
Number of buckets.
Definition HashTable.h:77
Integer nearestPrimeNumber(Integer n)
Returns the nearest prime number greater than n. The nearest prime number greater than n is returned ...
Definition HashTable.cc:57
Integer m_count
Number of elements.
Definition HashTable.h:76
Integer count() const
Number of elements in the table.
Definition HashTable.h:65
1D data vector with value semantics (STL style).
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Int32 Integer
Type representing an integer.
void changeKey(const KeyType &new_key)
Changes the key value.
Definition HashTable.h:129
KeyTypeValue m_key
Search key.
Definition HashTable.h:136