Advertisement
bobmarley12345

C Map/ArrayMap (O(n))

Jan 28th, 2023
802
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.84 KB | None | 0 0
  1. //
  2. // Created by kettl on 28/01/2023.
  3. //
  4.  
  5. #ifndef REGHZYLIBS_ARRAYMAP_H
  6. #define REGHZYLIBS_ARRAYMAP_H
  7.  
  8. #define SIZEOF_NODE(count) (sizeof(ArrayMapNode) * (count))
  9. #define AM_ENTRY_REPLACED 0
  10. #define AM_ENTRY_INSERTED 1
  11.  
  12. typedef int32_t hash_t;
  13.  
  14. typedef hash_t (* hash_func)(const void*);
  15. typedef int (* comp_func)(const void*, const void*);
  16.  
  17. typedef struct {
  18.     hash_t hashCode;
  19.     void* m_key;
  20.     void* m_val;
  21. } ArrayMapNode;
  22.  
  23. typedef struct {
  24.     hash_func m_hash;    // The key hashing function
  25.     comp_func m_comp;    // The key comparison function. Returns non-zero if two keys are equal
  26.     size_t m_tab_cap;    // The current max capacity of this map (m_tab_cap * sizeof(ArrayMapNode) bytes)
  27.     size_t m_tab_len;    // The number of entries in this map
  28.     ArrayMapNode* m_tab; // A pointer to the start of the table
  29. } ArrayMap;
  30.  
  31. static int def_comp_func(const void* a, const void* b) {
  32.     return a == b;
  33. }
  34.  
  35. ArrayMap* new_array_map(hash_func hash, comp_func comp) {
  36.     auto* map = (ArrayMap*) malloc(sizeof(ArrayMap));
  37.     memset(map, 0, sizeof(ArrayMap));
  38.     map->m_hash = hash;
  39.     map->m_comp = comp;
  40.     return map;
  41. }
  42.  
  43. ArrayMap* new_array_map(hash_func hash) {
  44.     return new_array_map(hash, def_comp_func);
  45. }
  46.  
  47. static int index_for_key(ArrayMap* map, void* key) {
  48.     hash_t hash = map->m_hash(key);
  49.     for(int i = 0; i < map->m_tab_len; i++) {
  50.         ArrayMapNode* node = &map->m_tab[i];
  51.         if (node->hashCode == hash) {
  52.             if (map->m_comp(node->m_key, key)) {
  53.                 return i;
  54.             }
  55.         }
  56.     }
  57.  
  58.     return -1;
  59. }
  60.  
  61. static void insert_entry(ArrayMap* map, void* key, void* val) {
  62.     if (map->m_tab_cap == 0 || map->m_tab_len >= map->m_tab_cap) {
  63.         size_t new_cap = map->m_tab_cap + (map->m_tab_cap >> 1);
  64.         if (new_cap < 1) {
  65.             new_cap = 1;
  66.         }
  67.         else if (new_cap == map->m_tab_cap) {
  68.             new_cap++;
  69.         }
  70.  
  71.         auto* table = (ArrayMapNode*) malloc(SIZEOF_NODE(new_cap));
  72.         if (table == nullptr) {
  73.             return; // ??? what to do here
  74.         }
  75.  
  76.         if (map->m_tab != nullptr) {
  77.             memcpy(table, map->m_tab, SIZEOF_NODE(map->m_tab_cap));
  78.             free(map->m_tab);
  79.         }
  80.  
  81.         map->m_tab_cap = new_cap;
  82.         map->m_tab = table;
  83.     }
  84.  
  85.     map->m_tab[map->m_tab_len++] = {map->m_hash(key), key, val};
  86. }
  87.  
  88.  
  89. static void remove_at_index(ArrayMap* map, int index) {
  90.     memmove(&map->m_tab[index], &map->m_tab[index + 1], SIZEOF_NODE(map->m_tab_len - index));
  91.     memset(&map->m_tab[map->m_tab_len], 0, sizeof(ArrayMapNode));
  92.     map->m_tab_len--;
  93. }
  94.  
  95. int arraymap_put(ArrayMap* map, void* key, void* val) {
  96.     int index = index_for_key(map, key);
  97.     if (index == -1) {
  98.         insert_entry(map, key, val);
  99.         return AM_ENTRY_INSERTED;
  100.     }
  101.  
  102.     ((ArrayMapNode*) &map->m_tab[index])->m_val = val;
  103.     return AM_ENTRY_REPLACED;
  104. }
  105.  
  106. int arraymap_get_node(ArrayMap* map, void* key, ArrayMapNode** out_node) {
  107.     int index = index_for_key(map, key);
  108.     if (index == -1)
  109.         return 0;
  110.     *out_node = &map->m_tab[index];
  111.     return 1;
  112. }
  113.  
  114. void* arraymap_get(ArrayMap* map, void* key) {
  115.     ArrayMapNode* node;
  116.     if (arraymap_get_node(map, key, &node))
  117.         return node->m_val;
  118.     return nullptr;
  119. }
  120.  
  121. int arraymap_try_get(ArrayMap* map, void* key, void** val) {
  122.     ArrayMapNode* node;
  123.     if (!arraymap_get_node(map, key, &node))
  124.         return 0;
  125.     *val = node->m_val;
  126.     return 1;
  127. }
  128.  
  129. int arraymap_remove(ArrayMap* map, void* key) {
  130.     int index = index_for_key(map, key);
  131.     if (index == -1)
  132.         return 0;
  133.     remove_at_index(map, index);
  134.     return 1;
  135. }
  136.  
  137. void arraymap_clear(ArrayMap* map) {
  138.     memset(map->m_tab, 0, SIZEOF_NODE(map->m_tab_len));
  139.     map->m_tab_len = 0;
  140. }
  141.  
  142. #undef SIZEOF_NODE
  143. #endif //REGHZYLIBS_ARRAYMAP_H
  144.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement