Skip to content

Commit d4bd334

Browse files
authored
Merge pull request #191 from ChAoSUnItY/fix/hashmap
Overhaul 'hashmap_t' functionalities
2 parents 61c9d10 + 9d2bb4b commit d4bd334

File tree

2 files changed

+89
-31
lines changed

2 files changed

+89
-31
lines changed

src/defs.h

+14-13
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,20 @@ typedef struct {
7878
arena_block_t *head;
7979
} arena_t;
8080

81+
/* string-based hash map definitions */
82+
83+
typedef struct hashmap_node {
84+
char *key;
85+
void *val;
86+
struct hashmap_node *next;
87+
} hashmap_node_t;
88+
89+
typedef struct {
90+
int size;
91+
int cap;
92+
hashmap_node_t **buckets;
93+
} hashmap_t;
94+
8195
/* builtin types */
8296
typedef enum {
8397
TYPE_void = 0,
@@ -331,19 +345,6 @@ typedef struct {
331345
int value;
332346
} constant_t;
333347

334-
/* string-based hash map definitions */
335-
336-
typedef struct hashmap_node {
337-
char *key;
338-
void *val;
339-
struct hashmap_node *next;
340-
} hashmap_node_t;
341-
342-
typedef struct {
343-
int size;
344-
hashmap_node_t **buckets;
345-
} hashmap_t;
346-
347348
struct phi_operand {
348349
var_t *var;
349350
basic_block_t *from;

src/globals.c

+75-18
Original file line numberDiff line numberDiff line change
@@ -231,27 +231,25 @@ int round_up_pow2(int v)
231231
*
232232
* Return: The pointer of created hashmap.
233233
*/
234-
hashmap_t *hashmap_create(int size)
234+
hashmap_t *hashmap_create(int cap)
235235
{
236236
hashmap_t *map = malloc(sizeof(hashmap_t));
237237

238238
if (!map) {
239-
printf("Failed to allocate hashmap_t with size %d\n", size);
239+
printf("Failed to allocate hashmap_t with capacity %d\n", cap);
240240
return NULL;
241241
}
242242

243-
map->size = round_up_pow2(size);
244-
map->buckets = malloc(map->size * sizeof(hashmap_node_t *));
243+
map->size = 0;
244+
map->cap = round_up_pow2(cap);
245+
map->buckets = calloc(map->cap, sizeof(hashmap_node_t *));
245246

246247
if (!map->buckets) {
247248
printf("Failed to allocate buckets in hashmap_t\n");
248249
free(map);
249250
return NULL;
250251
}
251252

252-
for (int i = 0; i < map->size; i++)
253-
map->buckets[i] = 0;
254-
255253
return map;
256254
}
257255

@@ -290,6 +288,47 @@ hashmap_node_t *hashmap_node_new(char *key, void *val)
290288
return node;
291289
}
292290

291+
void hashmap_rehash(hashmap_t *map)
292+
{
293+
if (!map)
294+
return;
295+
296+
int old_cap = map->cap;
297+
hashmap_node_t **old_buckets = map->buckets;
298+
299+
map->cap <<= 1;
300+
map->buckets = calloc(map->cap, sizeof(hashmap_node_t *));
301+
302+
if (!map->buckets) {
303+
printf("Failed to allocate new buckets in hashmap_t\n");
304+
map->buckets = old_buckets;
305+
map->cap = old_cap;
306+
return;
307+
}
308+
309+
for (int i = 0; i < old_cap; i++) {
310+
hashmap_node_t *cur = old_buckets[i], *next, *target_cur;
311+
312+
while (cur) {
313+
next = cur->next;
314+
cur->next = NULL;
315+
int index = hashmap_hash_index(map->cap, cur->key);
316+
target_cur = map->buckets[index];
317+
318+
if (!target_cur) {
319+
map->buckets[index] = cur;
320+
} else {
321+
cur->next = target_cur;
322+
map->buckets[index] = cur;
323+
}
324+
325+
cur = next;
326+
}
327+
}
328+
329+
free(old_buckets);
330+
}
331+
293332
/**
294333
* hashmap_put() - puts a key-value pair into given hashmap.
295334
* If key already contains a value, then replace it with new
@@ -304,42 +343,60 @@ void hashmap_put(hashmap_t *map, char *key, void *val)
304343
if (!map)
305344
return;
306345

307-
int index = hashmap_hash_index(map->size, key);
308-
hashmap_node_t *cur = map->buckets[index];
346+
int index = hashmap_hash_index(map->cap, key);
347+
hashmap_node_t *cur = map->buckets[index],
348+
*new_node = hashmap_node_new(key, val);
309349

310350
if (!cur) {
311-
map->buckets[index] = hashmap_node_new(key, val);
351+
map->buckets[index] = new_node;
312352
} else {
313353
while (cur->next)
314354
cur = cur->next;
315-
cur->next = hashmap_node_new(key, val);
355+
cur->next = new_node;
316356
}
317357

318-
/* TODO: Rehash if size exceeds size * load factor */
358+
map->size++;
359+
/* Check if size of map exceeds load factor 75% (or 3/4 of capacity) */
360+
if ((map->cap >> 2) + (map->cap >> 1) <= map->size)
361+
hashmap_rehash(map);
319362
}
320363

321364
/**
322-
* hashmap_get() - gets value from hashmap from given key.
365+
* hashmap_get_node() - gets key-value pair node from hashmap from given key.
323366
* @map: The hashmap to be looked up. Must no be NULL.
324367
* @key: The key string. May be NULL.
325368
*
326369
* Return: The look up result, if the key-value pair entry
327-
* exists, then returns its value's address, NULL otherwise.
370+
* exists, then returns address of itself, NULL otherwise.
328371
*/
329-
void *hashmap_get(hashmap_t *map, char *key)
372+
hashmap_node_t *hashmap_get_node(hashmap_t *map, char *key)
330373
{
331374
if (!map)
332375
return NULL;
333376

334-
int index = hashmap_hash_index(map->size, key);
377+
int index = hashmap_hash_index(map->cap, key);
335378

336379
for (hashmap_node_t *cur = map->buckets[index]; cur; cur = cur->next)
337380
if (!strcmp(cur->key, key))
338-
return cur->val;
381+
return cur;
339382

340383
return NULL;
341384
}
342385

386+
/**
387+
* hashmap_get() - gets value from hashmap from given key.
388+
* @map: The hashmap to be looked up. Must no be NULL.
389+
* @key: The key string. May be NULL.
390+
*
391+
* Return: The look up result, if the key-value pair entry
392+
* exists, then returns its value's address, NULL otherwise.
393+
*/
394+
void *hashmap_get(hashmap_t *map, char *key)
395+
{
396+
hashmap_node_t *node = hashmap_get_node(map, key);
397+
return node ? node->val : NULL;
398+
}
399+
343400
/**
344401
* hashmap_contains() - checks if the key-value pair entry exists
345402
* from given key.
@@ -351,7 +408,7 @@ void *hashmap_get(hashmap_t *map, char *key)
351408
*/
352409
bool hashmap_contains(hashmap_t *map, char *key)
353410
{
354-
return hashmap_get(map, key);
411+
return hashmap_get_node(map, key);
355412
}
356413

357414
/**

0 commit comments

Comments
 (0)