Mercurial
view dowa/d_memory.c @ 38:cf9caa4abc3e
[Love] FE and BE. Can chat and render images. Also created MCP for powerpoint generations.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Mon, 01 Dec 2025 20:35:56 -0800 |
| parents | 84672efec192 |
| children | 636eab07809d |
line wrap: on
line source
#include "dowa.h" // --- Arena --- // Dowa_PArena Dowa_Arena_Create(size_t capacity) { Dowa_PArena p_arena = malloc(sizeof(Dowa_Arena)); if (p_arena == NULL) { perror("malloc"); return NULL; } p_arena->buffer = malloc(capacity); p_arena->offset = 0; p_arena->capacity = capacity; return p_arena; } void *Dowa_Arena_Allocate(Dowa_PArena p_arena, size_t size) { if (p_arena->offset + size > p_arena->capacity) { return NULL; } void *currnet_ptr = p_arena->buffer + p_arena->offset; p_arena->offset += size; return currnet_ptr; } void Dowa_Arena_Destroy(Dowa_PArena p_arena) { if (!p_arena) return; if (p_arena->buffer) Dowa_Free(p_arena->buffer); Dowa_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 --- // Dowa_PHashMap Dowa_HashMap_Create(size_t capacity) { Dowa_PHashMap p_hash_map; p_hash_map = malloc(sizeof(Dowa_HashMap)); if (p_hash_map == NULL) { return NULL; } p_hash_map->entries = calloc(capacity, sizeof(*p_hash_map->entries)); if (p_hash_map->entries == NULL) { Dowa_Free(p_hash_map); return NULL; } 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)); if (p_hash_map == NULL) { 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) { Dowa_Free(p_hash_map); return NULL; } p_hash_map->capacity = capacity; p_hash_map->current_capacity = 0; p_hash_map->p_arena = p_arena; return p_hash_map; } void Dowa_HashMap_Destroy(Dowa_PHashMap p_hash_map) { if (!p_hash_map) return; if (p_hash_map->p_arena) { // Free arena instead of the map... // Dowa_Arena_Destroy(p_hash_map->p_arena); return; } else { Dowa_PHashEntry entry; if (p_hash_map->entries) { for (int idx=0; idx<p_hash_map->capacity; idx++) { entry = p_hash_map->entries[idx]; if (entry) { Dowa_Free(entry->key); Dowa_Free(entry->buffer); Dowa_Free(entry); } } } Dowa_Free(p_hash_map->entries); } Dowa_Free(p_hash_map); } int32 Dowa_HashMap_Get_Position(Dowa_PHashMap p_hash_map, const char *key) { int32 hash_val = HASH_KEY_NUMBER; int32 c; while ((c = *key++)) { hash_val = (hash_val << 5) + hash_val + c; } return hash_val % p_hash_map->capacity; } void *Dowa_HashMap_Get(Dowa_PHashMap p_hash_map, const char *key) { int idx = Dowa_HashMap_Get_Position(p_hash_map, key); Dowa_PHashEntry entry = p_hash_map->entries[idx]; while (entry) { if (strcmp(entry->key, key) == 0) { return entry->buffer; } entry = entry->next; } 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]; Dowa_PHashEntry prev = NULL; // Old key while (entry) { if (strcmp(entry->key, key) == 0) { // Fails if it the key exists... return -1; } } // Overriding doesn't really make sense? when copying over // as we need to free it. // //while (entry) //{ // if (strcmp(entry->key, key) == 0) // { // if (!p_hash_map->p_arena && entry->buffer) // Dowa_Free(entry->buffer); // entry->buffer = value; // entry->capacity = value_size; // entry->type = type; // return 0; // } // prev = entry; // entry = entry->next; //} // 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; } int32 Dowa_HashMap_Push_Value_With_Type(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]; Dowa_PHashEntry prev = NULL; // Check for existing key while (entry) { if (strcmp(entry->key, key) == 0) { if (!p_hash_map->p_arena && entry->buffer) Dowa_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; } memcpy(entry->buffer, value, value_size); entry->capacity = value_size; entry->type = type; return 0; } prev = entry; entry = entry->next; } // 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; } memcpy(entry->buffer, value, value_size); 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; } void Dowa_HashMap_Push_Value(Dowa_PHashMap p_hash_map, const char *key, void *value, size_t value_size) { Dowa_HashMap_Push_Value_With_Type(p_hash_map, key, value, value_size, DOWA_HASH_MAP_TYPE_BUFFER); } void Dowa_HashMap_Pop_Key(Dowa_PHashMap p_hash_map, const char *key) { int idx = Dowa_HashMap_Get_Position(p_hash_map, key); Dowa_PHashEntry entry = p_hash_map->entries[idx]; if (entry && !(p_hash_map->p_arena)) { Dowa_Free(entry->key); Dowa_Free(entry->buffer); Dowa_Free(entry); } p_hash_map->entries[idx] = NULL; if (p_hash_map->current_capacity > 0) { p_hash_map->current_capacity--; } } void Dowa_HashMap_Print(Dowa_PHashMap map) { printf("\n-----------\n\n"); for (size_t i = 0; i < map->capacity; ++i) { Dowa_PHashEntry e = map->entries[i]; while (e) { if (!e) break; printf("%s: ", e->key); switch (e->type) { 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"); } } e = e->next; } } printf("-----------\n"); } int Dowa_HashMap_Cache_Folder(Dowa_PHashMap p_hash_map, const char *folder_path) { DIR *dir = opendir(folder_path); if (!dir) { perror("opendir"); return -1; } struct dirent *entry; while ((entry = readdir(dir))) { // skip "." and ".." if (entry->d_name[0] == '.' && (entry->d_name[1] == '\0' || (entry->d_name[1] == '.' && entry->d_name[2] == '\0'))) continue; char fullpath[PATH_MAX]; snprintf(fullpath, sizeof fullpath, "%s/%s", folder_path, entry->d_name); struct stat st; if (stat(fullpath, &st) < 0) { perror("stat"); continue; } if (S_ISREG(st.st_mode)) { size_t size = (size_t)st.st_size; FILE *f = fopen(fullpath, "rb"); if (!f) { perror("fopen"); continue; } void *buf = p_hash_map->p_arena ? Dowa_Arena_Allocate(p_hash_map->p_arena, size) : malloc(size); if (!buf) { perror("malloc"); fclose(f); closedir(dir); return -1; } if (fread(buf, 1, size, f) != size) { perror("fread"); if (!p_hash_map->p_arena) Dowa_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); Dowa_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) { perror("Dowa_HashMap_Create"); return -1; } if (Dowa_HashMap_Cache_Folder(p_child_map, fullpath) == -1) { perror("Dowa_HashMap_Cache_Folder"); return -1; } // Should not copy as we malloced already. if (Dowa_HashMap_Push_Value_With_Type_NoCopy(p_hash_map, entry->d_name, p_child_map, sizeof(p_child_map), DOWA_HASH_MAP_TYPE_HASHMAP) == -1) { Dowa_HashMap_Destroy(p_child_map); return -1; } } } closedir(dir); return 0; }