hash.c
上传用户:ig0539
上传日期:2022-05-21
资源大小:181k
文件大小:3k
源码类别:

Ftp客户端

开发平台:

C/C++

  1. /*
  2.  * Part of Very Secure FTPd
  3.  * Licence: GPL v2
  4.  * Author: Chris Evans
  5.  * hash.c
  6.  *
  7.  * Routines to handle simple hash table lookups and modifications.
  8.  */
  9. #include "hash.h"
  10. #include "sysutil.h"
  11. #include "utility.h"
  12. struct hash_node
  13. {
  14.   void* p_key;
  15.   void* p_value;
  16.   struct hash_node* p_prev;
  17.   struct hash_node* p_next;
  18. };
  19. struct hash
  20. {
  21.   unsigned int buckets;
  22.   unsigned int key_size;
  23.   unsigned int value_size;
  24.   hashfunc_t hash_func;
  25.   struct hash_node** p_nodes;
  26. };
  27. /* Internal functions */
  28. struct hash_node** hash_get_bucket(struct hash* p_hash, void* p_key);
  29. struct hash_node* hash_get_node_by_key(struct hash* p_hash, void* p_key);
  30. struct hash*
  31. hash_alloc(unsigned int buckets, unsigned int key_size,
  32.            unsigned int value_size, hashfunc_t hash_func)
  33. {
  34.   unsigned int size;
  35.   struct hash* p_hash = vsf_sysutil_malloc(sizeof(*p_hash));
  36.   p_hash->buckets = buckets;
  37.   p_hash->key_size = key_size;
  38.   p_hash->value_size = value_size;
  39.   p_hash->hash_func = hash_func;
  40.   size = sizeof(struct hash_node*) * buckets;
  41.   p_hash->p_nodes = vsf_sysutil_malloc(size);
  42.   vsf_sysutil_memclr(p_hash->p_nodes, size);
  43.   return p_hash;
  44. }
  45. void*
  46. hash_lookup_entry(struct hash* p_hash, void* p_key)
  47. {
  48.   struct hash_node* p_node = hash_get_node_by_key(p_hash, p_key);
  49.   if (!p_node)
  50.   {
  51.     return p_node;
  52.   }
  53.   return p_node->p_value;
  54. }
  55. void
  56. hash_add_entry(struct hash* p_hash, void* p_key, void* p_value)
  57. {
  58.   struct hash_node** p_bucket;
  59.   struct hash_node* p_new_node;
  60.   if (hash_lookup_entry(p_hash, p_key))
  61.   {
  62.     bug("duplicate hash key");
  63.   }
  64.   p_bucket = hash_get_bucket(p_hash, p_key);
  65.   p_new_node = vsf_sysutil_malloc(sizeof(*p_new_node));
  66.   p_new_node->p_prev = 0;
  67.   p_new_node->p_next = 0;
  68.   p_new_node->p_key = vsf_sysutil_malloc(p_hash->key_size);
  69.   vsf_sysutil_memcpy(p_new_node->p_key, p_key, p_hash->key_size);
  70.   p_new_node->p_value = vsf_sysutil_malloc(p_hash->value_size);
  71.   vsf_sysutil_memcpy(p_new_node->p_value, p_value, p_hash->value_size);
  72.   if (!*p_bucket)
  73.   {
  74.     *p_bucket = p_new_node;    
  75.   }
  76.   else
  77.   {
  78.     p_new_node->p_next = *p_bucket;
  79.     (*p_bucket)->p_prev = p_new_node;
  80.     *p_bucket = p_new_node;
  81.   }
  82. }
  83. void
  84. hash_free_entry(struct hash* p_hash, void* p_key)
  85. {
  86.   struct hash_node* p_node = hash_get_node_by_key(p_hash, p_key);
  87.   if (!p_node)
  88.   {
  89.     bug("hash node not found");
  90.   }
  91.   vsf_sysutil_free(p_node->p_key);
  92.   vsf_sysutil_free(p_node->p_value);
  93.   if (p_node->p_prev)
  94.   {
  95.     p_node->p_prev->p_next = p_node->p_next;
  96.   }
  97.   else
  98.   {
  99.     struct hash_node** p_bucket = hash_get_bucket(p_hash, p_key);
  100.     *p_bucket = p_node->p_next;
  101.   }
  102.   if (p_node->p_next)
  103.   {
  104.     p_node->p_next->p_prev = p_node->p_prev;
  105.   }
  106.   vsf_sysutil_free(p_node);
  107. }
  108. struct hash_node**
  109. hash_get_bucket(struct hash* p_hash, void* p_key)
  110. {
  111.   unsigned int bucket = (*p_hash->hash_func)(p_hash->buckets, p_key);
  112.   if (bucket >= p_hash->buckets)
  113.   {
  114.     bug("bad bucket lookup");
  115.   }
  116.   return &(p_hash->p_nodes[bucket]);
  117. }
  118. struct hash_node*
  119. hash_get_node_by_key(struct hash* p_hash, void* p_key)
  120. {
  121.   struct hash_node** p_bucket = hash_get_bucket(p_hash, p_key);
  122.   struct hash_node* p_node = *p_bucket;
  123.   if (!p_node)
  124.   {
  125.     return p_node;
  126.   }
  127.   while (p_node != 0 &&
  128.          vsf_sysutil_memcmp(p_key, p_node->p_key, p_hash->key_size) != 0)
  129.   {
  130.     p_node = p_node->p_next;
  131.   }
  132.   return p_node;
  133. }