Mercurial
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 70:4bc56e88e1f3 | 71:75de5903355c |
|---|---|
| 1 #ifndef DOWA | 1 #ifndef DOWA |
| 2 #define DOWA | 2 #define DOWA |
| 3 | 3 |
| 4 #include <stdio.h> | 4 #include <stdio.h> |
| 5 #include <string.h> // stdup | 5 #include <string.h> // strdup, strlen, memcmp, memcpy |
| 6 #include <stdlib.h> // only for malloc, free, stuff | 6 #include <stdlib.h> // malloc, free, realloc |
| 7 #include <assert.h> // mostly for TODO | 7 #include <assert.h> // mostly for TODO |
| 8 #include <stddef.h> // size_t | |
| 8 | 9 |
| 9 #ifdef DIRECTORY | 10 #ifdef DIRECTORY |
| 10 // Only for linux and mac since window do not support. | 11 // Only for linux and mac since window do not support. |
| 11 // Maybe move this into seobeo file directly? | 12 // Maybe move this into seobeo file directly? |
| 12 #include <dirent.h> // some functions loop through files | 13 #include <dirent.h> // some functions loop through files |
| 13 #endif | 14 #endif |
| 14 | 15 |
| 15 #include <math.h> // I am not re-writing stuff I guess... | 16 #include <math.h> // I am not re-writing stuff I guess... |
| 17 #include <sys/stat.h> | 18 #include <sys/stat.h> |
| 18 #include <limits.h> | 19 #include <limits.h> |
| 19 | 20 |
| 20 #include "dowa_internal.h" | 21 #include "dowa_internal.h" |
| 21 | 22 |
| 22 #define HASH_KEY_NUMBER 5381 // DJD hash number | 23 // DLAPI macro for DLL export/import |
| 24 #ifndef DLAPI | |
| 25 #ifdef _WIN32 | |
| 26 #ifdef DOWA_EXPORTS | |
| 27 #define DLAPI __declspec(dllexport) | |
| 28 #else | |
| 29 #define DLAPI __declspec(dllimport) | |
| 30 #endif | |
| 31 #else | |
| 32 #define DLAPI extern | |
| 33 #endif | |
| 34 #endif | |
| 35 | |
| 36 #define HASH_KEY_NUMBER 5381 | |
| 23 #define ONE_MEGA_BYTE 1048576 | 37 #define ONE_MEGA_BYTE 1048576 |
| 24 #define TRUE 1 | 38 #define TRUE 1 |
| 25 #define FALSE 0 | 39 #define FALSE 0 |
| 40 #define DOWA_HASH_BUCKET_SIZE 8 | |
| 41 #define DOWA_HASH_CACHE_LINE_SIZE 64 | |
| 26 | 42 |
| 27 #define Dowa_Free(p) do { \ | 43 #define Dowa_Free(p) do { \ |
| 28 if (p) { \ | 44 if (p) { \ |
| 29 free(p); \ | 45 free(p); \ |
| 30 (p) = NULL; \ | 46 (p) = NULL; \ |
| 31 } \ | 47 } \ |
| 32 } while (0) | 48 } while (0) |
| 33 | 49 |
| 34 // Fixed-width integer types | 50 // Fixed-width integer types |
| 35 typedef unsigned int uint32; // 32-bit unsigned integer | 51 typedef unsigned int uint32; |
| 36 typedef int int32; // 32-bit signed integer | 52 typedef int int32; |
| 37 typedef unsigned short uint16; // 16-bit unsigned integer | 53 typedef unsigned short uint16; |
| 38 typedef short int16; // 16-bit signed integer | 54 typedef short int16; |
| 39 typedef unsigned char uint8; // 8-bit unsigned integer | 55 typedef unsigned char uint8; |
| 40 typedef char int8; // 8-bit signed integer | 56 typedef char int8; |
| 41 typedef char boolean; // Boolean type (0 = false, nonzero = true) | 57 typedef char boolean; |
| 42 | 58 |
| 43 // --- Arena Allocator --- // | 59 // --- Arena Allocator --- // |
| 44 typedef struct { | 60 typedef struct { |
| 45 char *buffer; | 61 char *buffer; |
| 46 size_t offset; | 62 size_t offset; |
| 47 size_t capacity; | 63 size_t capacity; |
| 48 } Dowa_Arena; | 64 } Dowa_Arena; |
| 49 | 65 |
| 50 /* Creates a new arena with the specified capacity (in bytes). Returns a pointer to the arena, or NULL on failure. */ | 66 DLAPI Dowa_Arena *Dowa_Arena_Create(size_t capacity); |
| 51 extern Dowa_Arena *Dowa_Arena_Create(size_t capacity); | 67 DLAPI void *Dowa_Arena_Allocate(Dowa_Arena *p_arena, size_t size); |
| 52 /* 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. */ | 68 DLAPI void *Dowa_Arena_Allocate_Aligned(Dowa_Arena *p_arena, size_t size, size_t alignment); |
| 53 extern void *Dowa_Arena_Allocate(Dowa_Arena *arena, size_t size); | 69 DLAPI void Dowa_Arena_Destroy(Dowa_Arena *p_arena); |
| 54 /* Destroys the arena and frees its underlying memory block.*/ | 70 DLAPI void *Dowa_Arena_Copy(Dowa_Arena *p_arena, const void *p_src, size_t size); |
| 55 extern void Dowa_Arena_Destroy(Dowa_Arena *arena); | 71 DLAPI void Dowa_Arena_Reset(Dowa_Arena *p_arena); |
| 56 /* Strdup but saves within the arena */ | 72 DLAPI size_t Dowa_Arena_Get_Used(Dowa_Arena *p_arena); |
| 57 extern void *Dowa_Arena_Copy(Dowa_Arena *p_arena, const void *src, size_t size); | 73 DLAPI size_t Dowa_Arena_Get_Remaining(Dowa_Arena *p_arena); |
| 58 /* Resets the arena offset to 0, allowing reuse without freeing */ | 74 |
| 59 extern void Dowa_Arena_Reset(Dowa_Arena *p_arena); | 75 // --- New stb_ds-style Data Structures --- // |
| 60 /* Returns the current number of bytes allocated in the arena */ | 76 |
| 61 extern size_t Dowa_Arena_Get_Used(Dowa_Arena *p_arena); | 77 // Allocator type enum |
| 62 /* Returns the remaining capacity in bytes */ | |
| 63 extern size_t Dowa_Arena_Get_Remaining(Dowa_Arena *p_arena); | |
| 64 | |
| 65 | |
| 66 // --- HashMap --- // | |
| 67 typedef enum { | 78 typedef enum { |
| 68 DOWA_HASH_MAP_TYPE_BUFFER, // Raw byte buffer | 79 DOWA_ALLOCATOR_MALLOC = 0, |
| 69 DOWA_HASH_MAP_TYPE_STRING, // Null-terminated string | 80 DOWA_ALLOCATOR_ARENA = 1 |
| 70 DOWA_HASH_MAP_TYPE_HASHMAP, // Nested hashmap | 81 } Dowa_Allocator_Type; |
| 71 DOWA_HASH_MAP_TYPE_INT // Integer value | 82 |
| 83 // Array header (prefix to actual array data) | |
| 84 typedef struct { | |
| 85 size_t length; | |
| 86 size_t capacity; | |
| 87 uint8 allocator_type; | |
| 88 Dowa_Arena* p_arena; | |
| 89 void* p_hash; | |
| 90 } Dowa_Array_Header; | |
| 91 | |
| 92 // Hash bucket (64 bytes for cache line alignment) | |
| 93 typedef struct { | |
| 94 uint32 hash[DOWA_HASH_BUCKET_SIZE]; | |
| 95 uint32 index[DOWA_HASH_BUCKET_SIZE]; | |
| 96 } Dowa_Hash_Bucket; | |
| 97 | |
| 98 // Hash index structure (separate from value array) | |
| 99 typedef struct { | |
| 100 size_t bucket_count; | |
| 101 size_t item_count; | |
| 102 size_t tombstone_count; | |
| 103 uint8 allocator_type; | |
| 104 Dowa_Arena* p_arena; | |
| 105 Dowa_Hash_Bucket* p_buckets; | |
| 106 } Dowa_Hash_Index; | |
| 107 | |
| 108 // Key-Value pair declaration macro | |
| 109 #define Dowa_KV(K, V) struct { K key; V value; } | |
| 110 | |
| 111 // Internal header accessor | |
| 112 #define dowa__header(a) ((Dowa_Array_Header*)(a) - 1) | |
| 113 | |
| 114 // --- Array Macros --- // | |
| 115 | |
| 116 #define Dowa_Array_Length(a) ((a) ? dowa__header(a)->length : 0) | |
| 117 #define Dowa_Array_Capacity(a) ((a) ? dowa__header(a)->capacity : 0) | |
| 118 | |
| 119 #define Dowa_Array_Push(a, v) \ | |
| 120 ((a) = dowa__array_grow((a), sizeof(*(a)), 0, NULL), \ | |
| 121 (a)[dowa__header(a)->length++] = (v)) | |
| 122 | |
| 123 #define Dowa_Array_Push_Arena(a, v, arena) \ | |
| 124 ((a) = dowa__array_grow((a), sizeof(*(a)), 0, (arena)), \ | |
| 125 (a)[dowa__header(a)->length++] = (v)) | |
| 126 | |
| 127 #define Dowa_Array_Pop(a) ((a)[--dowa__header(a)->length]) | |
| 128 | |
| 129 #define Dowa_Array_Clear(a) ((a) ? (dowa__header(a)->length = 0) : 0) | |
| 130 | |
| 131 #define Dowa_Array_Free(a) ((a) ? (dowa__array_free((a)), (a) = NULL) : 0) | |
| 132 | |
| 133 #define Dowa_Array_Reserve(a, n) \ | |
| 134 ((a) = dowa__array_grow((a), sizeof(*(a)), (n), NULL)) | |
| 135 | |
| 136 #define Dowa_Array_Reserve_Arena(a, n, arena) \ | |
| 137 ((a) = dowa__array_grow((a), sizeof(*(a)), (n), (arena))) | |
| 138 | |
| 139 // --- HashMap Macros --- // | |
| 140 | |
| 141 #define Dowa_HashMap_Get(m, k) \ | |
| 142 dowa__hashmap_get((m), sizeof(*(m)), (k), strlen(k) + 1) | |
| 143 | |
| 144 #define Dowa_HashMap_Get_Ptr(m, k) \ | |
| 145 dowa__hashmap_get_ptr((m), sizeof(*(m)), (k), strlen(k) + 1) | |
| 146 | |
| 147 #define Dowa_HashMap_Push(m, k, v) \ | |
| 148 do { \ | |
| 149 (m) = dowa__hashmap_push((m), sizeof(*(m)), (k), strlen(k) + 1, NULL); \ | |
| 150 void* p_kv_temp = dowa__hashmap_get_ptr((m), sizeof(*(m)), (k), strlen(k) + 1); \ | |
| 151 if (p_kv_temp) \ | |
| 152 ((typeof(m))p_kv_temp)->value = (v); \ | |
| 153 } while (0) | |
| 154 | |
| 155 #define Dowa_HashMap_Push_Arena(m, k, v, arena) \ | |
| 156 do { \ | |
| 157 (m) = dowa__hashmap_push((m), sizeof(*(m)), (k), strlen(k) + 1, (arena)); \ | |
| 158 void* p_kv_temp = dowa__hashmap_get_ptr((m), sizeof(*(m)), (k), strlen(k) + 1); \ | |
| 159 if (p_kv_temp) \ | |
| 160 ((typeof(m))p_kv_temp)->value = (v); \ | |
| 161 } while (0) | |
| 162 | |
| 163 #define Dowa_HashMap_Has_Key(m, k) \ | |
| 164 dowa__hashmap_has_key((m), sizeof(*(m)), (k), strlen(k) + 1) | |
| 165 | |
| 166 #define Dowa_HashMap_Delete(m, k) \ | |
| 167 dowa__hashmap_delete((m), sizeof(*(m)), (k), strlen(k) + 1) | |
| 168 | |
| 169 #define Dowa_HashMap_Clear(m) dowa__hashmap_clear((m), sizeof(*(m))) | |
| 170 | |
| 171 #define Dowa_HashMap_Free(m) ((m) ? (dowa__hashmap_free((m)), (m) = NULL) : 0) | |
| 172 | |
| 173 #define Dowa_HashMap_Count(m) dowa__hashmap_count(m) | |
| 174 | |
| 175 #define Dowa_HashMap_Get_Binary(m, k, ksize) \ | |
| 176 dowa__hashmap_get((m), sizeof(*(m)), (k), (ksize)) | |
| 177 | |
| 178 #define Dowa_HashMap_Get_Ptr_Binary(m, k, ksize) \ | |
| 179 dowa__hashmap_get_ptr((m), sizeof(*(m)), (k), (ksize)) | |
| 180 | |
| 181 #define Dowa_HashMap_Push_Binary(m, k, ksize, v) \ | |
| 182 do { \ | |
| 183 (m) = dowa__hashmap_push((m), sizeof(*(m)), (k), (ksize), NULL); \ | |
| 184 void* p_kv_temp = dowa__hashmap_get_ptr((m), sizeof(*(m)), (k), (ksize)); \ | |
| 185 if (p_kv_temp) \ | |
| 186 ((typeof(m))p_kv_temp)->value = (v); \ | |
| 187 } while (0) | |
| 188 | |
| 189 #define Dowa_HashMap_Push_Binary_Arena(m, k, ksize, v, arena) \ | |
| 190 do { \ | |
| 191 (m) = dowa__hashmap_push((m), sizeof(*(m)), (k), (ksize), (arena)); \ | |
| 192 void* p_kv_temp = dowa__hashmap_get_ptr((m), sizeof(*(m)), (k), (ksize)); \ | |
| 193 if (p_kv_temp) \ | |
| 194 ((typeof(m))p_kv_temp)->value = (v); \ | |
| 195 } while (0) | |
| 196 | |
| 197 // --- Array Core Functions --- // | |
| 198 | |
| 199 DLAPI void* dowa__array_grow(void* p_array, size_t element_size, size_t minimum_capacity, Dowa_Arena* p_arena); | |
| 200 DLAPI void dowa__array_free(void* p_array); | |
| 201 | |
| 202 // --- HashMap Core Functions --- // | |
| 203 | |
| 204 DLAPI uint32 dowa__hash_bytes(void* p_key, size_t key_size); | |
| 205 DLAPI void* dowa__hashmap_get(void* p_map, size_t element_size, void* p_key, size_t key_size); | |
| 206 DLAPI void* dowa__hashmap_get_ptr(void* p_map, size_t element_size, void* p_key, size_t key_size); | |
| 207 DLAPI void* dowa__hashmap_push(void* p_map, size_t element_size, void* p_key, size_t key_size, Dowa_Arena* p_arena); | |
| 208 DLAPI boolean dowa__hashmap_has_key(void* p_map, size_t element_size, void* p_key, size_t key_size); | |
| 209 DLAPI void dowa__hashmap_delete(void* p_map, size_t element_size, void* p_key, size_t key_size); | |
| 210 DLAPI void dowa__hashmap_clear(void* p_map, size_t element_size); | |
| 211 DLAPI void dowa__hashmap_free(void* p_map); | |
| 212 DLAPI size_t dowa__hashmap_count(void* p_map); | |
| 213 | |
| 214 // --- OLD API (kept for reference, will be removed after migration) --- // | |
| 215 /* | |
| 216 | |
| 217 | |
| 218 OLD HashMap API - Commented out for migration | |
| 219 typedef enum { | |
| 220 DOWA_HASH_MAP_TYPE_BUFFER, | |
| 221 DOWA_HASH_MAP_TYPE_STRING, | |
| 222 DOWA_HASH_MAP_TYPE_HASHMAP, | |
| 223 DOWA_HASH_MAP_TYPE_INT | |
| 72 } Dowa_HashMap_ValueType; | 224 } Dowa_HashMap_ValueType; |
| 73 | 225 |
| 74 typedef struct Dowa_HashEntry { | 226 typedef struct Dowa_HashEntry { |
| 75 char *key; | 227 char *key; |
| 76 void *buffer; | 228 void *buffer; |
| 77 size_t capacity; | 229 size_t capacity; |
| 78 Dowa_HashMap_ValueType type; | 230 Dowa_HashMap_ValueType type; |
| 79 struct Dowa_HashEntry *next; | 231 struct Dowa_HashEntry *next; |
| 80 } Dowa_HashEntry; | 232 } Dowa_HashEntry; |
| 81 | 233 |
| 82 typedef struct { | 234 typedef struct { |
| 83 Dowa_HashEntry **entries; | 235 Dowa_HashEntry **entries; |
| 84 size_t capacity; | 236 size_t capacity; |
| 85 uint32 current_capacity; | 237 uint32 current_capacity; |
| 86 Dowa_Arena *p_arena; | 238 Dowa_Arena *p_arena; |
| 87 } Dowa_HashMap; | 239 } Dowa_HashMap; |
| 88 | 240 |
| 89 /* Creates a new hashmap with the given initial capacity. Returns pointer to the hashmap, or NULL on failure. */ | |
| 90 extern Dowa_HashMap *Dowa_HashMap_Create(size_t capacity); | 241 extern Dowa_HashMap *Dowa_HashMap_Create(size_t capacity); |
| 91 /* 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. */ | |
| 92 extern Dowa_HashMap *Dowa_HashMap_Create_With_Arena(size_t capacity, Dowa_Arena *arena); | 242 extern Dowa_HashMap *Dowa_HashMap_Create_With_Arena(size_t capacity, Dowa_Arena *arena); |
| 93 /* Destroys the hashmap and frees all associated memory */ | |
| 94 extern void Dowa_HashMap_Destroy(Dowa_HashMap *p_hash_map); | 243 extern void Dowa_HashMap_Destroy(Dowa_HashMap *p_hash_map); |
| 95 /* Returns the index of the entry for the specified key, or -1 if the key is not found. */ | |
| 96 extern int32 Dowa_HashMap_Get_Position(Dowa_HashMap *p_hash_map, const char *key); | 244 extern int32 Dowa_HashMap_Get_Position(Dowa_HashMap *p_hash_map, const char *key); |
| 97 /* Retrieves the value buffer for the specified key, or NULL if the key does not exist. */ | |
| 98 extern void *Dowa_HashMap_Get(Dowa_HashMap *p_hash_map, const char *key); | 245 extern void *Dowa_HashMap_Get(Dowa_HashMap *p_hash_map, const char *key); |
| 99 /* Inserts a copy of the given value into the hashmap under the specified key. Uses DOWA_HASH_MAP_TYPE_BUFFER as the entry type. */ | |
| 100 extern void Dowa_HashMap_Push_Value(Dowa_HashMap *p_hash_map, const char *key, void *value, size_t value_size); | 246 extern void Dowa_HashMap_Push_Value(Dowa_HashMap *p_hash_map, const char *key, void *value, size_t value_size); |
| 101 /* 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. */ | |
| 102 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); | 247 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); |
| 103 /* 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. */ | |
| 104 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); | 248 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); |
| 105 /* Removes the entry with the specified key from the hashmap and frees its data if owned. */ | |
| 106 extern void Dowa_HashMap_Pop_Key(Dowa_HashMap *p_hash_map, const char *key); | 249 extern void Dowa_HashMap_Pop_Key(Dowa_HashMap *p_hash_map, const char *key); |
| 107 /* Returns TRUE if the key exists in the hashmap, FALSE otherwise. */ | |
| 108 extern boolean Dowa_HashMap_Has_Key(Dowa_HashMap *p_hash_map, const char *key); | 250 extern boolean Dowa_HashMap_Has_Key(Dowa_HashMap *p_hash_map, const char *key); |
| 109 /* Removes all entries from the hashmap without destroying it. */ | |
| 110 extern void Dowa_HashMap_Clear(Dowa_HashMap *p_hash_map); | 251 extern void Dowa_HashMap_Clear(Dowa_HashMap *p_hash_map); |
| 111 /* Returns the number of entries currently in the hashmap. */ | |
| 112 extern uint32 Dowa_HashMap_Get_Count(Dowa_HashMap *p_hash_map); | 252 extern uint32 Dowa_HashMap_Get_Count(Dowa_HashMap *p_hash_map); |
| 113 | 253 |
| 114 // --- String manipuliation -- // | 254 OLD Array API - Commented out for migration |
| 115 // Splice string from start to end | 255 #define DOWA_ARRAY_DEFAULT_CAPACITY 256 |
| 116 const char *Dowa_String_Slice(const char *from, size_t start, size_t end); | 256 |
| 117 // --- Miscellaneous --- // | 257 typedef struct { |
| 118 char *Dowa_Int32ToString(uint32 value, char *buffer); /* Just use atoid lmao*/ | 258 void *value; |
| 119 | 259 uint32 length; |
| 120 // --- Utility Functions --- // | 260 } Dowa_Array_Item; |
| 121 /* Prints all entries in the hashmap to stdout for debugging purposes. */ | 261 |
| 122 extern void Dowa_HashMap_Print(Dowa_HashMap *map); | 262 typedef struct { |
| 123 #ifdef DIRECTORY | 263 uint32 capacity; |
| 124 /* 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. */ | 264 uint32 current_length; |
| 125 extern int Dowa_HashMap_Cache_Folder(Dowa_HashMap *map, const char *folder_path); | 265 Dowa_Array_Item *items; |
| 266 } Dowa_Array; | |
| 267 | |
| 268 #define Dowa_Array_Push_Value(dowa_array, buffer, length) ... | |
| 269 Dowa_Array *Dowa_Array_Init(); | |
| 270 | |
| 271 OLD Utility Functions - Will be migrated | |
| 272 extern void Dowa_HashMap_Print(Dowa_HashMap *map); | |
| 273 extern int Dowa_HashMap_Cache_Folder(Dowa_HashMap *map, const char *folder_path); | |
| 274 */ | |
| 275 | |
| 276 // --- String Manipulation --- // | |
| 277 | |
| 278 DLAPI const char *Dowa_String_Slice(const char *p_from, size_t start, size_t end); | |
| 279 DLAPI int32 Dowa_String_Pos_Find(const char *p_from, const char *p_value, const size_t from_length, const size_t value_length); | |
| 280 DLAPI char *Dowa_String_Find(const char *p_from, const char *p_value, const size_t from_length, const size_t value_length); | |
| 281 DLAPI int32 Dowa_String_Pos_Find_Char(const char *p_from, int c, int32 from_len); | |
| 282 DLAPI char *Dowa_String_Find_Char(const char *p_from, int c, int32 from_len); | |
| 283 DLAPI char *Dowa_Int32ToString(uint32 value, char *p_buffer); | |
| 284 | |
| 285 | |
| 126 #endif | 286 #endif |
| 127 | |
| 128 | |
| 129 #endif |