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

📄 hashtable.c

📁 mobile ip 在linux下的一种实现
💻 C
字号:
/* $Id: hashtable.c,v 1.27 2000/04/06 07:26:53 jm Exp $ * This file defines the interface of hashtable. * * Dynamic hierarchial IP tunnel * Copyright (C) 1998-2000, Dynamics group * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See README and COPYING for * more details. */#include <stdio.h>#include <stdlib.h>#include <assert.h>#include "owntypes.h"#include "hashtable.h"#include "list.h"#include "debug.h"/* defines */#ifndef TRUE#define TRUE 1#endif#ifndef FALSE#define FALSE 0#endif#define DEBUG_FLAG 'h'#define ASSERT assert/* Test cases *//* #define HASHTABLE_TEST_CASE_M03 *//* NOTE! The internal structure of the hashtable is an array that has * pointers to collision lists. *//* * The idea is to give a freedom to use any hashfunction. * * We do not make any assumptions about the data to be added, but as * this module is using the list module to store the values, the * pointer must point to a node structure. Read more information about * how to use the nodes and lists from the list module. * * All the hashtable module functions begin with the word 'hashtable_'. *//* "Ixx" are test case IDs to help in the design of the test module *//* hashtable_init allocates the memory for the structures and lists. * It also initializes the lists. * * INPUT VALUES: * * M01) size is zero * M02) size is negative * M03) not enough memory for struct hashtable *      - requires changes in code, will be tested manually * M04) size is too large for malloc to succeed (not enough memory) * M05) realistic values * *//** * hashtable_init: * @size: size of the table *  * Allocate the memory for the structures and lists. * It also initializes the lists. *  * Returns: Pointer to table, or NULL if failed */struct hashtable *hashtable_init(int size){	int i;	struct hashtable *table;	DEBUG(DEBUG_FLAG, "Initializing hashtable!\n");	if (size < 1) {		fprintf(stderr, "hashtable_init: Size must be at least 1\n");		return NULL;	}#ifdef HASHTABLE_TEST_CASE_M03	table = malloc((unsigned int) -1);#else	table = malloc(sizeof(struct hashtable)); #endif	if (table == NULL) {		fprintf(stderr, "hashtable_init: Not enough memory!\n");		return NULL;	}	/* Initialize the array and lists. */	table->hasharray = malloc(sizeof(struct list) * size);	if (table->hasharray == NULL) {		fprintf(stderr,			"hashtable_init: Not enough memory for hasharray!\n");		free(table);		return NULL;	}	DEBUG(DEBUG_FLAG, "hashtable_init: Initializing collision lists.\n");	for (i = 0; i < size; i++) {		list_init(&table->hasharray[i]);	}	table->hashtablesize = size;	ASSERT(table->hashtablesize == size);	return table;}/* * INPUT VALUES: * * M06) table is not empty * M07) table is empty *    ) table is NULL * *//** * hashtable_destroy: * @table:  *  * The user should remove all nodes before destroying the hash table object. * This can't do it, because it has no way to know how the memory was * allocated to the entry. This removed the entries from the list and returns * FALSE as a warning that there was something in the hashtable. * Even though FALSE is returned, it's just a warning and the hashtable has * already been destroyed. * * We start destroying the hashtable from inside: * - the list nodes * - the hasharray * - the hashtable structure * * Returns:  */int hashtable_destroy(struct hashtable *table){	int i, status;	DEBUG(DEBUG_FLAG, "hashtable_destroy: Destroying hashtable!\n");	ASSERT(table != NULL);	status = TRUE;	for (i = 0; i < table->hashtablesize; i++) {		while(list_remove_first(&table->hasharray[i]) != NULL) {			fprintf(stderr,				"hashtable_destroy: Warning! Removing node "				"from list at index %d\n", i);			status = FALSE;		}	}	free(table->hasharray);	free(table);	return status;}/* INPUT VALUES: * * M08) hash function is invalid * M09) hash function is valid *    ) table is NULL *    ) hashfunc is NULL *    ) entry is NULL * *//** * hashtable_add: * @table: pointer to the hashtable structure  * @hashfunc: function that returns the hash value * @key: key input to the hash function * @entry: node to be added to the list * * Add entry to hash table. * Care must be taken that the same node isn't added twice!  * * Returns: TRUE if completed successfully, otherwise FALSE */int hashtable_add(struct hashtable *table,		  int (*hashfunc)(void *key, const int hashsize),		  void *key,		  struct node *entry){	int hashvalue;	DEBUG(DEBUG_FLAG,	      "hashtable_add: Adding entry to the hashtable.\n");	ASSERT(table != NULL);	ASSERT(hashfunc != NULL);	ASSERT(entry != NULL);	hashvalue = (*hashfunc)(key, table->hashtablesize);	if (hashvalue < 0 || hashvalue >= table->hashtablesize) {		fprintf(stderr,			"hashtable_add: invalid hash function, "			"returned %d that is out of the range [0,%d]\n",			hashvalue, table->hashtablesize - 1);		return FALSE;	}	list_add_tail(&table->hasharray[hashvalue], entry);	return TRUE;}/* INPUT VALUES: * * M10) hash function is invalid * M11) node is found * M12) node is not found *    ) table is NULL *    ) hashfunc is NULL *    ) cmpfunc is NULL *    ) cmpfunc is invalid * *//** * hashtable_fetch: * @table: * @hashfunc: * @key: * @cmpfunc: * * Fetch entry from hashtable. * * Returns: A pointer to the found nodem or NULL if nothing is found. */struct node *hashtable_fetch(struct hashtable *table,			     int (*hashfunc)(void *key, const int hashsize),			     void *key,			     int (*cmpfunc)(void *key, struct node *cmprd)){	int hashvalue;	struct node *node;	ASSERT(table != NULL);	ASSERT(hashfunc != NULL);	ASSERT(cmpfunc != NULL);	hashvalue = (*hashfunc)(key, table->hashtablesize);	if (hashvalue < 0 || hashvalue >= table->hashtablesize) {		fprintf(stderr,			"hashtable_fetch: invalid hash function, "			"returned %d that is out of range [0,%d]\n",			hashvalue, table->hashtablesize - 1);		return NULL;	}	node = list_get_first(&table->hasharray[hashvalue]);	while(node != NULL) {		if ((*cmpfunc)(key, node) == TRUE) break;		node = list_get_next(node);	}	return node;}/* INPUT VALUES: * * M13) entry is valid *    ) entry is NULL *    ) entry is invalid (cannot be checked) * *//** * hashtable_remove: * @entry: *  * Remove entry from hashtable */void hashtable_remove(struct node *entry){	ASSERT(entry != NULL);	list_remove(entry);}/* INPUT VALUES: * * M14) entry is found * M15) entry is not found *    ) table is NULL *    ) entry is NULL *    ) entry is invalid (cannot be checked) * *//** * hashtable_find_and_remove: * @table: * @hashfunc: * @key: * @cmpfunc: * * Find and remove entry from hashtable. *  * Returns: TRUE if entry is found, else FALSE */int hashtable_find_and_remove(struct hashtable *table,			      int (*hashfunc)(void *key, const int hashsize),			      void *key,			      int (*cmpfunc)(void *key, struct node *cmprd)){	struct node *node;	ASSERT(table != NULL);	ASSERT(hashfunc != NULL);	ASSERT(cmpfunc != NULL);	node = hashtable_fetch(table, hashfunc, key, cmpfunc);	if (node == NULL) return FALSE;	list_remove(node);	return TRUE;}/* * INPUT VALUES: * * iterator function returning TRUE: * M16) hashtable is empty * M17) hashtable is not empty * M18) hashtable is not empty and remove nodes in iterfunc * iterator function returning FALSE: * M19) hashtable is empty * M20) hashtable is not empty * M21) hashtable is not empty and remove nodes in iterfunc * M28) verify that data is passed to iterfunc *    ) table is NULL *    ) iterfunc is NULL * *//** * hashtable_iterator: * @table: * @iterfunc: * @data: * * Go through every entry in the hashtable until the iterator function returns * FALSE or the hashtable has no more entries. * Data is passed to @iterfunc to allow any user-specified data to be used * in that function. * * Returns: TRUE if the iteration was not stopped by iterator function * and FALSE if it was stopped. */ int hashtable_iterator(struct hashtable *table,		       int (*iterfunc)(struct node *node, void *data),		       void *data){	int i;	struct node *node, *next;	for (i = 0; i < table->hashtablesize; i++) {		node = list_get_first(&table->hasharray[i]);		while (node != NULL) {			next = list_get_next(node);			if ((*iterfunc)(node, data) != TRUE) {				return FALSE;			}			node = next;		}	}	return TRUE;}/* Can't be used to get larger primes than about 2^30. * * M22) n is less than zero * M23) n is zero * M24) n is 1, 2 or 3 * M25) n is prime * M26) n is not prime * M27) n is large (2^30 + 10) * *//** * hashtable_find_prime: * @n: prime starting point *  * Find a prime that is next higher (or equal) to the given starting point @n. * Can't be used to get larger primes than about 2^30. *  * Returns: the prime or zero on failure. */int hashtable_find_prime(int n){	int i;	if (n <= 0) {		fprintf(stderr,			"hashtable_find_prime: starting value must be higher "			"than one (was %d)\n",                        n);		return 0;	}	if (n == 1) return 2;	if (n <= 3) return n;	if ( (n & 1) == 0) n++;	for(;;) {				if (n > 1 << 29) break; /* make sure int won't be overflown */		i = 2;		while(n % i != 0) {			if (i * i > n) return n;			i++;		}		n += 2;	}	fprintf(stderr,		"hashtable_find_prime: value of n is too high\n");	return 0;}

⌨️ 快捷键说明

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