⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gbx_hash.c

📁 Gambas is a graphical development environment based on a Basic interpreter, like Visual Basic. It us
💻 C
字号:
/***************************************************************************  hash.c  hash table routines, adapted from glib 1.2.8  (c) 2000-2004 Beno顃 Minisini <gambas@users.sourceforge.net>  This program is free software; you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the Free Software Foundation; either version 1, or (at your option)  any later version.  This program is distributed in the hope that it will be useful,  but WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License for more details.  You should have received a copy of the GNU General Public License  along with this program; if not, write to the Free Software  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.***************************************************************************/#define __GBX_HASH_C#include <ctype.h>#include "gb_common.h"#include "gb_common_case.h"#include "gb_alloc.h"#include "gbx_hash.h"#define NODE_key(htable, node) (((char *)node) + sizeof(HASH_NODE) + htable->s_value)#define NODE_value(node) ((void *)((char *)node) + sizeof(HASH_NODE))PRIVATE void hash_table_resize(HASH_TABLE *hash_table);PRIVATE HASH_NODE **hash_table_lookup_node(HASH_TABLE *hash_table, const char *key, long len);PRIVATE HASH_NODE *hash_node_new(HASH_TABLE *hash_table, const char *key, long len);PRIVATE void hash_node_destroy(HASH_NODE *hash_node);PRIVATE void hash_nodes_destroy(HASH_NODE *hash_node);PRIVATE const long primes[] ={  11, 19, 37, 73, 109, 163, 251, 367, 557, 823, 1237, 1861, 2777, 4177, 6247, 9371,  14057, 21089, 31627, 47431, 71143, 106721, 160073, 240101, 360163, 540217, 810343,  1215497, 1823231, 2734867, 4102283, 6153409, 9230113, 13845163};PRIVATE const long nprimes = sizeof (primes) / sizeof (primes[0]);PRIVATE long spaced_primes_closest(long num){  int i;  for (i = 0; i < nprimes; i++)    if (primes[i] > num)      return primes[i];  return primes[nprimes - 1];}PRIVATE boolean key_equal_binary(const char *key_comp, const char *key, long len){  return (!strncmp(key_comp, key, len) && (!key_comp[len]));}PRIVATE boolean key_equal_text(const char *key_comp, const char *key, long len){  return (!strncasecmp(key_comp, key, len) && (!key_comp[len]));}PRIVATE ulong key_hash_binary(const char *key, long len){  int i;  ulong hash = 0;  if (len >= 0)  {    for (i = 0; i < len; i++)      hash = (hash << 4) + (hash ^ key[i]);  }  else  {    for(i = 0; ; i++)    {      if (!key[i])        break;      hash = (hash << 4) + (hash ^ key[i]);    }  }  return hash;}PRIVATE ulong key_hash_text(const char *key, long len){  int i;  ulong hash = 0;  if (len >= 0)  {    for (i = 0; i < len; i++)      hash = (hash << 4) + (hash ^ toupper(key[i]));  }  else  {    for(i = 0; ; i++)    {      if (!key[i])        break;      hash = (hash << 4) + (hash ^ toupper(key[i]));    }  }  return hash;}PRIVATE HASH_COMP get_comp_func(HASH_TABLE *hash){  if (hash->mode == GB_COMP_TEXT)    return key_equal_text;  else    return key_equal_binary;}PRIVATE HASH_FUNC get_hash_func(HASH_TABLE *hash){  if (hash->mode == GB_COMP_TEXT)    return key_hash_text;  else    return key_hash_binary;}PUBLIC void HASH_TABLE_create(HASH_TABLE **hash, size_t s_value, int mode){  HASH_TABLE *hash_table;  /*int i;*/  ALLOC_ZERO(&hash_table, sizeof(HASH_TABLE), "HASH_TABLE_create");  hash_table->size = HASH_TABLE_MIN_SIZE;  hash_table->s_value = s_value;  ALLOC_ZERO(&hash_table->nodes, sizeof(HASH_NODE) * hash_table->size, "HASH_TABLE_create");  if (mode == GB_COMP_TEXT)    hash_table->mode = mode;  else    hash_table->mode = GB_COMP_BINARY;  *hash = hash_table;}PUBLIC void HASH_TABLE_delete(HASH_TABLE **hash){  int i;  HASH_TABLE *hash_table = *hash;  if (hash_table == NULL)    return;  for (i = 0; i < hash_table->size; i++)    hash_nodes_destroy(hash_table->nodes[i]);  FREE(&hash_table->nodes, "HASH_TABLE_delete");  FREE(hash, "HASH_TABLE_delete");}PUBLIC long HASH_TABLE_size(HASH_TABLE *hash_table){  return hash_table->nnodes;}PRIVATE HASH_NODE **hash_table_lookup_node(HASH_TABLE *hash_table, const char *key, long len){  HASH_NODE **node;  HASH_FUNC hash_func = get_hash_func(hash_table);  HASH_COMP comp_func = get_comp_func(hash_table);  node = &hash_table->nodes[(*hash_func)(key, len) % hash_table->size];  while (*node && !(*comp_func)(NODE_key(hash_table, *node), key, len))    node = &(*node)->next;  return node;}PUBLIC void *HASH_TABLE_lookup(HASH_TABLE *hash_table, const char *key, long len){  HASH_NODE *node;  node = *hash_table_lookup_node(hash_table, key, len);  hash_table->last = node;  return node ? NODE_value(node) : NULL;}PUBLIC void *HASH_TABLE_insert(HASH_TABLE *hash_table, const char *key, long len){  HASH_NODE **node;  node = hash_table_lookup_node(hash_table, key, len);  if (*node)    return NODE_value(*node);  /*hash_table_resize(hash_table);*/  *node = hash_node_new(hash_table, key, len);  hash_table->nnodes++;  /*if (!hash_table->frozen)*/  return NODE_value(*node);}PUBLIC void HASH_TABLE_remove(HASH_TABLE *hash_table, const char *key, long len){  HASH_NODE **node, *dest;  node = hash_table_lookup_node(hash_table, key, len);  if (*node)  {    dest = *node;    (*node) = dest->next;    #ifdef KEEP_ORDER    if (dest->sprev)      dest->sprev->snext = dest->snext;    else      hash_table->sfirst = dest->snext;    if (dest->snext)      dest->snext->sprev = dest->sprev;    else      hash_table->slast = dest->sprev;    #endif    hash_node_destroy(dest);    hash_table->nnodes--;    hash_table->last = NULL;    /*if (!hash_table->frozen)*/    hash_table_resize(hash_table);  }}PUBLIC void *HASH_TABLE_next(HASH_TABLE *hash_table, HASH_ENUM *iter){  #ifdef KEEP_ORDER  if (iter->node == NULL)    iter->node = hash_table->sfirst;  else    iter->node = iter->next;  hash_table->last = iter->node;  if (iter->node)  {    iter->next = iter->node->snext;    return NODE_value(iter->node);  }  else    return NULL;  #else  HASH_NODE *enum_node = iter->node;  long enum_i = iter->index;  if (enum_node)    enum_node = enum_node->next;  while (enum_node == NULL)  {    enum_i++;    if (enum_i >= hash_table->size)      break;    enum_node = hash_table->nodes[enum_i];  };  iter->node = enum_node;  iter->index = enum_i;  hash_table->last = enum_node;  if (enum_node)    return NODE_value(enum_node);  else    return NULL;  #endif}/*void HASH_TABLE_foreach (HASH_TABLE *hash_table,        GHFunc   func,        gpointer   user_data){  HASH_NODE *node;  gint i;  g_return_if_fail (hash_table != NULL);  g_return_if_fail (func != NULL);  for (i = 0; i < hash_table->size; i++)    for (node = hash_table->nodes[i]; node; node = node->next)      (* func) (node->key, node->value, user_data);}*/PRIVATE void hash_table_resize(HASH_TABLE *hash_table){  HASH_NODE **new_nodes;  HASH_NODE *node;  HASH_NODE *next;  char *node_key;  double nodes_per_list;  long hash_val;  long new_size;  long i;  HASH_FUNC hash_func = get_hash_func(hash_table);  nodes_per_list = hash_table->nnodes / hash_table->size;  if ((nodes_per_list > 0.3 || hash_table->size <= HASH_TABLE_MIN_SIZE) &&      (nodes_per_list < 3.0 || hash_table->size >= HASH_TABLE_MAX_SIZE))    return;  new_size = MinMax(spaced_primes_closest(hash_table->nnodes), HASH_TABLE_MIN_SIZE, HASH_TABLE_MAX_SIZE);  ALLOC_ZERO(&new_nodes, new_size * sizeof(HASH_NODE *), "hash_table_resize");  for (i = 0; i < hash_table->size; i++)    for (node = hash_table->nodes[i]; node; node = next)      {        next = node->next;        node_key = NODE_key(hash_table, node);        hash_val = (*hash_func)(node_key, -1) % new_size;        node->next = new_nodes[hash_val];        new_nodes[hash_val] = node;      }  FREE(&hash_table->nodes, "hash_table_resize");  hash_table->nodes = new_nodes;  hash_table->size = new_size;}PRIVATE HASH_NODE *hash_node_new(HASH_TABLE *hash_table, const char *key, long len){  HASH_NODE *hash_node;  int size;  char *node_key;  size = sizeof(HASH_NODE) + hash_table->s_value + len + 1;  ALLOC_ZERO(&hash_node, size, "hash_node_new");  node_key = NODE_key(hash_table, hash_node);  strncpy(node_key, key, len);  node_key[len] = 0;  #ifdef KEEP_ORDER  if (!hash_table->sfirst)  {    hash_table->sfirst = hash_node;    hash_table->slast = hash_node;  }  else  {    hash_node->sprev = hash_table->slast;    hash_node->sprev->snext = hash_node;    hash_table->slast = hash_node;  }  #endif  return hash_node;}PRIVATE void hash_node_destroy(HASH_NODE *hash_node){  FREE(&hash_node, "hash_node_destroy");}PRIVATE void hash_nodes_destroy(HASH_NODE *hash_node){  HASH_NODE *node = hash_node;  HASH_NODE *next;  for(;;)  {    if (node == NULL)      return;    next = node->next;    FREE(&node, "hash_nodes_destroy");    node = next;  }}PUBLIC bool HASH_TABLE_get_last_key(HASH_TABLE *hash_table, char **key, long *len){  if (hash_table->last == NULL)    return TRUE;  *key = NODE_key(hash_table, hash_table->last);  *len = strlen(*key);  return FALSE;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -