From bab376cab7aca8219b519ff3538304b4efaae4cc Mon Sep 17 00:00:00 2001
From: "Meredith L. Patterson" <mlp@thesmartpolitenerd.com>
Date: Sun, 20 Apr 2014 21:00:50 +0200
Subject: [PATCH] fix non-resizable hashtable

---
 SConstruct           |  2 --
 src/datastructures.c | 55 ++++++++++++++++++++++++++++++++++++--------
 2 files changed, 46 insertions(+), 11 deletions(-)

diff --git a/SConstruct b/SConstruct
index 207419c..f74f8d5 100644
--- a/SConstruct
+++ b/SConstruct
@@ -39,8 +39,6 @@ if 'DESTDIR' in env:
 
 
 env['libpath'] = calcInstallPath("$prefix", "lib")
-if env['PLATFORM'] != 'darwin' and platform.machine()[-2:] == '64':
-    env['libpath'] += '64'
 env['incpath'] = calcInstallPath("$prefix", "include", "hammer")
 env['parsersincpath'] = calcInstallPath("$prefix", "include", "hammer", "parsers")
 env['backendsincpath'] = calcInstallPath("$prefix", "include", "hammer", "backends")
diff --git a/src/datastructures.c b/src/datastructures.c
index 45a7eba..141adcd 100644
--- a/src/datastructures.c
+++ b/src/datastructures.c
@@ -157,30 +157,67 @@ void* h_hashtable_get(const HHashTable* ht, const void* key) {
   for (hte = &ht->contents[hashval & (ht->capacity - 1)];
        hte != NULL;
        hte = hte->next) {
-    if (hte->key == NULL)
+    if (hte->key == NULL) {
       continue;
-    if (hte->hashval != hashval)
+    }
+    if (hte->hashval != hashval) {
       continue;
-    if (ht->equalFunc(key, hte->key))
+    }
+    if (ht->equalFunc(key, hte->key)) {
       return hte->value;
+    }
   }
   return NULL;
 }
 
+void h_hashtable_put_raw(HHashTable* ht, HHashTableEntry* new_entry);
+
+void h_hashtable_ensure_capacity(HHashTable* ht, size_t n) {
+  bool do_resize = false;
+  size_t old_capacity = ht->capacity;
+  while (n * 1.3 > ht->capacity) {
+    ht->capacity *= 2;
+    do_resize = true;
+  }
+  if (!do_resize)
+    return;
+  HHashTableEntry *old_contents = ht->contents;
+  HHashTableEntry *new_contents = h_arena_malloc(ht->arena, sizeof(HHashTableEntry) * ht->capacity);
+  ht->contents = new_contents;
+  ht->used = 0;
+  memset(new_contents, 0, sizeof(HHashTableEntry) * ht->capacity);
+  for (size_t i = 0; i < old_capacity; ++i)
+    for (HHashTableEntry *entry = &old_contents[i];
+	 entry;
+	 entry = entry->next)
+      if (entry->key)
+	h_hashtable_put_raw(ht, entry);
+  //h_arena_free(ht->arena, old_contents);
+}
+
 void h_hashtable_put(HHashTable* ht, const void* key, void* value) {
   // # Start with a rebalancing
-  //h_hashtable_ensure_capacity(ht, ht->used + 1);
+  h_hashtable_ensure_capacity(ht, ht->used + 1);
 
   HHashValue hashval = ht->hashFunc(key);
+  HHashTableEntry entry = {
+    .key = key,
+    .value = value,
+    .hashval = hashval
+  };
+  h_hashtable_put_raw(ht, &entry);
+}
+ 
+void h_hashtable_put_raw(HHashTable* ht, HHashTableEntry *new_entry) {
 #ifdef CONSISTENCY_CHECK
   assert((ht->capacity & (ht->capacity - 1)) == 0); // capacity is a power of 2
 #endif
 
-  HHashTableEntry *hte = &ht->contents[hashval & (ht->capacity - 1)];
+  HHashTableEntry *hte = &ht->contents[new_entry->hashval & (ht->capacity - 1)];
   if (hte->key != NULL) {
     for(;;) {
       // check each link, stay on last if not found
-      if (hte->hashval == hashval && ht->equalFunc(key, hte->key))
+      if (hte->hashval == new_entry->hashval && ht->equalFunc(new_entry->key, hte->key))
 	goto insert_here;
       if (hte->next == NULL)
         break;
@@ -196,9 +233,9 @@ void h_hashtable_put(HHashTable* ht, const void* key, void* value) {
     ht->used++;
 
  insert_here:
-  hte->key = key;
-  hte->value = value;
-  hte->hashval = hashval;
+  hte->key = new_entry->key;
+  hte->value = new_entry->value;
+  hte->hashval = new_entry->hashval;
 }
 
 void h_hashtable_update(HHashTable *dst, const HHashTable *src) {
-- 
GitLab