Objectively
Ultra-lightweight object oriented framework for GNU C.
Loading...
Searching...
No Matches
HashTable.c File Reference
#include "Config.h"
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "Hash.h"
#include "HashTable.h"

Go to the source code of this file.

Macros

#define _Class   _HashTable
 
#define HASHTABLE_DEFAULT_CAPACITY   16
 
#define HASHTABLE_GROW_FACTOR   2
 
#define HASHTABLE_MAX_LOAD   0.75f
 

Functions

Class_HashTable (void)
 
static void _remove (HashTable *self, const ident key)
 
static bool containsKey (const HashTable *self, const ident key)
 
static void dealloc (Object *self)
 
static void enumerate (const HashTable *self, HashTableEnumerator enumerator, ident data)
 
static ident get (const HashTable *self, const ident key)
 
bool HashTableEqualDirect (const ident a, const ident b)
 
bool HashTableEqualStr (const ident a, const ident b)
 
bool HashTableEqualStri (const ident a, const ident b)
 
size_t HashTableHashDirect (const ident key)
 
size_t HashTableHashStr (const ident key)
 Common hash functions for use with HashTable.
 
size_t HashTableHashStri (const ident key)
 
static HashTableinit (HashTable *self, HashTableHashFunc hash, HashTableEqualFunc equal)
 
static void initialize (Class *clazz)
 
static HashTableinitWithCapacity (HashTable *self, HashTableHashFunc hash, HashTableEqualFunc equal, size_t capacity)
 
static void removeAll (HashTable *self)
 
static void resize (HashTable *self, size_t capacity)
 Rehashes all entries into a new bucket array of the given capacity.
 
static void set (HashTable *self, const ident key, const ident value)
 

Macro Definition Documentation

◆ _Class

#define _Class   _HashTable

Definition at line 34 of file HashTable.c.

◆ HASHTABLE_DEFAULT_CAPACITY

#define HASHTABLE_DEFAULT_CAPACITY   16

Definition at line 36 of file HashTable.c.

◆ HASHTABLE_GROW_FACTOR

#define HASHTABLE_GROW_FACTOR   2

Definition at line 37 of file HashTable.c.

◆ HASHTABLE_MAX_LOAD

#define HASHTABLE_MAX_LOAD   0.75f

Definition at line 38 of file HashTable.c.

Function Documentation

◆ _HashTable()

Class * _HashTable ( void  )

Definition at line 328 of file HashTable.c.

328 {
329 static Class *clazz;
330 static Once once;
331
332 do_once(&once, {
333 clazz = _initialize(&(const ClassDef) {
334 .name = "HashTable",
335 .superclass = _Object(),
336 .instanceSize = sizeof(HashTable),
337 .interfaceOffset = offsetof(HashTable, interface),
338 .interfaceSize = sizeof(HashTableInterface),
340 });
341 });
342
343 return clazz;
344}
Class * _initialize(const ClassDef *def)
Initializes the given Class.
Definition Class.c:86
static void initialize(Class *clazz)
Definition HashTable.c:310
Class * _Object(void)
Definition Object.c:136
long Once
The Once type.
Definition Once.h:37
#define do_once(once, block)
Executes the given block at most one time.
Definition Once.h:43
ClassDefs are passed to _initialize via an archetype to initialize a Class.
Definition Class.h:41
The runtime representation of a Class.
Definition Class.h:95
Hash tables with user-supplied hash and equality functions.
Definition HashTable.h:80

◆ _remove()

static void _remove ( HashTable self,
const ident  key 
)
static

Definition at line 200 of file HashTable.c.

200 {
201
202 const size_t bin = self->hash(key) % self->capacity;
203
204 HashTableEntry **e = &self->buckets[bin];
205 while (*e) {
206 if (self->equal((*e)->key, key)) {
207 HashTableEntry *found = *e;
208 *e = found->next;
209 if (self->destroyKey) {
210 self->destroyKey(found->key);
211 }
212 if (self->destroyValue) {
213 self->destroyValue(found->value);
214 }
215 free(found);
216 self->count--;
217 return;
218 }
219 e = &(*e)->next;
220 }
221}
size_t capacity
The number of buckets.
Definition HashTable.h:102
HashTableEntry ** buckets
The buckets.
Definition HashTable.h:108
size_t count
The number of entries.
Definition HashTable.h:96
Consumer destroyKey
Optional destructor called when a key is removed or replaced.
Definition HashTable.h:123
HashTableHashFunc hash
The hash function.
Definition HashTable.h:113
Consumer destroyValue
Optional destructor called when a value is removed or replaced.
Definition HashTable.h:128
HashTableEqualFunc equal
The equality function.
Definition HashTable.h:118

◆ containsKey()

static bool containsKey ( const HashTable self,
const ident  key 
)
static

Definition at line 131 of file HashTable.c.

131 {
132 return $(self, get, key) != NULL;
133}
static ident get(const HashTable *self, const ident key)
Definition HashTable.c:154

◆ dealloc()

static void dealloc ( Object self)
static
See also
Object::dealloc(Object *)

Definition at line 101 of file HashTable.c.

101 {
102
103 HashTable *this = (HashTable *) self;
104
105 for (size_t i = 0; i < this->capacity; i++) {
106 HashTableEntry *e = this->buckets[i];
107 while (e) {
108 HashTableEntry *next = e->next;
109 if (this->destroyKey) {
110 this->destroyKey(e->key);
111 }
112 if (this->destroyValue) {
113 this->destroyValue(e->value);
114 }
115 free(e);
116 e = next;
117 }
118 }
119
120 free(this->buckets);
121
122 super(Object, self, dealloc);
123}
#define super(type, obj, method,...)
static void dealloc(Object *self)
Definition HashTable.c:101
static Unicode next(StringReader *self, StringReaderMode mode)
Object is the root Class of The Objectively Class hierarchy.
Definition Object.h:46

◆ enumerate()

static void enumerate ( const HashTable self,
HashTableEnumerator  enumerator,
ident  data 
)
static

Definition at line 139 of file HashTable.c.

139 {
140
141 assert(enumerator);
142
143 for (size_t i = 0; i < self->capacity; i++) {
144 for (const HashTableEntry *e = self->buckets[i]; e; e = e->next) {
145 enumerator(self, e->key, e->value, data);
146 }
147 }
148}
static Data * data(void)
Definition Data.c:286

◆ get()

static ident get ( const HashTable self,
const ident  key 
)
static

Definition at line 154 of file HashTable.c.

154 {
155
156 const size_t bin = self->hash(key) % self->capacity;
157
158 for (const HashTableEntry *e = self->buckets[bin]; e; e = e->next) {
159 if (self->equal(e->key, key)) {
160 return e->value;
161 }
162 }
163
164 return NULL;
165}

◆ HashTableEqualDirect()

bool HashTableEqualDirect ( const ident  a,
const ident  b 
)
See also
HashTableEqualDirect

Definition at line 92 of file HashTable.c.

92 {
93 return a == b;
94}

◆ HashTableEqualStr()

bool HashTableEqualStr ( const ident  a,
const ident  b 
)
See also
HashTableEqualStr

Definition at line 58 of file HashTable.c.

58 {
59 return strcmp((const char *) a, (const char *) b) == 0;
60}

◆ HashTableEqualStri()

bool HashTableEqualStri ( const ident  a,
const ident  b 
)
See also
HashTableEqualStri

Definition at line 78 of file HashTable.c.

78 {
79 return strcasecmp((const char *) a, (const char *) b) == 0;
80}

◆ HashTableHashDirect()

size_t HashTableHashDirect ( const ident  key)
See also
HashTableHashDirect

Definition at line 85 of file HashTable.c.

85 {
86 return (size_t) (uintptr_t) key;
87}

◆ HashTableHashStr()

size_t HashTableHashStr ( const ident  key)

Common hash functions for use with HashTable.

See also
HashTableHashStr

Definition at line 45 of file HashTable.c.

45 {
46 const char *s = (const char *) key;
47 size_t h = 5381;
48 int c;
49 while ((c = *s++)) {
50 h = ((h << 5) + h) + (size_t) c;
51 }
52 return h;
53}

◆ HashTableHashStri()

size_t HashTableHashStri ( const ident  key)
See also
HashTableHashStri

Definition at line 65 of file HashTable.c.

65 {
66 const char *s = (const char *) key;
67 size_t h = 5381;
68 int c;
69 while ((c = *s++)) {
70 h = ((h << 5) + h) + (size_t) tolower(c);
71 }
72 return h;
73}

◆ init()

static HashTable * init ( HashTable self,
HashTableHashFunc  hash,
HashTableEqualFunc  equal 
)
static

Definition at line 171 of file HashTable.c.

171 {
172 return $(self, initWithCapacity, hash, equal, HASHTABLE_DEFAULT_CAPACITY);
173}
static int hash(const Object *self)
Definition Array.c:129
static HashTable * initWithCapacity(HashTable *self, HashTableHashFunc hash, HashTableEqualFunc equal, size_t capacity)
Definition HashTable.c:179
#define HASHTABLE_DEFAULT_CAPACITY
Definition HashTable.c:36

◆ initialize()

static void initialize ( Class clazz)
static
See also
Class::initialize(Class *)

Definition at line 310 of file HashTable.c.

310 {
311
312 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
313
314 ((HashTableInterface *) clazz->interface)->containsKey = containsKey;
315 ((HashTableInterface *) clazz->interface)->enumerate = enumerate;
316 ((HashTableInterface *) clazz->interface)->get = get;
317 ((HashTableInterface *) clazz->interface)->init = init;
318 ((HashTableInterface *) clazz->interface)->initWithCapacity = initWithCapacity;
319 ((HashTableInterface *) clazz->interface)->remove = _remove;
320 ((HashTableInterface *) clazz->interface)->removeAll = removeAll;
321 ((HashTableInterface *) clazz->interface)->set = set;
322}
static void _remove(HashTable *self, const ident key)
Definition HashTable.c:200
static HashTable * init(HashTable *self, HashTableHashFunc hash, HashTableEqualFunc equal)
Definition HashTable.c:171
static void enumerate(const HashTable *self, HashTableEnumerator enumerator, ident data)
Definition HashTable.c:139
static void removeAll(HashTable *self)
Definition HashTable.c:227
static bool containsKey(const HashTable *self, const ident key)
Definition HashTable.c:131
static Set * set(void)
Definition Set.c:572
ident interface
The interface of the Class.
Definition Class.h:105
void remove(HashTable *self, const ident key)
Removes the entry for the given key.
HashTable * initWithCapacity(HashTable *self, HashTableHashFunc hash, HashTableEqualFunc equal, size_t capacity)
Initializes this HashTable with the given capacity.
Definition HashTable.c:179

◆ initWithCapacity()

static HashTable * initWithCapacity ( HashTable self,
HashTableHashFunc  hash,
HashTableEqualFunc  equal,
size_t  capacity 
)
static

Definition at line 179 of file HashTable.c.

179 {
180
181 self = (HashTable *) super(Object, self, init);
182 if (self) {
183 assert(hash);
184 assert(equal);
185 assert(capacity);
186
187 self->hash = hash;
188 self->equal = equal;
189 self->capacity = capacity;
190 self->buckets = calloc(self->capacity, sizeof(HashTableEntry *));
191 assert(self->buckets);
192 }
193 return self;
194}

◆ removeAll()

static void removeAll ( HashTable self)
static

Definition at line 227 of file HashTable.c.

227 {
228
229 for (size_t i = 0; i < self->capacity; i++) {
230 HashTableEntry *e = self->buckets[i];
231 while (e) {
232 HashTableEntry *next = e->next;
233 if (self->destroyKey) {
234 self->destroyKey(e->key);
235 }
236 if (self->destroyValue) {
237 self->destroyValue(e->value);
238 }
239 free(e);
240 e = next;
241 }
242 self->buckets[i] = NULL;
243 }
244
245 self->count = 0;
246}

◆ resize()

static void resize ( HashTable self,
size_t  capacity 
)
static

Rehashes all entries into a new bucket array of the given capacity.

Definition at line 251 of file HashTable.c.

251 {
252
253 HashTableEntry **buckets = calloc(capacity, sizeof(HashTableEntry *));
254 assert(buckets);
255
256 for (size_t i = 0; i < self->capacity; i++) {
257 for (HashTableEntry *e = self->buckets[i]; e; ) {
258 HashTableEntry *next = e->next;
259 const size_t bin = self->hash(e->key) % capacity;
260 e->next = buckets[bin];
261 buckets[bin] = e;
262 e = next;
263 }
264 }
265
266 free(self->buckets);
267 self->buckets = buckets;
268 self->capacity = capacity;
269}

◆ set()

static void set ( HashTable self,
const ident  key,
const ident  value 
)
static

Definition at line 275 of file HashTable.c.

275 {
276
277 if ((float) self->count / (float) self->capacity >= HASHTABLE_MAX_LOAD) {
279 }
280
281 const size_t bin = self->hash(key) % self->capacity;
282
283 for (HashTableEntry *e = self->buckets[bin]; e; e = e->next) {
284 if (self->equal(e->key, key)) {
285 if (self->destroyKey) {
286 self->destroyKey(e->key);
287 }
288 if (self->destroyValue) {
289 self->destroyValue(e->value);
290 }
291 e->key = key;
292 e->value = value;
293 return;
294 }
295 }
296
297 HashTableEntry *e = calloc(1, sizeof(HashTableEntry));
298 assert(e);
299 e->key = key;
300 e->value = value;
301 e->next = self->buckets[bin];
302 self->buckets[bin] = e;
303 self->count++;
304}
#define HASHTABLE_MAX_LOAD
Definition HashTable.c:38
#define HASHTABLE_GROW_FACTOR
Definition HashTable.c:37
static void resize(HashTable *self, size_t capacity)
Rehashes all entries into a new bucket array of the given capacity.
Definition HashTable.c:251