Mercurial
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 21:09def63429b9 | 22:947b81010aba |
|---|---|
| 26 return currnet_ptr; | 26 return currnet_ptr; |
| 27 } | 27 } |
| 28 | 28 |
| 29 void Dowa_Arena_Destroy(Dowa_PArena p_arena) | 29 void Dowa_Arena_Destroy(Dowa_PArena p_arena) |
| 30 { | 30 { |
| 31 if (p_arena) | 31 if (!p_arena) return; |
| 32 { | 32 |
| 33 if (p_arena->buffer) | 33 if (p_arena->buffer) |
| 34 free(p_arena->buffer); | 34 free(p_arena->buffer); |
| 35 free(p_arena); | 35 free(p_arena); |
| 36 } | 36 } |
| 37 | |
| 38 void *Dowa_Arena_Copy(Dowa_PArena p_arena, const void *src, size_t size) | |
| 39 { | |
| 40 if (p_arena == NULL || src == NULL || size == 0) | |
| 41 return NULL; | |
| 42 | |
| 43 void *dest = Dowa_Arena_Allocate(p_arena, size); | |
| 44 if (!dest) | |
| 45 return NULL; | |
| 46 | |
| 47 memcpy(dest, src, size); | |
| 48 return dest; | |
| 37 } | 49 } |
| 38 | 50 |
| 39 // --- HashMap --- // | 51 // --- HashMap --- // |
| 40 Dowa_PHashMap Dowa_HashMap_Create(size_t capacity) | 52 Dowa_PHashMap Dowa_HashMap_Create(size_t capacity) |
| 41 { | 53 { |
| 51 free(p_hash_map); | 63 free(p_hash_map); |
| 52 return NULL; | 64 return NULL; |
| 53 } | 65 } |
| 54 p_hash_map->capacity = capacity; | 66 p_hash_map->capacity = capacity; |
| 55 p_hash_map->current_capacity = 0; | 67 p_hash_map->current_capacity = 0; |
| 68 p_hash_map->p_arena = NULL; | |
| 56 return p_hash_map; | 69 return p_hash_map; |
| 57 } | 70 } |
| 58 | 71 |
| 59 Dowa_PHashMap Dowa_HashMap_Create_With_Arena(size_t capacity, Dowa_PArena p_arena) | 72 Dowa_PHashMap Dowa_HashMap_Create_With_Arena(size_t capacity, Dowa_PArena p_arena) |
| 60 { | 73 { |
| 61 if (p_arena == NULL) | 74 if (p_arena == NULL) |
| 75 { | |
| 62 printf("Arena is NULL\n"); | 76 printf("Arena is NULL\n"); |
| 63 return Dowa_HashMap_Create(capacity); | 77 return Dowa_HashMap_Create(capacity); |
| 78 } | |
| 64 | 79 |
| 65 Dowa_PHashMap p_hash_map; | 80 Dowa_PHashMap p_hash_map; |
| 66 p_hash_map = Dowa_Arena_Allocate(p_arena, sizeof(Dowa_HashMap)); | 81 p_hash_map = Dowa_Arena_Allocate(p_arena, sizeof(Dowa_HashMap)); |
| 67 if (p_hash_map == NULL) | 82 if (p_hash_map == NULL) |
| 68 { | 83 { |
| 69 return NULL; | 84 return NULL; |
| 70 } | 85 } |
| 71 p_hash_map->entries = Dowa_Arena_Allocate(p_arena, sizeof(*p_hash_map->entries) * capacity); | 86 p_hash_map->entries = Dowa_Arena_Allocate(p_arena, sizeof(*p_hash_map->entries) * capacity); |
| 87 memset(p_hash_map->entries, 0, capacity * sizeof *p_hash_map->entries); | |
| 72 if (p_hash_map->entries == NULL) | 88 if (p_hash_map->entries == NULL) |
| 73 { | 89 { |
| 74 free(p_hash_map); | 90 free(p_hash_map); |
| 75 return NULL; | 91 return NULL; |
| 76 } | 92 } |
| 83 void Dowa_HashMap_Destroy(Dowa_PHashMap p_hash_map) | 99 void Dowa_HashMap_Destroy(Dowa_PHashMap p_hash_map) |
| 84 { | 100 { |
| 85 if (!p_hash_map) return; | 101 if (!p_hash_map) return; |
| 86 | 102 |
| 87 if (p_hash_map->p_arena) | 103 if (p_hash_map->p_arena) |
| 88 Dowa_Arena_Destroy(p_hash_map->p_arena); | 104 { |
| 105 // Free arena instead of the map... | |
| 106 // Dowa_Arena_Destroy(p_hash_map->p_arena); | |
| 107 return; | |
| 108 } | |
| 89 else | 109 else |
| 90 { | 110 { |
| 91 Dowa_PHashEntry entry; | 111 Dowa_PHashEntry entry; |
| 92 if (p_hash_map->entries) | 112 if (p_hash_map->entries) |
| 93 { | 113 { |
| 118 return hash_val % p_hash_map->capacity; | 138 return hash_val % p_hash_map->capacity; |
| 119 } | 139 } |
| 120 | 140 |
| 121 void *Dowa_HashMap_Get(Dowa_PHashMap p_hash_map, const char *key) | 141 void *Dowa_HashMap_Get(Dowa_PHashMap p_hash_map, const char *key) |
| 122 { | 142 { |
| 123 int idx_foo = Dowa_HashMap_Get_Position(p_hash_map, key); | 143 int idx = Dowa_HashMap_Get_Position(p_hash_map, key); |
| 124 void *value = p_hash_map->entries[idx_foo]; | 144 Dowa_PHashEntry entry = p_hash_map->entries[idx]; |
| 125 if (value == NULL || strcmp(((Dowa_PHashEntry) value)->key, key) != 0) | 145 |
| 126 { | 146 while (entry) |
| 127 return NULL; | 147 { |
| 128 } | 148 if (strcmp(entry->key, key) == 0) |
| 129 return ((Dowa_PHashEntry) value)->buffer; | 149 { |
| 130 } | 150 return entry->buffer; |
| 151 } | |
| 152 entry = entry->next; | |
| 153 } | |
| 154 | |
| 155 return NULL; | |
| 156 } | |
| 157 | |
| 131 | 158 |
| 132 int32 Dowa_HashMap_Push_Value_With_Type_NoCopy(Dowa_PHashMap p_hash_map, const char *key, | 159 int32 Dowa_HashMap_Push_Value_With_Type_NoCopy(Dowa_PHashMap p_hash_map, const char *key, |
| 133 void *value, size_t value_size, | 160 void *value, size_t value_size, |
| 134 Dowa_HashMap_ValueType type) | 161 Dowa_HashMap_ValueType type) |
| 135 { | 162 { |
| 136 int idx = Dowa_HashMap_Get_Position(p_hash_map, key); | 163 int idx = Dowa_HashMap_Get_Position(p_hash_map, key); |
| 137 Dowa_PHashEntry entry = p_hash_map->entries[idx]; | 164 Dowa_PHashEntry entry = p_hash_map->entries[idx]; |
| 138 if (entry) | 165 Dowa_PHashEntry prev = NULL; |
| 139 free(entry->buffer); | 166 |
| 140 else | 167 // Old key |
| 141 { | 168 while (entry) |
| 142 entry = p_hash_map->p_arena ? | 169 { |
| 143 Dowa_Arena_Allocate(p_hash_map->p_arena, sizeof(Dowa_HashEntry)) : | 170 if (strcmp(entry->key, key) == 0) |
| 144 malloc(sizeof(Dowa_HashEntry)); | 171 { |
| 145 if (entry == NULL) { perror("malloc or arena alloc"); return -1; } | 172 if (!p_hash_map->p_arena && entry->buffer) |
| 146 | 173 free(entry->buffer); |
| 147 p_hash_map->entries[idx] = entry; | 174 entry->buffer = value; |
| 148 p_hash_map->current_capacity++; | 175 entry->capacity = value_size; |
| 149 entry->key = strdup(key); | 176 entry->type = type; |
| 150 } | 177 return 0; |
| 178 } | |
| 179 prev = entry; | |
| 180 entry = entry->next; | |
| 181 } | |
| 182 | |
| 183 // New Key | |
| 184 entry = p_hash_map->p_arena ? | |
| 185 Dowa_Arena_Allocate(p_hash_map->p_arena, sizeof(Dowa_HashEntry)) : | |
| 186 malloc(sizeof(Dowa_HashEntry)); | |
| 187 if (!entry) { perror("malloc or arena alloc"); return -1; } | |
| 188 | |
| 189 entry->key = p_hash_map->p_arena ? | |
| 190 Dowa_Arena_Copy(p_hash_map->p_arena, key, strlen(key) + 1 /* \0 */) : | |
| 191 strdup(key); | |
| 151 entry->buffer = value; | 192 entry->buffer = value; |
| 152 entry->capacity = value_size; | 193 entry->capacity = value_size; |
| 153 entry->type = type; | 194 entry->type = type; |
| 195 entry->next = NULL; | |
| 196 | |
| 197 if (prev) | |
| 198 prev->next = entry; | |
| 199 else | |
| 200 p_hash_map->entries[idx] = entry; | |
| 201 | |
| 202 p_hash_map->current_capacity++; | |
| 154 return 0; | 203 return 0; |
| 155 } | 204 } |
| 156 | 205 |
| 157 int32 Dowa_HashMap_Push_Value_With_Type(Dowa_PHashMap p_hash_map, const char *key, | 206 int32 Dowa_HashMap_Push_Value_With_Type(Dowa_PHashMap p_hash_map, const char *key, |
| 158 void *value, size_t value_size, | 207 void *value, size_t value_size, |
| 159 Dowa_HashMap_ValueType type) | 208 Dowa_HashMap_ValueType type) |
| 160 { | 209 { |
| 161 int idx = Dowa_HashMap_Get_Position(p_hash_map, key); | 210 int idx = Dowa_HashMap_Get_Position(p_hash_map, key); |
| 162 Dowa_PHashEntry entry = p_hash_map->entries[idx]; | 211 Dowa_PHashEntry entry = p_hash_map->entries[idx]; |
| 163 if (entry) | 212 Dowa_PHashEntry prev = NULL; |
| 164 free(entry->buffer); | 213 |
| 165 else | 214 // Check for existing key |
| 166 { | 215 while (entry) |
| 167 entry = p_hash_map->p_arena ? | 216 { |
| 168 Dowa_Arena_Allocate(p_hash_map->p_arena, sizeof(Dowa_HashEntry)) : | 217 if (strcmp(entry->key, key) == 0) |
| 169 malloc(sizeof(Dowa_HashEntry)); | 218 { |
| 170 if (entry == NULL) { perror("malloc or arena alloc"); return -1; } | 219 if (!p_hash_map->p_arena && entry->buffer) |
| 171 | 220 free(entry->buffer); |
| 172 p_hash_map->entries[idx] = entry; | 221 |
| 173 p_hash_map->current_capacity++; | 222 entry->buffer = p_hash_map->p_arena ? |
| 174 entry->key = strdup(key); | 223 Dowa_Arena_Allocate(p_hash_map->p_arena, value_size) : |
| 175 } | 224 malloc(value_size); |
| 176 entry->buffer = p_hash_map->p_arena ? | 225 if (!entry->buffer) { perror("malloc or arena alloc"); return -1; } |
| 226 | |
| 227 memcpy(entry->buffer, value, value_size); | |
| 228 entry->capacity = value_size; | |
| 229 entry->type = type; | |
| 230 return 0; | |
| 231 } | |
| 232 prev = entry; | |
| 233 entry = entry->next; | |
| 234 } | |
| 235 | |
| 236 // New Key | |
| 237 entry = p_hash_map->p_arena ? | |
| 238 Dowa_Arena_Allocate(p_hash_map->p_arena, sizeof(Dowa_HashEntry)) : | |
| 239 malloc(sizeof(Dowa_HashEntry)); | |
| 240 if (!entry) { perror("malloc or arena alloc"); return -1; } | |
| 241 | |
| 242 entry->key = p_hash_map->p_arena ? | |
| 243 Dowa_Arena_Copy(p_hash_map->p_arena, key, strlen(key) + 1 /* \0 */) : | |
| 244 strdup(key); | |
| 245 if (!entry->key) { perror("strdup"); return -1; } | |
| 246 | |
| 247 entry->buffer = p_hash_map->p_arena ? | |
| 177 Dowa_Arena_Allocate(p_hash_map->p_arena, value_size) : | 248 Dowa_Arena_Allocate(p_hash_map->p_arena, value_size) : |
| 178 malloc(value_size); | 249 malloc(value_size); |
| 179 | 250 if (!entry->buffer) { perror("malloc or arena alloc"); return -1; } |
| 180 if (entry->buffer == NULL) { perror("malloc or arena alloc"); return -1; } | 251 |
| 252 memcpy(entry->buffer, value, value_size); | |
| 181 entry->capacity = value_size; | 253 entry->capacity = value_size; |
| 182 entry->type = type; | 254 entry->type = type; |
| 183 memcpy(entry->buffer, value, value_size); | 255 entry->next = NULL; |
| 256 | |
| 257 if (prev) | |
| 258 prev->next = entry; | |
| 259 else | |
| 260 p_hash_map->entries[idx] = entry; | |
| 261 | |
| 262 p_hash_map->current_capacity++; | |
| 184 return 0; | 263 return 0; |
| 185 } | 264 } |
| 186 | 265 |
| 187 void Dowa_HashMap_Push_Value(Dowa_PHashMap p_hash_map, const char *key, void *value, size_t value_size) | 266 void Dowa_HashMap_Push_Value(Dowa_PHashMap p_hash_map, const char *key, void *value, size_t value_size) |
| 188 { | 267 { |
| 191 | 270 |
| 192 void Dowa_HashMap_Pop_Key(Dowa_PHashMap p_hash_map, const char *key) | 271 void Dowa_HashMap_Pop_Key(Dowa_PHashMap p_hash_map, const char *key) |
| 193 { | 272 { |
| 194 int idx = Dowa_HashMap_Get_Position(p_hash_map, key); | 273 int idx = Dowa_HashMap_Get_Position(p_hash_map, key); |
| 195 Dowa_PHashEntry entry = p_hash_map->entries[idx]; | 274 Dowa_PHashEntry entry = p_hash_map->entries[idx]; |
| 196 if (entry) | 275 if (entry && !(p_hash_map->p_arena)) |
| 197 { | 276 { |
| 198 free(entry->key); | 277 free(entry->key); |
| 199 free(entry->buffer); | 278 free(entry->buffer); |
| 200 free(entry); | 279 free(entry); |
| 201 } | 280 } |
| 210 { | 289 { |
| 211 printf("\n-----------\n\n"); | 290 printf("\n-----------\n\n"); |
| 212 for (size_t i = 0; i < map->capacity; ++i) | 291 for (size_t i = 0; i < map->capacity; ++i) |
| 213 { | 292 { |
| 214 Dowa_PHashEntry e = map->entries[i]; | 293 Dowa_PHashEntry e = map->entries[i]; |
| 215 if (!e) continue; | 294 while (e) |
| 216 printf("%s: ", e->key); | 295 { |
| 217 switch (e->type) | 296 if (!e) break; |
| 218 { | 297 printf("%s: ", e->key); |
| 219 case DOWA_HASH_MAP_TYPE_BUFFER: | 298 switch (e->type) |
| 220 { | 299 { |
| 221 unsigned char *p = e->buffer; | 300 case DOWA_HASH_MAP_TYPE_BUFFER: |
| 222 for (size_t j = 0; j < e->capacity; ++j) | 301 { |
| 223 { | 302 unsigned char *p = e->buffer; |
| 224 printf("%02x", p[j]); | 303 for (size_t j = 0; j < e->capacity; ++j) |
| 225 } | 304 { |
| 226 printf("\n"); | 305 printf("%02x", p[j]); |
| 227 } | 306 } |
| 228 break; | 307 printf("\n"); |
| 229 case DOWA_HASH_MAP_TYPE_STRING: | 308 } |
| 230 { | 309 break; |
| 231 printf("%s\n", (char*)e->buffer); | 310 case DOWA_HASH_MAP_TYPE_STRING: |
| 232 } | 311 { |
| 233 break; | 312 printf("%s\n", (char*)e->buffer); |
| 234 case DOWA_HASH_MAP_TYPE_HASHMAP: | 313 } |
| 235 { | 314 break; |
| 236 printf("This is a hashmap with size of %zu, and pointer %p\n", (Dowa_PHashMap)e->capacity, (void *)e); | 315 case DOWA_HASH_MAP_TYPE_HASHMAP: |
| 237 } | 316 { |
| 238 break; | 317 printf("This is a hashmap with size of %zu, and pointer %p\n", e->capacity, (void *)e); |
| 239 case DOWA_HASH_MAP_TYPE_INT: | 318 } |
| 240 { | 319 break; |
| 241 printf("%d\n", *(int32*)e->buffer); | 320 case DOWA_HASH_MAP_TYPE_INT: |
| 242 } | 321 { |
| 243 break; | 322 printf("%d\n", *(int32*)e->buffer); |
| 244 default: | 323 } |
| 245 { | 324 break; |
| 246 printf("<unknown type>\n"); | 325 default: |
| 247 } | 326 { |
| 327 printf("<unknown type>\n"); | |
| 328 } | |
| 329 } | |
| 330 e = e->next; | |
| 248 } | 331 } |
| 249 } | 332 } |
| 250 printf("-----------\n"); | 333 printf("-----------\n"); |
| 251 } | 334 } |
| 252 | 335 |
| 275 size_t size = (size_t)st.st_size; | 358 size_t size = (size_t)st.st_size; |
| 276 FILE *f = fopen(fullpath, "rb"); | 359 FILE *f = fopen(fullpath, "rb"); |
| 277 if (!f) { perror("fopen"); continue; } | 360 if (!f) { perror("fopen"); continue; } |
| 278 | 361 |
| 279 void *buf = p_hash_map->p_arena ? | 362 void *buf = p_hash_map->p_arena ? |
| 280 Dowa_Arena_Allocate(p_hash_map->p_arena, size) : | 363 Dowa_Arena_Allocate(p_hash_map->p_arena, size+1) : |
| 281 malloc(size); | 364 malloc(size+1); |
| 282 if (!buf) { perror("malloc"); fclose(f); closedir(dir); return -1; } | 365 if (!buf) { perror("malloc"); fclose(f); closedir(dir); return -1; } |
| 283 | 366 |
| 367 | |
| 284 if (fread(buf, 1, size, f) != size) | 368 if (fread(buf, 1, size, f) != size) |
| 285 { | 369 { |
| 286 perror("fread"); | 370 perror("fread"); |
| 287 free(buf); | 371 if (!p_hash_map->p_arena) free(buf); |
| 288 fclose(f); | 372 fclose(f); |
| 289 continue; | 373 continue; |
| 290 } | 374 } |
| 291 fclose(f); | 375 fclose(f); |
| 292 | 376 |
| 293 Dowa_HashMap_Push_Value_With_Type(p_hash_map, entry->d_name, buf, size, DOWA_HASH_MAP_TYPE_STRING); | 377 // null-terminate since the files don't do this and we need this for print. |
| 378 ((unsigned char*)buf)[size] = '\0'; | |
| 379 | |
| 380 Dowa_HashMap_Push_Value_With_Type(p_hash_map, entry->d_name, buf, size + 1, DOWA_HASH_MAP_TYPE_STRING); | |
| 294 free(buf); // Dowa_HashMap_PushValue made its own copy | 381 free(buf); // Dowa_HashMap_PushValue made its own copy |
| 295 } | 382 } |
| 296 else if (S_ISDIR(st.st_mode)) | 383 else if (S_ISDIR(st.st_mode)) |
| 297 { | 384 { |
| 385 // TODO: Adjust the sizes of the recursive map? | |
| 298 Dowa_PHashMap p_child_map = Dowa_HashMap_Create_With_Arena(100, p_hash_map->p_arena); | 386 Dowa_PHashMap p_child_map = Dowa_HashMap_Create_With_Arena(100, p_hash_map->p_arena); |
| 299 if (!p_child_map) | 387 if (!p_child_map) |
| 300 { | 388 { |
| 301 perror("Dowa_HashMap_Create"); | 389 perror("Dowa_HashMap_Create"); |
| 302 return -1; | 390 return -1; |