@@ -414,90 +414,61 @@ hashmap_t *hashmap_create(int cap)
414414
415415 map -> size = 0 ;
416416 map -> cap = round_up_pow2 (cap );
417- map -> buckets = calloc (map -> cap , sizeof (hashmap_node_t * ));
417+ map -> table = calloc (map -> cap , sizeof (hashmap_node_t ));
418418
419- if (!map -> buckets ) {
420- printf ("Failed to allocate buckets in hashmap_t\n" );
419+ if (!map -> table ) {
420+ printf ("Failed to allocate table in hashmap_t\n" );
421421 free (map );
422422 return NULL ;
423423 }
424424
425425 return map ;
426426}
427427
428- /* Create a hashmap node on heap.
429- * @key: The key of node. Must not be NULL.
430- * @val: The value of node. Could be NULL.
431- *
432- * Return: The pointer of created node.
433- */
434- hashmap_node_t * hashmap_node_new (char * key , void * val )
435- {
436- if (!key )
437- return NULL ;
438-
439- const int len = strlen (key );
440- hashmap_node_t * node = arena_alloc (HASHMAP_ARENA , sizeof (hashmap_node_t ));
441-
442-
443- if (!node ) {
444- printf ("Failed to allocate hashmap_node_t\n" );
445- return NULL ;
446- }
447-
448- node -> key = arena_alloc (HASHMAP_ARENA , len + 1 );
449- if (!node -> key ) {
450- printf ("Failed to allocate hashmap_node_t key with size %d\n" , len + 1 );
451- return NULL ;
452- }
453-
454- strcpy (node -> key , key );
455- node -> val = val ;
456- node -> next = NULL ;
457- return node ;
458- }
459428
460429void hashmap_rehash (hashmap_t * map )
461430{
462431 if (!map )
463432 return ;
464433
465434 int old_cap = map -> cap ;
466- hashmap_node_t * * old_buckets = map -> buckets ;
435+ hashmap_node_t * old_table = map -> table ;
467436
468437 map -> cap <<= 1 ;
469- map -> buckets = calloc (map -> cap , sizeof (hashmap_node_t * ));
438+ map -> table = calloc (map -> cap , sizeof (hashmap_node_t ));
470439
471- if (!map -> buckets ) {
472- printf ("Failed to allocate new buckets in hashmap_t\n" );
473- map -> buckets = old_buckets ;
440+ if (!map -> table ) {
441+ printf ("Failed to allocate new table in hashmap_t\n" );
442+ map -> table = old_table ;
474443 map -> cap = old_cap ;
475444 return ;
476445 }
477446
447+ map -> size = 0 ;
448+
478449 for (int i = 0 ; i < old_cap ; i ++ ) {
479- hashmap_node_t * cur = old_buckets [i ];
480- hashmap_node_t * next ;
481- hashmap_node_t * target_cur ;
482-
483- while (cur ) {
484- next = cur -> next ;
485- cur -> next = NULL ;
486- int index = hashmap_hash_index (map -> cap , cur -> key );
487- target_cur = map -> buckets [index ];
488-
489- if (!target_cur ) {
490- map -> buckets [index ] = cur ;
491- } else {
492- cur -> next = target_cur ;
493- map -> buckets [index ] = cur ;
450+ if (old_table [i ].state == true) {
451+ char * key = old_table [i ].key ;
452+ void * val = old_table [i ].val ;
453+
454+ int index = hashmap_hash_index (map -> cap , key );
455+ int start = index ;
456+
457+ while (map -> table [index ].state == true) {
458+ index = (index + 1 ) & (map -> cap - 1 );
459+ if (index == start ) {
460+ printf ("Error: New table is full during rehash\n" );
461+ abort ();
462+ }
494463 }
495464
496- cur = next ;
465+ map -> table [index ].key = key ;
466+ map -> table [index ].val = val ;
467+ map -> table [index ].state = true;
468+ map -> size ++ ;
497469 }
498470 }
499-
500- free (old_buckets );
471+ free (old_table );
501472}
502473
503474/* Put a key-value pair into given hashmap.
@@ -513,22 +484,28 @@ void hashmap_put(hashmap_t *map, char *key, void *val)
513484 if (!map )
514485 return ;
515486
487+ /* Check if size of map exceeds load factor 50% (or 1/2 of capacity) */
488+ if ((map -> cap >> 1 ) <= map -> size )
489+ hashmap_rehash (map );
490+
516491 int index = hashmap_hash_index (map -> cap , key );
517- hashmap_node_t * cur = map -> buckets [index ],
518- * new_node = hashmap_node_new (key , val );
492+ int start = index ;
519493
520- if (!cur ) {
521- map -> buckets [index ] = new_node ;
522- } else {
523- while (cur -> next )
524- cur = cur -> next ;
525- cur -> next = new_node ;
494+ while (map -> table [index ].state == true) {
495+ if (!strcmp (map -> table [index ].key , key )) {
496+ map -> table [index ].val = val ;
497+ return ;
498+ }
499+
500+ index = (index + 1 ) & (map -> cap - 1 );
501+ if (index == start )
502+ return ;
526503 }
527504
505+ map -> table [index ].key = arena_strdup (HASHMAP_ARENA , key );
506+ map -> table [index ].val = val ;
507+ map -> table [index ].state = true;
528508 map -> size ++ ;
529- /* Check if size of map exceeds load factor 75% (or 3/4 of capacity) */
530- if ((map -> cap >> 2 ) + (map -> cap >> 1 ) <= map -> size )
531- hashmap_rehash (map );
532509}
533510
534511/* Get key-value pair node from hashmap from given key.
@@ -544,10 +521,16 @@ hashmap_node_t *hashmap_get_node(hashmap_t *map, char *key)
544521 return NULL ;
545522
546523 int index = hashmap_hash_index (map -> cap , key );
524+ int start = index ;
547525
548- for (hashmap_node_t * cur = map -> buckets [index ]; cur ; cur = cur -> next )
549- if (!strcmp (cur -> key , key ))
550- return cur ;
526+ while (map -> table [index ].state == true) {
527+ if (!strcmp (map -> table [index ].key , key ))
528+ return & map -> table [index ];
529+
530+ index = (index + 1 ) & (map -> cap - 1 );
531+ if (index == start )
532+ return NULL ;
533+ }
551534
552535 return NULL ;
553536}
@@ -574,7 +557,7 @@ void *hashmap_get(hashmap_t *map, char *key)
574557 */
575558bool hashmap_contains (hashmap_t * map , char * key )
576559{
577- return hashmap_get_node (map , key );
560+ return hashmap_get_node (map , key ) != NULL ;
578561}
579562
580563/* Free the hashmap, this also frees key-value pair entry's value.
@@ -585,7 +568,7 @@ void hashmap_free(hashmap_t *map)
585568 if (!map )
586569 return ;
587570
588- free (map -> buckets );
571+ free (map -> table );
589572 free (map );
590573}
591574
0 commit comments