diff dowa/d_memory.c @ 22:947b81010aba

[Dowa & Seobeo] Updated so that Dowa hashmaps can use arena and not be broken. Split up web so taht it can handle different paths. Also fixes issues with hash collisions which was pain in the ass.
author June Park <parkjune1995@gmail.com>
date Tue, 07 Oct 2025 07:11:02 -0700
parents 09def63429b9
children 08a465eec50b
line wrap: on
line diff
--- a/dowa/d_memory.c	Mon Oct 06 10:57:30 2025 -0700
+++ b/dowa/d_memory.c	Tue Oct 07 07:11:02 2025 -0700
@@ -28,12 +28,24 @@
 
 void Dowa_Arena_Destroy(Dowa_PArena p_arena)
 {
-  if (p_arena)
-  {
-    if (p_arena->buffer)
-      free(p_arena->buffer);
-    free(p_arena);
-  }
+  if (!p_arena) return;
+
+  if (p_arena->buffer)
+    free(p_arena->buffer);
+  free(p_arena);
+}
+
+void *Dowa_Arena_Copy(Dowa_PArena p_arena, const void *src, size_t size)
+{
+  if (p_arena == NULL || src == NULL || size == 0)
+    return NULL;
+
+  void *dest = Dowa_Arena_Allocate(p_arena, size);
+  if (!dest)
+    return NULL;
+
+  memcpy(dest, src, size);
+  return dest;
 }
 
 // --- HashMap --- //
@@ -53,14 +65,17 @@
   }
   p_hash_map->capacity = capacity;
   p_hash_map->current_capacity = 0;
+  p_hash_map->p_arena = NULL;
   return p_hash_map;
 }
 
 Dowa_PHashMap Dowa_HashMap_Create_With_Arena(size_t capacity, Dowa_PArena p_arena)
 {
   if (p_arena == NULL)
+  {
     printf("Arena is NULL\n");
     return Dowa_HashMap_Create(capacity);
+  }
 
   Dowa_PHashMap p_hash_map;
   p_hash_map = Dowa_Arena_Allocate(p_arena, sizeof(Dowa_HashMap));
@@ -69,6 +84,7 @@
     return NULL;
   }
   p_hash_map->entries = Dowa_Arena_Allocate(p_arena, sizeof(*p_hash_map->entries) * capacity);
+  memset(p_hash_map->entries, 0, capacity * sizeof *p_hash_map->entries);
   if (p_hash_map->entries == NULL)
   {
     free(p_hash_map);
@@ -85,7 +101,11 @@
   if (!p_hash_map) return;
 
   if (p_hash_map->p_arena)
-    Dowa_Arena_Destroy(p_hash_map->p_arena);
+  {
+    // Free arena instead of the map...
+    // Dowa_Arena_Destroy(p_hash_map->p_arena);
+    return;
+  }
   else
   {
     Dowa_PHashEntry entry;
@@ -120,37 +140,66 @@
 
 void *Dowa_HashMap_Get(Dowa_PHashMap p_hash_map, const char *key)
 {
-  int idx_foo = Dowa_HashMap_Get_Position(p_hash_map, key);
-  void *value = p_hash_map->entries[idx_foo];
-  if (value == NULL || strcmp(((Dowa_PHashEntry) value)->key, key) != 0)
+  int idx = Dowa_HashMap_Get_Position(p_hash_map, key);
+  Dowa_PHashEntry entry = p_hash_map->entries[idx];
+
+  while (entry)
   {
-    return NULL;
+    if (strcmp(entry->key, key) == 0)
+    {
+      return entry->buffer;
+    }
+    entry = entry->next;
   }
-  return ((Dowa_PHashEntry) value)->buffer;
+
+  return NULL;
 }
 
+
 int32 Dowa_HashMap_Push_Value_With_Type_NoCopy(Dowa_PHashMap p_hash_map, const char *key, 
                                                void *value, size_t value_size,
                                                Dowa_HashMap_ValueType type)
 {
   int idx = Dowa_HashMap_Get_Position(p_hash_map, key);
   Dowa_PHashEntry entry = p_hash_map->entries[idx];
-  if (entry)
-    free(entry->buffer);
-  else 
+  Dowa_PHashEntry prev = NULL;
+
+  // Old key 
+  while (entry)
   {
-    entry = p_hash_map->p_arena ? 
-      Dowa_Arena_Allocate(p_hash_map->p_arena, sizeof(Dowa_HashEntry)) :
-      malloc(sizeof(Dowa_HashEntry));
-    if (entry == NULL) { perror("malloc or arena alloc"); return -1; }
+    if (strcmp(entry->key, key) == 0)
+    {
+      if (!p_hash_map->p_arena && entry->buffer)
+        free(entry->buffer);
+      entry->buffer = value;
+      entry->capacity = value_size;
+      entry->type = type;
+      return 0; 
+    }
+    prev = entry;
+    entry = entry->next;
+  }
 
-    p_hash_map->entries[idx] = entry;
-    p_hash_map->current_capacity++;
-    entry->key = strdup(key);
-  }
+  // New Key 
+  entry = p_hash_map->p_arena ? 
+    Dowa_Arena_Allocate(p_hash_map->p_arena, sizeof(Dowa_HashEntry)) :
+    malloc(sizeof(Dowa_HashEntry));
+  if (!entry) { perror("malloc or arena alloc"); return -1; }
+
+  entry->key = p_hash_map->p_arena ?
+    Dowa_Arena_Copy(p_hash_map->p_arena, key, strlen(key) + 1 /* \0 */) : 
+    strdup(key);
   entry->buffer = value;
   entry->capacity = value_size;
   entry->type = type;
+  entry->next = NULL;
+
+  if (prev)
+    prev->next = entry;
+  else
+    p_hash_map->entries[idx] = entry;
+
+  p_hash_map->current_capacity++;
   return 0;
 }
 
@@ -160,27 +209,57 @@
 {
   int idx = Dowa_HashMap_Get_Position(p_hash_map, key);
   Dowa_PHashEntry entry = p_hash_map->entries[idx];
-  if (entry)
-    free(entry->buffer);
-  else 
+  Dowa_PHashEntry prev = NULL;
+
+  // Check for existing key
+  while (entry)
   {
-    entry = p_hash_map->p_arena ? 
-      Dowa_Arena_Allocate(p_hash_map->p_arena, sizeof(Dowa_HashEntry)) :
-      malloc(sizeof(Dowa_HashEntry));
-    if (entry == NULL) { perror("malloc or arena alloc"); return -1; }
+    if (strcmp(entry->key, key) == 0)
+    {
+      if (!p_hash_map->p_arena && entry->buffer)
+        free(entry->buffer);
+
+      entry->buffer = p_hash_map->p_arena ?
+        Dowa_Arena_Allocate(p_hash_map->p_arena, value_size) :
+        malloc(value_size);
+      if (!entry->buffer) { perror("malloc or arena alloc"); return -1; }
 
-    p_hash_map->entries[idx] = entry;
-    p_hash_map->current_capacity++;
-    entry->key = strdup(key);
+      memcpy(entry->buffer, value, value_size);
+      entry->capacity = value_size;
+      entry->type = type;
+      return 0;
+    }
+    prev = entry;
+    entry = entry->next;
   }
-  entry->buffer = p_hash_map->p_arena ? 
+
+  // New Key
+  entry = p_hash_map->p_arena ?
+    Dowa_Arena_Allocate(p_hash_map->p_arena, sizeof(Dowa_HashEntry)) :
+    malloc(sizeof(Dowa_HashEntry));
+  if (!entry) { perror("malloc or arena alloc"); return -1; }
+
+  entry->key = p_hash_map->p_arena ?
+    Dowa_Arena_Copy(p_hash_map->p_arena, key, strlen(key) + 1 /* \0 */) :
+    strdup(key);
+  if (!entry->key) { perror("strdup"); return -1; }
+
+  entry->buffer = p_hash_map->p_arena ?
     Dowa_Arena_Allocate(p_hash_map->p_arena, value_size) :
     malloc(value_size);
+  if (!entry->buffer) { perror("malloc or arena alloc"); return -1; }
 
-  if (entry->buffer == NULL) { perror("malloc or arena alloc"); return -1; }
+  memcpy(entry->buffer, value, value_size);
   entry->capacity = value_size;
   entry->type = type;
-  memcpy(entry->buffer, value, value_size);
+  entry->next = NULL;
+
+  if (prev)
+    prev->next = entry;
+  else
+    p_hash_map->entries[idx] = entry;
+
+  p_hash_map->current_capacity++;
   return 0;
 }
 
@@ -193,7 +272,7 @@
 {
   int idx = Dowa_HashMap_Get_Position(p_hash_map, key);
   Dowa_PHashEntry entry = p_hash_map->entries[idx];
-  if (entry)
+  if (entry && !(p_hash_map->p_arena))
   {
     free(entry->key);
     free(entry->buffer);
@@ -212,39 +291,43 @@
   for (size_t i = 0; i < map->capacity; ++i)
   {
     Dowa_PHashEntry e = map->entries[i];
-    if (!e) continue;
-    printf("%s: ", e->key);
-    switch (e->type)
+    while (e) 
     {
-      case DOWA_HASH_MAP_TYPE_BUFFER:
-      {
-        unsigned char *p = e->buffer;
-        for (size_t j = 0; j < e->capacity; ++j)
-        {
-          printf("%02x", p[j]);
-        }
-        printf("\n");
-      }
-      break;
-      case DOWA_HASH_MAP_TYPE_STRING:
+      if (!e) break;
+      printf("%s: ", e->key);
+      switch (e->type)
       {
-        printf("%s\n", (char*)e->buffer);
-      }
-      break;
-      case DOWA_HASH_MAP_TYPE_HASHMAP:
-      {
-        printf("This is a hashmap with size of %zu, and pointer %p\n", (Dowa_PHashMap)e->capacity, (void *)e);
+        case DOWA_HASH_MAP_TYPE_BUFFER:
+        {
+          unsigned char *p = e->buffer;
+          for (size_t j = 0; j < e->capacity; ++j)
+          {
+            printf("%02x", p[j]);
+          }
+          printf("\n");
+        }
+        break;
+        case DOWA_HASH_MAP_TYPE_STRING:
+        {
+          printf("%s\n", (char*)e->buffer);
+        }
+        break;
+        case DOWA_HASH_MAP_TYPE_HASHMAP:
+        {
+          printf("This is a hashmap with size of %zu, and pointer %p\n", e->capacity, (void *)e);
+        }
+        break;
+        case DOWA_HASH_MAP_TYPE_INT:
+        {
+          printf("%d\n", *(int32*)e->buffer);
+        }
+        break;
+        default:
+        {
+          printf("<unknown type>\n");
+        }
       }
-      break;
-      case DOWA_HASH_MAP_TYPE_INT:
-      {
-        printf("%d\n", *(int32*)e->buffer);
-      }
-      break;
-      default:
-      {
-        printf("<unknown type>\n");
-      }
+      e = e->next;
     }
   }
   printf("-----------\n");
@@ -277,24 +360,29 @@
       if (!f) { perror("fopen"); continue; }
 
       void *buf = p_hash_map->p_arena ? 
-        Dowa_Arena_Allocate(p_hash_map->p_arena, size) :
-        malloc(size);
+        Dowa_Arena_Allocate(p_hash_map->p_arena, size+1) :
+        malloc(size+1);
       if (!buf) { perror("malloc"); fclose(f); closedir(dir); return -1; }
 
+
       if (fread(buf, 1, size, f) != size)
       {
         perror("fread");
-        free(buf);
+        if (!p_hash_map->p_arena) free(buf);
         fclose(f);
         continue;
       }
       fclose(f);
 
-      Dowa_HashMap_Push_Value_With_Type(p_hash_map, entry->d_name, buf, size, DOWA_HASH_MAP_TYPE_STRING);
+      // null-terminate since the files don't do this and we need this for print.
+      ((unsigned char*)buf)[size] = '\0';
+
+      Dowa_HashMap_Push_Value_With_Type(p_hash_map, entry->d_name, buf, size + 1, DOWA_HASH_MAP_TYPE_STRING);
       free(buf);  // Dowa_HashMap_PushValue made its own copy
     }
     else if (S_ISDIR(st.st_mode))
     {
+      // TODO: Adjust the sizes of the recursive map?
       Dowa_PHashMap p_child_map = Dowa_HashMap_Create_With_Arena(100, p_hash_map->p_arena); 
       if (!p_child_map)
       {