view dowa/d_memory.c @ 12:de54585a40f1

Adding bun and node modules.
author June Park <parkjune1995@gmail.com>
date Thu, 02 Oct 2025 14:39:48 -0700
parents 1e61008b9980
children fa2b8af609d9
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;
      }

      // Should not copy as we malloced already.
      if (Dowa_HashMap_PushValueWithTypeNoCopy(map, entry->d_name, p_child_map,
                                         sizeof(p_child_map), DOWA_HASH_MAP_TYPE_HASHMAP) == -1)
      {
        Dowa_HashMap_Free(p_child_map);
        return -1;
      }
    }
  }
  closedir(dir);
  return 0;
}