Mercurial
view dowa/d_memory.c @ 5:3e12bf044589
Fixed Dowa hashmap to recursively add files into memory.
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Sat, 27 Sep 2025 16:23:04 -0700 |
| parents | 2758f5527d2b |
| children | 1e61008b9980 |
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_Free(Dowa_PArena p_arena) { if (p_arena) { if (p_arena->buffer) free(p_arena->buffer); free(p_arena); } } // --- 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) { free(p_hash_map); return NULL; } p_hash_map->capacity = capacity; p_hash_map->current_capacity = 0; return p_hash_map; } void Dowa_HashMap_Free(Dowa_PHashMap p_hash_map) { if (p_hash_map) { 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) { free(entry->key); free(entry->buffer); free(entry); } } free(p_hash_map->entries); } } free(p_hash_map); } int32 Dowa_HashMap_GetPosition(Dowa_PHashMap p_hash_map, 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, char *key) { int idx_foo = Dowa_HashMap_GetPosition(p_hash_map, key); void *value = p_hash_map->entries[idx_foo]; if (strcmp(((Dowa_PHashEntry) value)->key, key) != 0) { return NULL; } return ((Dowa_PHashEntry) value)->buffer; } int32 Dowa_HashMap_PushValueWithTypeNoCopy(Dowa_PHashMap p_hash_map, char *key, void *value, size_t value_size, Dowa_HashMap_ValueType type) { int idx = Dowa_HashMap_GetPosition(p_hash_map, key); Dowa_PHashEntry entry = p_hash_map->entries[idx]; if (entry) free(entry->buffer); else { entry = malloc(sizeof(Dowa_HashEntry)); if (entry == NULL) { perror("malloc"); return -1; } p_hash_map->entries[idx] = entry; p_hash_map->current_capacity++; entry->key = strdup(key); } entry->buffer = value; entry->capacity = value_size; entry->type = type; return 0; } int32 Dowa_HashMap_PushValueWithType(Dowa_PHashMap p_hash_map, char *key, void *value, size_t value_size, Dowa_HashMap_ValueType type) { int idx = Dowa_HashMap_GetPosition(p_hash_map, key); Dowa_PHashEntry entry = p_hash_map->entries[idx]; if (entry) free(entry->buffer); else { entry = malloc(sizeof(Dowa_HashEntry)); if (entry == NULL) { perror("malloc"); return -1; } p_hash_map->entries[idx] = entry; p_hash_map->current_capacity++; entry->key = strdup(key); } entry->buffer = malloc(value_size); if (entry->buffer == NULL) { perror("malloc"); return -1; } entry->capacity = value_size; entry->type = type; memcpy(entry->buffer, value, value_size); return 0; } void Dowa_HashMap_PushValue(Dowa_PHashMap p_hash_map, char *key, void *value, size_t value_size) { Dowa_HashMap_PushValueWithType(p_hash_map, key, value, value_size, DOWA_HASH_MAP_TYPE_BUFFER); } void Dowa_HashMap_PopKey(Dowa_PHashMap p_hash_map, char *key) { int idx = Dowa_HashMap_GetPosition(p_hash_map, key); Dowa_PHashEntry entry = p_hash_map->entries[idx]; if (entry) { free(entry->key); free(entry->buffer); 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]; if (!e) continue; 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", (Dowa_PHashMap)e->capacity, (void *)e); } break; case DOWA_HASH_MAP_TYPE_INT: { printf("%d\n", *(int32*)e->buffer); } break; default: { printf("<unknown type>\n"); } } } printf("-----------\n"); } int Dowa_HashMap_Cache_Folder(Dowa_PHashMap 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 = malloc(size); if (!buf) { perror("malloc"); fclose(f); closedir(dir); return -1; } if (fread(buf, 1, size, f) != size) { perror("fread"); free(buf); fclose(f); continue; } fclose(f); Dowa_HashMap_PushValueWithType(map, entry->d_name, buf, size, DOWA_HASH_MAP_TYPE_STRING); free(buf); // Dowa_HashMap_PushValue made its own copy } else if (S_ISDIR(st.st_mode)) { Dowa_PHashMap p_child_map = Dowa_HashMap_Create(100); 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; } void *value = Dowa_HashMap_Get(p_child_map, "bar.txt"); // Should not copy as we malloced alredy. if (Dowa_HashMap_PushValueWithTypeNoCopy(map, entry->d_name, p_child_map, sizeof(p_child_map), DOWA_HASH_MAP_TYPE_HASHMAP) == -1) { Dowa_HashMap_Free(map); return -1; } } } closedir(dir); return 0; }