diff dowa/dowa.h @ 71:75de5903355c

Giagantic changes that update Dowa library to be more align with stb style array and hashmap. Updated Seobeo to be caching on server side instead of file level caching. Deleted bunch of things I don't really use.
author June Park <parkjune1995@gmail.com>
date Sun, 28 Dec 2025 20:34:22 -0800
parents ecb6ee6a22c3
children 4532ce6d9eb8
line wrap: on
line diff
--- a/dowa/dowa.h	Thu Dec 25 20:10:46 2025 -0800
+++ b/dowa/dowa.h	Sun Dec 28 20:34:22 2025 -0800
@@ -2,12 +2,13 @@
 #define DOWA
 
 #include <stdio.h>
-#include <string.h> // stdup
-#include <stdlib.h> // only for malloc, free, stuff
+#include <string.h> // strdup, strlen, memcmp, memcpy
+#include <stdlib.h> // malloc, free, realloc
 #include <assert.h> // mostly for TODO
+#include <stddef.h> // size_t
 
 #ifdef DIRECTORY
-// Only for linux and mac since window do not support.  
+// Only for linux and mac since window do not support.
 // Maybe move this into seobeo file directly?
 #include <dirent.h> // some functions loop through files
 #endif
@@ -19,10 +20,25 @@
 
 #include "dowa_internal.h"
 
-#define HASH_KEY_NUMBER 5381 // DJD hash number
+// DLAPI macro for DLL export/import
+#ifndef DLAPI
+  #ifdef _WIN32
+    #ifdef DOWA_EXPORTS
+      #define DLAPI __declspec(dllexport)
+    #else
+      #define DLAPI __declspec(dllimport)
+    #endif
+  #else
+    #define DLAPI extern
+  #endif
+#endif
+
+#define HASH_KEY_NUMBER 5381
 #define ONE_MEGA_BYTE   1048576
 #define TRUE  1
 #define FALSE 0
+#define DOWA_HASH_BUCKET_SIZE 8
+#define DOWA_HASH_CACHE_LINE_SIZE 64
 
 #define Dowa_Free(p) do { \
   if (p) {                \
@@ -32,13 +48,13 @@
 } while (0)
 
 // Fixed-width integer types
-typedef unsigned int   uint32;   // 32-bit unsigned integer
-typedef int            int32;    // 32-bit signed integer
-typedef unsigned short uint16;   // 16-bit unsigned integer
-typedef short          int16;    // 16-bit signed integer
-typedef unsigned char  uint8;    // 8-bit unsigned integer
-typedef char           int8;     // 8-bit signed integer
-typedef char           boolean;  // Boolean type (0 = false, nonzero = true)
+typedef unsigned int   uint32;
+typedef int            int32;
+typedef unsigned short uint16;
+typedef short          int16;
+typedef unsigned char  uint8;
+typedef char           int8;
+typedef char           boolean;
 
 // --- Arena Allocator --- //
 typedef struct {
@@ -47,28 +63,164 @@
   size_t  capacity;
 } Dowa_Arena;
 
-/* Creates a new arena with the specified capacity (in bytes). Returns a pointer to the arena, or NULL on failure. */
-extern Dowa_Arena *Dowa_Arena_Create(size_t capacity);
-/* Allocates a block of memory of the given size from the arena. Returns pointer to the allocated memory, or NULL if there is insufficient space. */
-extern void       *Dowa_Arena_Allocate(Dowa_Arena *arena, size_t size);
-/* Destroys the arena and frees its underlying memory block.*/
-extern void        Dowa_Arena_Destroy(Dowa_Arena *arena);
-/* Strdup but saves within the arena */
-extern void       *Dowa_Arena_Copy(Dowa_Arena *p_arena, const void *src, size_t size);
-/* Resets the arena offset to 0, allowing reuse without freeing */
-extern void        Dowa_Arena_Reset(Dowa_Arena *p_arena);
-/* Returns the current number of bytes allocated in the arena */
-extern size_t      Dowa_Arena_Get_Used(Dowa_Arena *p_arena);
-/* Returns the remaining capacity in bytes */
-extern size_t      Dowa_Arena_Get_Remaining(Dowa_Arena *p_arena);
+DLAPI Dowa_Arena *Dowa_Arena_Create(size_t capacity);
+DLAPI void       *Dowa_Arena_Allocate(Dowa_Arena *p_arena, size_t size);
+DLAPI void       *Dowa_Arena_Allocate_Aligned(Dowa_Arena *p_arena, size_t size, size_t alignment);
+DLAPI void        Dowa_Arena_Destroy(Dowa_Arena *p_arena);
+DLAPI void       *Dowa_Arena_Copy(Dowa_Arena *p_arena, const void *p_src, size_t size);
+DLAPI void        Dowa_Arena_Reset(Dowa_Arena *p_arena);
+DLAPI size_t      Dowa_Arena_Get_Used(Dowa_Arena *p_arena);
+DLAPI size_t      Dowa_Arena_Get_Remaining(Dowa_Arena *p_arena);
+
+// --- New stb_ds-style Data Structures --- //
+
+// Allocator type enum
+typedef enum {
+  DOWA_ALLOCATOR_MALLOC = 0,
+  DOWA_ALLOCATOR_ARENA = 1
+} Dowa_Allocator_Type;
+
+// Array header (prefix to actual array data)
+typedef struct {
+  size_t length;
+  size_t capacity;
+  uint8  allocator_type;
+  Dowa_Arena* p_arena;
+  void* p_hash;
+} Dowa_Array_Header;
+
+// Hash bucket (64 bytes for cache line alignment)
+typedef struct {
+  uint32 hash[DOWA_HASH_BUCKET_SIZE];
+  uint32 index[DOWA_HASH_BUCKET_SIZE];
+} Dowa_Hash_Bucket;
+
+// Hash index structure (separate from value array)
+typedef struct {
+  size_t bucket_count;
+  size_t item_count;
+  size_t tombstone_count;
+  uint8  allocator_type;
+  Dowa_Arena* p_arena;
+  Dowa_Hash_Bucket* p_buckets;
+} Dowa_Hash_Index;
+
+// Key-Value pair declaration macro
+#define Dowa_KV(K, V) struct { K key; V value; }
+
+// Internal header accessor
+#define dowa__header(a) ((Dowa_Array_Header*)(a) - 1)
+
+// --- Array Macros --- //
+
+#define Dowa_Array_Length(a)   ((a) ? dowa__header(a)->length : 0)
+#define Dowa_Array_Capacity(a) ((a) ? dowa__header(a)->capacity : 0)
+
+#define Dowa_Array_Push(a, v) \
+  ((a) = dowa__array_grow((a), sizeof(*(a)), 0, NULL), \
+   (a)[dowa__header(a)->length++] = (v))
+
+#define Dowa_Array_Push_Arena(a, v, arena) \
+  ((a) = dowa__array_grow((a), sizeof(*(a)), 0, (arena)), \
+   (a)[dowa__header(a)->length++] = (v))
+
+#define Dowa_Array_Pop(a) ((a)[--dowa__header(a)->length])
+
+#define Dowa_Array_Clear(a) ((a) ? (dowa__header(a)->length = 0) : 0)
+
+#define Dowa_Array_Free(a) ((a) ? (dowa__array_free((a)), (a) = NULL) : 0)
+
+#define Dowa_Array_Reserve(a, n) \
+  ((a) = dowa__array_grow((a), sizeof(*(a)), (n), NULL))
+
+#define Dowa_Array_Reserve_Arena(a, n, arena) \
+  ((a) = dowa__array_grow((a), sizeof(*(a)), (n), (arena)))
+
+// --- HashMap Macros --- //
+
+#define Dowa_HashMap_Get(m, k) \
+  dowa__hashmap_get((m), sizeof(*(m)), (k), strlen(k) + 1)
+
+#define Dowa_HashMap_Get_Ptr(m, k) \
+  dowa__hashmap_get_ptr((m), sizeof(*(m)), (k), strlen(k) + 1)
+
+#define Dowa_HashMap_Push(m, k, v) \
+  do { \
+    (m) = dowa__hashmap_push((m), sizeof(*(m)), (k), strlen(k) + 1, NULL); \
+    void* p_kv_temp = dowa__hashmap_get_ptr((m), sizeof(*(m)), (k), strlen(k) + 1); \
+    if (p_kv_temp) \
+      ((typeof(m))p_kv_temp)->value = (v); \
+  } while (0)
+
+#define Dowa_HashMap_Push_Arena(m, k, v, arena) \
+  do { \
+    (m) = dowa__hashmap_push((m), sizeof(*(m)), (k), strlen(k) + 1, (arena)); \
+    void* p_kv_temp = dowa__hashmap_get_ptr((m), sizeof(*(m)), (k), strlen(k) + 1); \
+    if (p_kv_temp) \
+      ((typeof(m))p_kv_temp)->value = (v); \
+  } while (0)
+
+#define Dowa_HashMap_Has_Key(m, k) \
+  dowa__hashmap_has_key((m), sizeof(*(m)), (k), strlen(k) + 1)
+
+#define Dowa_HashMap_Delete(m, k) \
+  dowa__hashmap_delete((m), sizeof(*(m)), (k), strlen(k) + 1)
+
+#define Dowa_HashMap_Clear(m) dowa__hashmap_clear((m), sizeof(*(m)))
+
+#define Dowa_HashMap_Free(m) ((m) ? (dowa__hashmap_free((m)), (m) = NULL) : 0)
+
+#define Dowa_HashMap_Count(m) dowa__hashmap_count(m)
+
+#define Dowa_HashMap_Get_Binary(m, k, ksize) \
+  dowa__hashmap_get((m), sizeof(*(m)), (k), (ksize))
+
+#define Dowa_HashMap_Get_Ptr_Binary(m, k, ksize) \
+  dowa__hashmap_get_ptr((m), sizeof(*(m)), (k), (ksize))
+
+#define Dowa_HashMap_Push_Binary(m, k, ksize, v) \
+  do { \
+    (m) = dowa__hashmap_push((m), sizeof(*(m)), (k), (ksize), NULL); \
+    void* p_kv_temp = dowa__hashmap_get_ptr((m), sizeof(*(m)), (k), (ksize)); \
+    if (p_kv_temp) \
+      ((typeof(m))p_kv_temp)->value = (v); \
+  } while (0)
+
+#define Dowa_HashMap_Push_Binary_Arena(m, k, ksize, v, arena) \
+  do { \
+    (m) = dowa__hashmap_push((m), sizeof(*(m)), (k), (ksize), (arena)); \
+    void* p_kv_temp = dowa__hashmap_get_ptr((m), sizeof(*(m)), (k), (ksize)); \
+    if (p_kv_temp) \
+      ((typeof(m))p_kv_temp)->value = (v); \
+  } while (0)
+
+// --- Array Core Functions --- //
+
+DLAPI void* dowa__array_grow(void* p_array, size_t element_size, size_t minimum_capacity, Dowa_Arena* p_arena);
+DLAPI void  dowa__array_free(void* p_array);
+
+// --- HashMap Core Functions --- //
+
+DLAPI uint32  dowa__hash_bytes(void* p_key, size_t key_size);
+DLAPI void*   dowa__hashmap_get(void* p_map, size_t element_size, void* p_key, size_t key_size);
+DLAPI void*   dowa__hashmap_get_ptr(void* p_map, size_t element_size, void* p_key, size_t key_size);
+DLAPI void*   dowa__hashmap_push(void* p_map, size_t element_size, void* p_key, size_t key_size, Dowa_Arena* p_arena);
+DLAPI boolean dowa__hashmap_has_key(void* p_map, size_t element_size, void* p_key, size_t key_size);
+DLAPI void    dowa__hashmap_delete(void* p_map, size_t element_size, void* p_key, size_t key_size);
+DLAPI void    dowa__hashmap_clear(void* p_map, size_t element_size);
+DLAPI void    dowa__hashmap_free(void* p_map);
+DLAPI size_t  dowa__hashmap_count(void* p_map);
+
+// --- OLD API (kept for reference, will be removed after migration) --- //
+/*
 
 
-// --- HashMap --- //
+OLD HashMap API - Commented out for migration
 typedef enum {
-  DOWA_HASH_MAP_TYPE_BUFFER,   // Raw byte buffer
-  DOWA_HASH_MAP_TYPE_STRING,   // Null-terminated string
-  DOWA_HASH_MAP_TYPE_HASHMAP,  // Nested hashmap
-  DOWA_HASH_MAP_TYPE_INT       // Integer value
+  DOWA_HASH_MAP_TYPE_BUFFER,
+  DOWA_HASH_MAP_TYPE_STRING,
+  DOWA_HASH_MAP_TYPE_HASHMAP,
+  DOWA_HASH_MAP_TYPE_INT
 } Dowa_HashMap_ValueType;
 
 typedef struct Dowa_HashEntry {
@@ -76,7 +228,7 @@
   void                   *buffer;
   size_t                  capacity;
   Dowa_HashMap_ValueType  type;
-  struct Dowa_HashEntry  *next; 
+  struct Dowa_HashEntry  *next;
 } Dowa_HashEntry;
 
 typedef struct {
@@ -86,44 +238,49 @@
     Dowa_Arena      *p_arena;
 } Dowa_HashMap;
 
-/* Creates a new hashmap with the given initial capacity. Returns pointer to the hashmap, or NULL on failure. */
 extern Dowa_HashMap *Dowa_HashMap_Create(size_t capacity);
-/* Creates a new hashmap with the given initial capacity, using the provided arena for all internal allocations. Returns pointer to the hashmap, or NULL on failure. */
 extern Dowa_HashMap *Dowa_HashMap_Create_With_Arena(size_t capacity, Dowa_Arena *arena);
-/* Destroys the hashmap and frees all associated memory */
 extern void          Dowa_HashMap_Destroy(Dowa_HashMap *p_hash_map);
-/* Returns the index of the entry for the specified key, or -1 if the key is not found. */
 extern int32         Dowa_HashMap_Get_Position(Dowa_HashMap *p_hash_map, const char *key);
-/* Retrieves the value buffer for the specified key, or NULL if the key does not exist. */
 extern void         *Dowa_HashMap_Get(Dowa_HashMap *p_hash_map, const char *key);
-/* Inserts a copy of the given value into the hashmap under the specified key. Uses DOWA_HASH_MAP_TYPE_BUFFER as the entry type. */
 extern void          Dowa_HashMap_Push_Value(Dowa_HashMap *p_hash_map, const char *key, void *value, size_t value_size);
-/* Inserts a copy of the given value with the specified type into the hashmap under the key. Returns the index of the new entry, or -1 on failure. */
 extern int32         Dowa_HashMap_Push_Value_With_Type(Dowa_HashMap *p_hash_map, const char *key, void *value, size_t value_size, Dowa_HashMap_ValueType type);
-/* Inserts a value pointer into the hashmap under the specified key without copying data. The caller retains ownership of the pointer. Returns the entry index, or -1 on failure. */
 extern int32         Dowa_HashMap_Push_Value_With_Type_NoCopy(Dowa_HashMap *p_hash_map, const char *key, void *value, size_t value_size, Dowa_HashMap_ValueType type);
-/* Removes the entry with the specified key from the hashmap and frees its data if owned. */
 extern void          Dowa_HashMap_Pop_Key(Dowa_HashMap *p_hash_map, const char *key);
-/* Returns TRUE if the key exists in the hashmap, FALSE otherwise. */
 extern boolean       Dowa_HashMap_Has_Key(Dowa_HashMap *p_hash_map, const char *key);
-/* Removes all entries from the hashmap without destroying it. */
 extern void          Dowa_HashMap_Clear(Dowa_HashMap *p_hash_map);
-/* Returns the number of entries currently in the hashmap. */
 extern uint32        Dowa_HashMap_Get_Count(Dowa_HashMap *p_hash_map);
 
-// --- String manipuliation -- //
-// Splice string from start to end
-const char *Dowa_String_Slice(const char *from, size_t start, size_t end);
-// --- Miscellaneous --- //
-char *Dowa_Int32ToString(uint32 value, char *buffer); /* Just use atoid lmao*/
+OLD Array API - Commented out for migration
+#define DOWA_ARRAY_DEFAULT_CAPACITY 256
+
+typedef struct {
+  void   *value;
+  uint32  length;
+} Dowa_Array_Item;
+
+typedef struct {
+  uint32             capacity;
+  uint32             current_length;
+  Dowa_Array_Item   *items;
+} Dowa_Array;
 
-// --- Utility Functions --- //
-/* Prints all entries in the hashmap to stdout for debugging purposes. */
-extern void          Dowa_HashMap_Print(Dowa_HashMap *map);
-#ifdef DIRECTORY
-/* Loads all files from the specified folder into the hashmap. Uses file names as keys and file contents as values. Returns 0 on success, or -1 on failure. */
-extern int           Dowa_HashMap_Cache_Folder(Dowa_HashMap *map, const char *folder_path);
-#endif
+#define Dowa_Array_Push_Value(dowa_array, buffer, length) ...
+Dowa_Array *Dowa_Array_Init();
+
+OLD Utility Functions - Will be migrated
+extern void Dowa_HashMap_Print(Dowa_HashMap *map);
+extern int  Dowa_HashMap_Cache_Folder(Dowa_HashMap *map, const char *folder_path);
+*/
+
+// --- String Manipulation --- //
+
+DLAPI const char *Dowa_String_Slice(const char *p_from, size_t start, size_t end);
+DLAPI int32       Dowa_String_Pos_Find(const char *p_from, const char *p_value, const size_t from_length, const size_t value_length);
+DLAPI char       *Dowa_String_Find(const char *p_from, const char *p_value, const size_t from_length, const size_t value_length);
+DLAPI int32       Dowa_String_Pos_Find_Char(const char *p_from, int c, int32 from_len);
+DLAPI char       *Dowa_String_Find_Char(const char *p_from, int c, int32 from_len);
+DLAPI char       *Dowa_Int32ToString(uint32 value, char *p_buffer);
 
 
 #endif