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

📄 hash.c

📁 xorp源码hg
💻 C
📖 第 1 页 / 共 2 页
字号:
  } else {    node = _new_HashNode(hash, name, code, fn, data, del_fn);    if(!node)      return NULL;  };/* * Install the node at the head of the hash-bucket list. */  node->next = bucket->head;  bucket->head = node;  bucket->count++;  return &node->symbol;}/*....................................................................... * Remove and delete a given hash-table entry. * * Input: *  hash   HashTable *  The hash table to find the symbol in. *  name  const char *  The name of the entry. * Output: *  return  HashNode *  The deleted hash node (always NULL). */Symbol *_del_HashSymbol(HashTable *hash, const char *name){  if(hash && name) {    HashBucket *bucket = _find_HashBucket(hash, name);    HashNode *prev;   /* The node preceding the located node */    HashNode *node = _find_HashNode(hash, bucket, name, &prev);/* * Node found? */    if(node) {/* * Remove the node from the bucket list. */      if(prev) {	prev->next = node->next;      } else {	bucket->head = node->next;      };/* * Record the loss of a node. */      bucket->count--;/* * Delete the node. */      (void) _del_HashNode(hash, node);    };  };  return NULL;}/*....................................................................... * Look up a symbol in the hash table. * * Input: *  hash   HashTable *   The table to look up the string in. *  name  const char *   The name of the symbol to look up. * Output: *  return    Symbol *   The located hash-table symbol, or NULL if not *                       found. */Symbol *_find_HashSymbol(HashTable *hash, const char *name){  HashBucket *bucket;  /* The hash-table bucket associated with name[] */  HashNode *node;      /* The hash-table node of the requested symbol *//* * Check arguments. */  if(!hash)    return NULL;/* * Nothing to lookup? */  if(!name)    return NULL;/* * Hash the name to a hash-table bucket. */  bucket = _find_HashBucket(hash, name);/* * Find the bucket entry that exactly matches the name. */  node = _find_HashNode(hash, bucket, name, NULL);  if(!node)    return NULL;  return &node->symbol;}/*....................................................................... * Private function used to allocate a hash-table node. * The caller is responsible for checking that the specified symbol * is unique and for installing the returned entry in the table. * * Input: *  hash     HashTable *  The table to allocate the node for. *  name    const char *  The name of the new entry. *  code           int    A user-supplied context code. *  fn  void (*)(void)    A user-supplied function pointer. *  data          void *  A user-supplied data pointer. *  del_fn  SYM_DEL_FN(*) An optional 'data' destructor function. * Output: *  return    HashNode *  The new node, or NULL on error. */static HashNode *_new_HashNode(HashTable *hash, const char *name, int code,			      void (*fn)(void), void *data, SYM_DEL_FN(*del_fn)){  HashNode *node;  /* The new node *//* * Allocate the new node from the free list. */  node = (HashNode *) _new_FreeListNode(hash->mem->node_memory);  if(!node)    return NULL;/* * Before attempting any operation that might fail, initialize the * contents of 'node' at least up to the point at which it can be * safely passed to _del_HashNode(). */  node->symbol.name = NULL;  node->symbol.code = code;  node->symbol.fn = fn;  node->symbol.data = data;  node->symbol.del_fn = del_fn;  node->next = NULL;/* * Allocate a copy of 'name'. */  node->symbol.name = _new_StringMemString(hash->mem->string_memory,					  strlen(name) + 1);  if(!node->symbol.name)    return _del_HashNode(hash, node);/* * If character-case is insignificant in the current table, convert the * name to lower case while copying it. */  if(hash->case_sensitive) {    strcpy(node->symbol.name, name);  } else {    const char *src = name;    char *dst = node->symbol.name;    for( ; *src; src++,dst++)      *dst = tolower((int)(unsigned char) *src);    *dst = '\0';  };  return node;}/*....................................................................... * Private function used to delete a hash-table node. * The node must have been removed from its list before calling this * function. * * Input: *  hash   HashTable *  The table for which the node was originally *                      allocated. *  node    HashNode *  The node to be deleted. * Output: *  return  HashNode *  The deleted node (always NULL). */static HashNode *_del_HashNode(HashTable *hash, HashNode *node){  if(node) {    node->symbol.name = _del_StringMemString(hash->mem->string_memory,					    node->symbol.name);/* * Call the user-supplied data-destructor if provided. */    if(node->symbol.data && node->symbol.del_fn)      node->symbol.data = node->symbol.del_fn(hash->app_data,					      node->symbol.code,					      node->symbol.data);/* * Return the node to the free-list. */    node->next = NULL;    node = (HashNode *) _del_FreeListNode(hash->mem->node_memory, node);  };  return NULL;}/*....................................................................... * Private function to locate the hash bucket associated with a given * name. * * This uses a hash-function described in the dragon-book * ("Compilers - Principles, Techniques and Tools", by Aho, Sethi and *  Ullman; pub. Adison Wesley) page 435. * * Input: *  hash    HashTable *   The table to look up the string in. *  name   const char *   The name of the symbol to look up. * Output: *  return HashBucket *   The located hash-bucket. */static HashBucket *_find_HashBucket(HashTable *hash, const char *name){  unsigned const char *kp;  unsigned long h = 0L;  if(hash->case_sensitive) {    for(kp=(unsigned const char *) name; *kp; kp++)      h = 65599UL * h + *kp;  /* 65599 is a prime close to 2^16 */  } else {    for(kp=(unsigned const char *) name; *kp; kp++)      h = 65599UL * h + tolower((int)*kp);  /* 65599 is a prime close to 2^16 */  };  return hash->bucket + (h % hash->size);}/*....................................................................... * Search for a given name in the entries of a given bucket. * * Input: *  hash     HashTable *  The hash-table being searched. *  bucket  HashBucket *  The bucket to search (use _find_HashBucket()). *  name    const char *  The name to search for. * Output: *  prev      HashNode ** If prev!=NULL then the pointer to the node *                        preceding the located node in the list will *                        be recorded in *prev. This will be NULL either *                        if the name is not found or the located node is *                        at the head of the list of entries. * return     HashNode *  The located hash-table node, or NULL if not *                        found. */static HashNode *_find_HashNode(HashTable *hash, HashBucket *bucket,			       const char *name, HashNode **prev){  HashNode *last;  /* The previously searched node */  HashNode *node;  /* The node that is being searched *//* * Search the list for a node containing the specified name. */  for(last=NULL, node=bucket->head;      node && hash->keycmp(node->symbol.name, name)!=0;      last = node, node=node->next)    ;  if(prev)    *prev = node ? last : NULL;  return node;}/*....................................................................... * When hash->case_sensitive is zero this function is called * in place of strcmp(). In such cases the hash-table names are stored * as lower-case versions of the original strings so this function * performs the comparison against lower-case copies of the characters * of the string being compared. * * Input: *  node_key   const char *  The lower-case hash-node key being compared *                           against. *  look_key   const char *  The lookup key. * Output: *  return            int    <0 if node_key < look_key. *                            0 if node_key == look_key. *                           >0 if node_key > look_key. */static int _ht_lower_strcmp(const char *node_key, const char *look_key){  int cn;  /* The latest character from node_key[] */  int cl;  /* The latest character from look_key[] */  do {    cn = *node_key++;    cl = *look_key++;  } while(cn && cn==tolower((int)(unsigned char) cl));  return cn - tolower((int)(unsigned char) cl);}/*....................................................................... * This is a wrapper around strcmp for comparing hash-keys in a case * sensitive manner. The reason for having this wrapper, instead of using * strcmp() directly, is to make some C++ compilers happy. The problem * is that when the library is compiled with a C++ compiler, the * declaration of the comparison function is a C++ declaration, whereas * strcmp() is a pure C function and thus although it appears to have the * same declaration, the compiler disagrees. * * Input: *  node_key   char *  The lower-case hash-node key being compared against. *  look_key   char *  The lookup key. * Output: *  return      int    <0 if node_key < look_key. *                      0 if node_key == look_key. *                     >0 if node_key > look_key. */static int _ht_strcmp(const char *node_key, const char *look_key){  return strcmp(node_key, look_key);}/*....................................................................... * Empty a hash-table by deleting all of its entries. * * Input: *  hash    HashTable *  The hash table to clear. * Output: *  return        int    0 - OK. *                       1 - Invalid arguments. */int _clear_HashTable(HashTable *hash){  int i;/* * Check the arguments. */  if(!hash)    return 1;/* * Clear the contents of the bucket array. */  for(i=0; i<hash->size; i++) {    HashBucket *bucket = hash->bucket + i;/* * Delete the list of active hash nodes from the bucket. */    HashNode *node = bucket->head;    while(node) {      HashNode *next = node->next;      (void) _del_HashNode(hash, node);      node = next;    };/* * Mark the bucket as empty. */    bucket->head = NULL;    bucket->count = 0;  };  return 0;}/*....................................................................... * Execute a given function on each entry of a hash table, returning * before completion if the the specified function returns non-zero. * * Input: *  hash       HashTable *    The table to traverse. *  scan_fn HASH_SCAN_FN(*)   The function to call. *  context         void *    Optional caller-specific context data *                            to be passed to scan_fn(). * Output: *  return           int      0 - OK. *                            1 - Either the arguments were invalid, or *                                scan_fn() returned non-zero at some *                                point. */int _scan_HashTable(HashTable *hash, HASH_SCAN_FN(*scan_fn), void *context){  int i;/* * Check the arguments. */  if(!hash || !scan_fn)    return 1;/* * Iterate through the buckets of the table. */  for(i=0; i<hash->size; i++) {    HashBucket *bucket = hash->bucket + i;    HashNode *node;/* * Iterate through the list of symbols that fall into bucket i, * passing each one to the caller-specified function. */    for(node=bucket->head; node; node=node->next) {      if(scan_fn(&node->symbol, context))	return 1;    };  };  return 0;}

⌨️ 快捷键说明

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