Advertisement
_vim_

ht.c

Dec 19th, 2019
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.10 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. #include "ht.h"
  6.  
  7. #define RETURN_IF_NULL(p) \
  8.     if (p == NULL)        \
  9.         return NULL;
  10.  
  11. size_t hash(const char *key)
  12. {
  13.     size_t val = 0, i, key_length = strlen(key);
  14.  
  15.     for (i = 0; i < key_length; ++i)
  16.         val = val * 37 + key[i];
  17.  
  18.     /* value must be between 0 <= val < TABLE_SIZE */
  19.     val %= TABLE_SIZE;
  20.  
  21.     return val;
  22. }
  23.  
  24. Entry *ht_pair(const char *key, const char *val)
  25. {
  26.     /* allocate the entry */
  27.     Entry *entry = malloc(sizeof(Entry) * 1);
  28.  
  29.     RETURN_IF_NULL(entry);
  30.  
  31.     entry->key = malloc(strlen(key) + 1);
  32.     entry->val = malloc(strlen(val) + 1);
  33.  
  34.     /* copy the key and value in place */
  35.     strcpy(entry->key, key);
  36.     strcpy(entry->val, val);
  37.  
  38.     /* next starts out null but may be set later on */
  39.     entry->next = NULL;
  40.  
  41.     return entry;
  42. }
  43.  
  44. HT *ht_init(void)
  45. {
  46.     /* allocate table */
  47.     HT *ht = malloc(sizeof(HT) * 1);
  48.  
  49.     RETURN_IF_NULL(ht);
  50.  
  51.     /* allocate table entries */
  52.     ht->entries = malloc(sizeof(Entry *) * TABLE_SIZE);
  53.  
  54.     /* set each to null (needed for proper operation) */
  55.     size_t i;
  56.     for (i = 0; i < TABLE_SIZE; ++i)
  57.         ht->entries[i] = NULL;
  58.  
  59.     return ht;
  60. }
  61.  
  62. void ht_set(HT *ht, const char *key, const char *val)
  63. {
  64.     size_t slot = hash(key);
  65.  
  66.     /* try to look up an entry set */
  67.     Entry *entry = ht->entries[slot];
  68.  
  69.     /* no entry means slot empty, insert immediately */
  70.     if (entry == NULL)
  71.     {
  72.         ht->entries[slot] = ht_pair(key, val);
  73.         return;
  74.     }
  75.  
  76.     Entry *prev;
  77.  
  78.     /* walk through each entry until either the end is
  79.     reached or a matching key is found */
  80.     while (entry != NULL)
  81.     {
  82.         /* check key */
  83.         if (strcmp(entry->key, key) == 0)
  84.         {
  85.             /* match found, replace val */
  86.             free(entry->val);
  87.             entry->val = malloc(strlen(val) + 1);
  88.             strcpy(entry->val, val);
  89.             return;
  90.         }
  91.  
  92.         /* walk to next */
  93.         prev = entry;
  94.         entry = prev->next;
  95.     }
  96.  
  97.     /* end of chain reached without a match, add new */
  98.     prev->next = ht_pair(key, val);
  99. }
  100.  
  101. char *ht_get(HT *ht, const char *key)
  102. {
  103.     size_t slot = hash(key);
  104.  
  105.     /* try to find a valid slot */
  106.     Entry *entry = ht->entries[slot];
  107.  
  108.     /* no slot means no entry */
  109.     RETURN_IF_NULL(entry);
  110.  
  111.     /* walk through each entry in the slot, which could just be a single thing */
  112.     while (entry != NULL)
  113.     {
  114.         /* return value if found */
  115.         if (strcmp(entry->key, key) == 0)
  116.             return entry->val;
  117.  
  118.         /* proceed to next key if available */
  119.         entry = entry->next;
  120.     }
  121.  
  122.     /* reaching here means there were >= 1 entries but no key match */
  123.     return NULL;
  124. }
  125.  
  126. int ht_has(HT *ht, const char *key)
  127. {
  128.     size_t slot = hash(key);
  129.  
  130.     /* try to find a valid slot */
  131.     Entry *entry = ht->entries[slot];
  132.  
  133.     /* no slot means no entry */
  134.     if (entry == NULL)
  135.         return 0;
  136.  
  137.     /* walk through each entry in the slot, which could just be a single thing */
  138.     while (entry != NULL)
  139.     {
  140.         /* return value if found */
  141.         if (strcmp(entry->key, key) == 0)
  142.             return 1;
  143.  
  144.         /* proceed to next key if available */
  145.         entry = entry->next;
  146.     }
  147.  
  148.     /* reaching here means there were >= 1 entries but no key match */
  149.     return 0;
  150. }
  151.  
  152. void ht_del(HT *ht, const char *key)
  153. {
  154.     size_t slot = hash(key);
  155.  
  156.     /* try to find a valid slot */
  157.     Entry *entry = ht->entries[slot];
  158.  
  159.     /* no slot means no entry */
  160.     if (entry == NULL)
  161.         return;
  162.  
  163.     Entry *prev;
  164.     int idx = 0;
  165.  
  166.     /* walk through each entry until either the end is reached or a matching key is found */
  167.     while (entry != NULL)
  168.     {
  169.         /* check key */
  170.         if (strcmp(entry->key, key) == 0)
  171.         {
  172.             /* first item and no next entry */
  173.             if (entry->next == NULL && idx == 0)
  174.                 ht->entries[slot] = NULL;
  175.  
  176.             /* first item with a next entry */
  177.             if (entry->next != NULL && idx == 0)
  178.                 ht->entries[slot] = entry->next;
  179.  
  180.             /* last item */
  181.             if (entry->next == NULL && idx != 0)
  182.                 prev->next = NULL;
  183.  
  184.             /* middle item */
  185.             if (entry->next != NULL && idx != 0)
  186.                 prev->next = entry->next;
  187.  
  188.             /* free the deleted entry */
  189.             free(entry->key);
  190.             free(entry->val);
  191.             free(entry);
  192.  
  193.             return;
  194.         }
  195.  
  196.         /* walk to next */
  197.         prev = entry;
  198.         entry = prev->next;
  199.  
  200.         ++idx;
  201.     }
  202. }
  203.  
  204. #ifdef DEBUG
  205. void ht_debug(HT *ht)
  206. {
  207.     size_t i;
  208.     for (i = 0; i < TABLE_SIZE; ++i)
  209.     {
  210.         Entry *entry = ht->entries[i];
  211.  
  212.         if (entry == NULL)
  213.             continue;
  214.  
  215.         printf("slot[%lu]: ", i);
  216.  
  217.         while (1)
  218.         {
  219.             printf("%s = %s ", entry->key, entry->val);
  220.  
  221.             if (entry->next == NULL)
  222.                 break;
  223.  
  224.             entry = entry->next;
  225.         }
  226.  
  227.         printf("\n");
  228.     }
  229. }
  230. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement