@@ -414,90 +414,61 @@ hashmap_t *hashmap_create(int cap)
414
414
415
415
map -> size = 0 ;
416
416
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 ));
418
418
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" );
421
421
free (map );
422
422
return NULL ;
423
423
}
424
424
425
425
return map ;
426
426
}
427
427
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
- }
459
428
460
429
void hashmap_rehash (hashmap_t * map )
461
430
{
462
431
if (!map )
463
432
return ;
464
433
465
434
int old_cap = map -> cap ;
466
- hashmap_node_t * * old_buckets = map -> buckets ;
435
+ hashmap_node_t * old_table = map -> table ;
467
436
468
437
map -> cap <<= 1 ;
469
- map -> buckets = calloc (map -> cap , sizeof (hashmap_node_t * ));
438
+ map -> table = calloc (map -> cap , sizeof (hashmap_node_t ));
470
439
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 ;
474
443
map -> cap = old_cap ;
475
444
return ;
476
445
}
477
446
447
+ map -> size = 0 ;
448
+
478
449
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 ].occupied ) {
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 ].occupied ) {
458
+ index = (index + 1 ) & (map -> cap - 1 );
459
+ if (index == start ) {
460
+ printf ("Error: New table is full during rehash\n" );
461
+ abort ();
462
+ }
494
463
}
495
464
496
- cur = next ;
465
+ map -> table [index ].key = key ;
466
+ map -> table [index ].val = val ;
467
+ map -> table [index ].occupied = true;
468
+ map -> size ++ ;
497
469
}
498
470
}
499
-
500
- free (old_buckets );
471
+ free (old_table );
501
472
}
502
473
503
474
/* Put a key-value pair into given hashmap.
@@ -513,22 +484,28 @@ void hashmap_put(hashmap_t *map, char *key, void *val)
513
484
if (!map )
514
485
return ;
515
486
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
+
516
491
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 ;
519
493
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 ].occupied ) {
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 ;
526
503
}
527
504
505
+ map -> table [index ].key = arena_strdup (HASHMAP_ARENA , key );
506
+ map -> table [index ].val = val ;
507
+ map -> table [index ].occupied = true;
528
508
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 );
532
509
}
533
510
534
511
/* 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)
544
521
return NULL ;
545
522
546
523
int index = hashmap_hash_index (map -> cap , key );
524
+ int start = index ;
547
525
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 ].occupied ) {
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
+ }
551
534
552
535
return NULL ;
553
536
}
@@ -585,7 +568,7 @@ void hashmap_free(hashmap_t *map)
585
568
if (!map )
586
569
return ;
587
570
588
- free (map -> buckets );
571
+ free (map -> table );
589
572
free (map );
590
573
}
591
574
0 commit comments