Mercurial
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 4:0b3b4f5887bb | 5:3e12bf044589 |
|---|---|
| 1 #include "dowa.h" | 1 #include "dowa.h" |
| 2 | 2 |
| 3 // --- Arena --- // | 3 // --- Arena --- // |
| 4 Dowa_PArena Dowa_Arena_Initialize(size_t capacity) | 4 Dowa_PArena Dowa_Arena_Create(size_t capacity) |
| 5 { | 5 { |
| 6 Dowa_PArena p_arena; | 6 Dowa_PArena p_arena = malloc(sizeof(Dowa_Arena)); |
| 7 p_arena = malloc(capacity); | |
| 8 if (p_arena == NULL) | 7 if (p_arena == NULL) |
| 9 { | 8 { |
| 10 perror("malloc"); | 9 perror("malloc"); |
| 11 return NULL; | 10 return NULL; |
| 12 } | 11 } |
| 12 p_arena->buffer = malloc(capacity); | |
| 13 p_arena->offset = 0; | 13 p_arena->offset = 0; |
| 14 p_arena->capacity = capacity; | 14 p_arena->capacity = capacity; |
| 15 return p_arena; | 15 return p_arena; |
| 16 } | 16 } |
| 17 | 17 |
| 26 return currnet_ptr; | 26 return currnet_ptr; |
| 27 } | 27 } |
| 28 | 28 |
| 29 void Dowa_Arena_Free(Dowa_PArena p_arena) | 29 void Dowa_Arena_Free(Dowa_PArena p_arena) |
| 30 { | 30 { |
| 31 if (p_arena) { | 31 if (p_arena) |
| 32 free(p_arena->buffer); | 32 { |
| 33 if (p_arena->buffer) | |
| 34 free(p_arena->buffer); | |
| 33 free(p_arena); | 35 free(p_arena); |
| 34 } | 36 } |
| 35 } | 37 } |
| 36 | 38 |
| 37 // --- HashMap --- // | 39 // --- HashMap --- // |
| 41 p_hash_map = malloc(sizeof(Dowa_HashMap)); | 43 p_hash_map = malloc(sizeof(Dowa_HashMap)); |
| 42 if (p_hash_map == NULL) | 44 if (p_hash_map == NULL) |
| 43 { | 45 { |
| 44 return NULL; | 46 return NULL; |
| 45 } | 47 } |
| 46 p_hash_map->entries = calloc(capacity, sizeof *p_hash_map->entries); | 48 p_hash_map->entries = calloc(capacity, sizeof(*p_hash_map->entries)); |
| 47 if (p_hash_map->entries == NULL) | 49 if (p_hash_map->entries == NULL) |
| 48 { | 50 { |
| 49 free(p_hash_map); | 51 free(p_hash_map); |
| 50 return NULL; | 52 return NULL; |
| 51 } | 53 } |
| 52 p_hash_map->capacity = capacity; | 54 p_hash_map->capacity = capacity; |
| 53 p_hash_map->current_capacity = 0; | 55 p_hash_map->current_capacity = 0; |
| 54 return p_hash_map; | 56 return p_hash_map; |
| 55 } | 57 } |
| 56 | 58 |
| 59 void Dowa_HashMap_Free(Dowa_PHashMap p_hash_map) | |
| 60 { | |
| 61 if (p_hash_map) | |
| 62 { | |
| 63 Dowa_PHashEntry entry; | |
| 64 if (p_hash_map->entries) | |
| 65 { | |
| 66 for (int idx=0; idx<p_hash_map->capacity; idx++) | |
| 67 { | |
| 68 entry = p_hash_map->entries[idx]; | |
| 69 if (entry) | |
| 70 { | |
| 71 free(entry->key); | |
| 72 free(entry->buffer); | |
| 73 free(entry); | |
| 74 } | |
| 75 } | |
| 76 free(p_hash_map->entries); | |
| 77 } | |
| 78 } | |
| 79 free(p_hash_map); | |
| 80 } | |
| 81 | |
| 57 int32 Dowa_HashMap_GetPosition(Dowa_PHashMap p_hash_map, char *key) | 82 int32 Dowa_HashMap_GetPosition(Dowa_PHashMap p_hash_map, char *key) |
| 58 { | 83 { |
| 59 int32 hash_val = HASH_KEY_NUMBER; | 84 int32 hash_val = HASH_KEY_NUMBER; |
| 60 int32 c; | 85 int32 c; |
| 61 while ((c = *key++)) | 86 while ((c = *key++)) |
| 63 hash_val = (hash_val << 5) + hash_val + c; | 88 hash_val = (hash_val << 5) + hash_val + c; |
| 64 } | 89 } |
| 65 return hash_val % p_hash_map->capacity; | 90 return hash_val % p_hash_map->capacity; |
| 66 } | 91 } |
| 67 | 92 |
| 68 void Dowa_HashMap_PushValueWithType(Dowa_PHashMap p_hash_map, char *key, void *value, size_t value_size, Dowa_ValueType type) | 93 void *Dowa_HashMap_Get(Dowa_PHashMap p_hash_map, char *key) |
| 94 { | |
| 95 int idx_foo = Dowa_HashMap_GetPosition(p_hash_map, key); | |
| 96 void *value = p_hash_map->entries[idx_foo]; | |
| 97 if (strcmp(((Dowa_PHashEntry) value)->key, key) != 0) | |
| 98 { | |
| 99 return NULL; | |
| 100 } | |
| 101 return ((Dowa_PHashEntry) value)->buffer; | |
| 102 } | |
| 103 | |
| 104 int32 Dowa_HashMap_PushValueWithTypeNoCopy(Dowa_PHashMap p_hash_map, char *key, void *value, size_t value_size, Dowa_HashMap_ValueType type) | |
| 69 { | 105 { |
| 70 int idx = Dowa_HashMap_GetPosition(p_hash_map, key); | 106 int idx = Dowa_HashMap_GetPosition(p_hash_map, key); |
| 71 Dowa_PHashEntry entry = p_hash_map->entries[idx]; | 107 Dowa_PHashEntry entry = p_hash_map->entries[idx]; |
| 72 if (entry) | 108 if (entry) |
| 73 { | |
| 74 free(entry->key); | |
| 75 free(entry->buffer); | 109 free(entry->buffer); |
| 76 } | |
| 77 else | 110 else |
| 78 { | 111 { |
| 79 entry = malloc(sizeof(Dowa_HashEntry)); | 112 entry = malloc(sizeof(Dowa_HashEntry)); |
| 80 if (entry == NULL) | 113 if (entry == NULL) { perror("malloc"); return -1; } |
| 81 { | 114 |
| 82 perror("malloc"); | |
| 83 return; | |
| 84 } | |
| 85 p_hash_map->entries[idx] = entry; | 115 p_hash_map->entries[idx] = entry; |
| 86 } | 116 p_hash_map->current_capacity++; |
| 87 entry->key = strdup(key); | 117 entry->key = strdup(key); |
| 118 } | |
| 119 entry->buffer = value; | |
| 120 entry->capacity = value_size; | |
| 121 entry->type = type; | |
| 122 return 0; | |
| 123 } | |
| 124 | |
| 125 int32 Dowa_HashMap_PushValueWithType(Dowa_PHashMap p_hash_map, char *key, void *value, size_t value_size, Dowa_HashMap_ValueType type) | |
| 126 { | |
| 127 int idx = Dowa_HashMap_GetPosition(p_hash_map, key); | |
| 128 Dowa_PHashEntry entry = p_hash_map->entries[idx]; | |
| 129 if (entry) | |
| 130 free(entry->buffer); | |
| 131 else | |
| 132 { | |
| 133 entry = malloc(sizeof(Dowa_HashEntry)); | |
| 134 if (entry == NULL) { perror("malloc"); return -1; } | |
| 135 | |
| 136 p_hash_map->entries[idx] = entry; | |
| 137 p_hash_map->current_capacity++; | |
| 138 entry->key = strdup(key); | |
| 139 } | |
| 88 entry->buffer = malloc(value_size); | 140 entry->buffer = malloc(value_size); |
| 89 if (entry->buffer == NULL) | 141 if (entry->buffer == NULL) { perror("malloc"); return -1; } |
| 90 { | |
| 91 perror("malloc"); | |
| 92 return; | |
| 93 } | |
| 94 entry->capacity = value_size; | 142 entry->capacity = value_size; |
| 95 entry->type = type; | 143 entry->type = type; |
| 96 memcpy(entry->buffer, value, value_size); | 144 memcpy(entry->buffer, value, value_size); |
| 97 p_hash_map->current_capacity++; | 145 return 0; |
| 98 } | 146 } |
| 99 | 147 |
| 100 void Dowa_HashMap_PushValue(Dowa_PHashMap p_hash_map, char *key, void *value, size_t value_size) | 148 void Dowa_HashMap_PushValue(Dowa_PHashMap p_hash_map, char *key, void *value, size_t value_size) |
| 101 { | 149 { |
| 102 Dowa_HashMap_PushValueWithType(p_hash_map, key, value, value_size, DOWA_TYPE_BUFFER); | 150 Dowa_HashMap_PushValueWithType(p_hash_map, key, value, value_size, DOWA_HASH_MAP_TYPE_BUFFER); |
| 103 } | 151 } |
| 104 | 152 |
| 105 void Dowa_HashMap_PopKey(Dowa_PHashMap p_hash_map, char *key) | 153 void Dowa_HashMap_PopKey(Dowa_PHashMap p_hash_map, char *key) |
| 106 { | 154 { |
| 107 int idx = Dowa_HashMap_GetPosition(p_hash_map, key); | 155 int idx = Dowa_HashMap_GetPosition(p_hash_map, key); |
| 117 { | 165 { |
| 118 p_hash_map->current_capacity--; | 166 p_hash_map->current_capacity--; |
| 119 } | 167 } |
| 120 } | 168 } |
| 121 | 169 |
| 122 #include <stdio.h> | |
| 123 | |
| 124 void Dowa_HashMap_Print(Dowa_PHashMap map) | 170 void Dowa_HashMap_Print(Dowa_PHashMap map) |
| 125 { | 171 { |
| 172 printf("\n-----------\n\n"); | |
| 126 for (size_t i = 0; i < map->capacity; ++i) | 173 for (size_t i = 0; i < map->capacity; ++i) |
| 127 { | 174 { |
| 128 Dowa_PHashEntry e = map->entries[i]; | 175 Dowa_PHashEntry e = map->entries[i]; |
| 129 if (!e) continue; | 176 if (!e) continue; |
| 130 printf("%s: ", e->key); | 177 printf("%s: ", e->key); |
| 131 switch (e->type) | 178 switch (e->type) |
| 132 { | 179 { |
| 133 case DOWA_TYPE_BUFFER: | 180 case DOWA_HASH_MAP_TYPE_BUFFER: |
| 134 { | 181 { |
| 135 unsigned char *p = e->buffer; | 182 unsigned char *p = e->buffer; |
| 136 for (size_t j = 0; j < e->capacity; ++j) { | 183 for (size_t j = 0; j < e->capacity; ++j) |
| 184 { | |
| 137 printf("%02x", p[j]); | 185 printf("%02x", p[j]); |
| 138 } | 186 } |
| 139 printf("\n"); | 187 printf("\n"); |
| 140 } | 188 } |
| 141 break; | 189 break; |
| 142 case DOWA_TYPE_STRING: | 190 case DOWA_HASH_MAP_TYPE_STRING: |
| 143 { | 191 { |
| 144 printf("%s\n", (char*)e->buffer); | 192 printf("%s\n", (char*)e->buffer); |
| 145 } | 193 } |
| 146 break; | 194 break; |
| 147 case DOWA_TYPE_INT: | 195 case DOWA_HASH_MAP_TYPE_HASHMAP: |
| 148 { | 196 { |
| 149 printf("%d\n", *(int32_t*)e->buffer); | 197 printf("This is a hashmap with size of %zu, and pointer %p\n", (Dowa_PHashMap)e->capacity, (void *)e); |
| 198 } | |
| 199 break; | |
| 200 case DOWA_HASH_MAP_TYPE_INT: | |
| 201 { | |
| 202 printf("%d\n", *(int32*)e->buffer); | |
| 150 } | 203 } |
| 151 break; | 204 break; |
| 152 default: | 205 default: |
| 153 { | 206 { |
| 154 printf("<unknown type>\n"); | 207 printf("<unknown type>\n"); |
| 155 } | 208 } |
| 156 } | 209 } |
| 157 } | 210 } |
| 158 } | 211 printf("-----------\n"); |
| 159 | 212 } |
| 160 | 213 |
| 161 | 214 int Dowa_HashMap_Cache_Folder(Dowa_PHashMap map, const char *folder_path) |
| 162 int Dowa_Cache_Folder(Dowa_PHashMap map, const char *folder_path) | |
| 163 { | 215 { |
| 164 DIR *dir = opendir(folder_path); | 216 DIR *dir = opendir(folder_path); |
| 165 if (!dir) { | 217 if (!dir) { perror("opendir"); return -1; } |
| 166 perror("opendir"); | |
| 167 return -1; | |
| 168 } | |
| 169 | 218 |
| 170 struct dirent *entry; | 219 struct dirent *entry; |
| 171 while ((entry = readdir(dir))) { | 220 while ((entry = readdir(dir))) |
| 221 { | |
| 172 // skip "." and ".." | 222 // skip "." and ".." |
| 173 if (entry->d_name[0] == '.' && | 223 if (entry->d_name[0] == '.' && |
| 174 (entry->d_name[1] == '\0' || | 224 (entry->d_name[1] == '\0' || |
| 175 (entry->d_name[1] == '.' && entry->d_name[2] == '\0'))) | 225 (entry->d_name[1] == '.' && entry->d_name[2] == '\0'))) |
| 176 continue; | 226 continue; |
| 177 | 227 |
| 178 char fullpath[PATH_MAX]; | 228 char fullpath[PATH_MAX]; |
| 179 snprintf(fullpath, sizeof fullpath, "%s/%s", folder_path, entry->d_name); | 229 snprintf(fullpath, sizeof fullpath, "%s/%s", folder_path, entry->d_name); |
| 180 | 230 |
| 181 struct stat st; | 231 struct stat st; |
| 182 if (stat(fullpath, &st) < 0 || !S_ISREG(st.st_mode)) | 232 if (stat(fullpath, &st) < 0) { perror("stat"); continue; } |
| 183 continue; // skip non-files or errors | 233 |
| 184 | 234 if (S_ISREG(st.st_mode)) |
| 185 size_t size = (size_t)st.st_size; | 235 { |
| 186 FILE *f = fopen(fullpath, "rb"); | 236 size_t size = (size_t)st.st_size; |
| 187 if (!f) | 237 FILE *f = fopen(fullpath, "rb"); |
| 188 { | 238 if (!f) { perror("fopen"); continue; } |
| 189 perror("fopen"); | 239 |
| 190 continue; | 240 void *buf = malloc(size); |
| 191 } | 241 if (!buf) { perror("malloc"); fclose(f); closedir(dir); return -1; } |
| 192 | 242 |
| 193 void *buf = malloc(size); | 243 if (fread(buf, 1, size, f) != size) |
| 194 if (!buf) | 244 { |
| 195 { | 245 perror("fread"); |
| 196 perror("malloc"); | 246 free(buf); |
| 247 fclose(f); | |
| 248 continue; | |
| 249 } | |
| 197 fclose(f); | 250 fclose(f); |
| 198 closedir(dir); | 251 |
| 199 return -1; | 252 Dowa_HashMap_PushValueWithType(map, entry->d_name, buf, size, DOWA_HASH_MAP_TYPE_STRING); |
| 200 } | 253 free(buf); // Dowa_HashMap_PushValue made its own copy |
| 201 | 254 } |
| 202 if (fread(buf, 1, size, f) != size) | 255 else if (S_ISDIR(st.st_mode)) |
| 203 { | 256 { |
| 204 perror("fread"); | 257 Dowa_PHashMap p_child_map = Dowa_HashMap_Create(100); |
| 205 free(buf); | 258 if (!p_child_map) |
| 206 fclose(f); | 259 { |
| 207 continue; | 260 perror("Dowa_HashMap_Create"); |
| 208 } | 261 return -1; |
| 209 fclose(f); | 262 } |
| 210 | 263 if (Dowa_HashMap_Cache_Folder(p_child_map, fullpath) == -1) |
| 211 // key = filename (d_name), value = file contents | 264 { |
| 212 Dowa_HashMap_PushValueWithType(map, entry->d_name, buf, size, DOWA_TYPE_STRING); | 265 perror("Dowa_HashMap_Cache_Folder"); |
| 213 | 266 return -1; |
| 214 free(buf); // Dowa_HashMap_PushValue made its own copy | 267 } |
| 215 } | 268 void *value = Dowa_HashMap_Get(p_child_map, "bar.txt"); |
| 216 | 269 |
| 270 // Should not copy as we malloced alredy. | |
| 271 if (Dowa_HashMap_PushValueWithTypeNoCopy(map, entry->d_name, p_child_map, | |
| 272 sizeof(p_child_map), DOWA_HASH_MAP_TYPE_HASHMAP) == -1) | |
| 273 { | |
| 274 Dowa_HashMap_Free(map); | |
| 275 return -1; | |
| 276 } | |
| 277 } | |
| 278 } | |
| 217 closedir(dir); | 279 closedir(dir); |
| 218 return 0; | 280 return 0; |
| 219 } | 281 } |