2003-05-26 09:18:31 +00:00
|
|
|
/* NeoStats - IRC Statistical Services
|
2004-01-14 11:36:37 +00:00
|
|
|
** Copyright (c) 1999-2004 Adam Rutter, Justin Hammond
|
2002-09-04 08:40:29 +00:00
|
|
|
** http://www.neostats.net/
|
|
|
|
**
|
|
|
|
** Portions Copyright (c) 2000-2001 ^Enigma^
|
|
|
|
**
|
|
|
|
** 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 2 of the License, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
|
|
** USA
|
|
|
|
**
|
|
|
|
** Portions borrowed from kazlib. Original Header follows:
|
|
|
|
*/
|
2002-02-27 11:19:15 +00:00
|
|
|
/*
|
|
|
|
* Hash Table Data Type
|
|
|
|
* Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
|
|
|
|
*
|
|
|
|
* Free Software License:
|
|
|
|
*
|
|
|
|
* All rights are reserved by the author, with the following exceptions:
|
|
|
|
* Permission is granted to freely reproduce and distribute this software,
|
|
|
|
* possibly in exchange for a fee, provided that this copyright notice appears
|
|
|
|
* intact. Permission is also granted to adapt this software to produce
|
|
|
|
* derivative works, as long as the modified versions carry this copyright
|
|
|
|
* notice and additional notices stating that the work has been modified.
|
|
|
|
* This source code may be translated into executable form and incorporated
|
|
|
|
* into proprietary software; there is no requirement for such software to
|
|
|
|
* contain a copyright notice related to this source.
|
|
|
|
*
|
2003-09-22 15:04:15 +00:00
|
|
|
* $Id$
|
2002-02-27 11:19:15 +00:00
|
|
|
* $Name: $
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef HASH_H
|
|
|
|
#define HASH_H
|
|
|
|
|
|
|
|
#include <limits.h>
|
|
|
|
#ifdef KAZLIB_SIDEEFFECT_DEBUG
|
|
|
|
#include "sfx.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Blurb for inclusion into C++ translation units
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2003-07-30 13:58:22 +00:00
|
|
|
typedef unsigned long hashcount_t;
|
2002-02-27 11:19:15 +00:00
|
|
|
#define HASHCOUNT_T_MAX ULONG_MAX
|
|
|
|
|
2003-07-30 13:58:22 +00:00
|
|
|
typedef unsigned long hash_val_t;
|
2002-02-27 11:19:15 +00:00
|
|
|
#define HASH_VAL_T_MAX ULONG_MAX
|
|
|
|
|
2003-07-30 13:58:22 +00:00
|
|
|
extern int hash_val_t_bit;
|
2002-02-27 11:19:15 +00:00
|
|
|
|
|
|
|
#ifndef HASH_VAL_T_BIT
|
|
|
|
#define HASH_VAL_T_BIT ((int) hash_val_t_bit)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Hash chain node structure.
|
|
|
|
* Notes:
|
|
|
|
* 1. This preprocessing directive is for debugging purposes. The effect is
|
|
|
|
* that if the preprocessor symbol KAZLIB_OPAQUE_DEBUG is defined prior to the
|
|
|
|
* inclusion of this header, then the structure shall be declared as having
|
|
|
|
* the single member int __OPAQUE__. This way, any attempts by the
|
|
|
|
* client code to violate the principles of information hiding (by accessing
|
|
|
|
* the structure directly) can be diagnosed at translation time. However,
|
|
|
|
* note the resulting compiled unit is not suitable for linking.
|
|
|
|
* 2. This is a pointer to the next node in the chain. In the last node of a
|
|
|
|
* chain, this pointer is null.
|
|
|
|
* 3. The key is a pointer to some user supplied data that contains a unique
|
|
|
|
* identifier for each hash node in a given table. The interpretation of
|
|
|
|
* the data is up to the user. When creating or initializing a hash table,
|
|
|
|
* the user must supply a pointer to a function for comparing two keys,
|
|
|
|
* and a pointer to a function for hashing a key into a numeric value.
|
|
|
|
* 4. The value is a user-supplied pointer to void which may refer to
|
|
|
|
* any data object. It is not interpreted in any way by the hashing
|
|
|
|
* module.
|
|
|
|
* 5. The hashed key is stored in each node so that we don't have to rehash
|
|
|
|
* each key when the table must grow or shrink.
|
|
|
|
*/
|
|
|
|
|
2003-07-30 13:58:22 +00:00
|
|
|
typedef struct hnode_t {
|
|
|
|
#if defined(HASH_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) /* 1 */
|
|
|
|
struct hnode_t *hash_next; /* 2 */
|
|
|
|
const void *hash_key; /* 3 */
|
|
|
|
void *hash_data; /* 4 */
|
|
|
|
hash_val_t hash_hkey; /* 5 */
|
|
|
|
#else
|
|
|
|
int hash_dummy;
|
|
|
|
#endif
|
|
|
|
} hnode_t;
|
2002-02-27 11:19:15 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The comparison function pointer type. A comparison function takes two keys
|
|
|
|
* and produces a value of -1 if the left key is less than the right key, a
|
|
|
|
* value of 0 if the keys are equal, and a value of 1 if the left key is
|
|
|
|
* greater than the right key.
|
|
|
|
*/
|
|
|
|
|
2003-07-30 13:58:22 +00:00
|
|
|
typedef int (*hash_comp_t) (const void *, const void *);
|
2002-02-27 11:19:15 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The hashing function performs some computation on a key and produces an
|
|
|
|
* integral value of type hash_val_t based on that key. For best results, the
|
|
|
|
* function should have a good randomness properties in *all* significant bits
|
|
|
|
* over the set of keys that are being inserted into a given hash table. In
|
|
|
|
* particular, the most significant bits of hash_val_t are most significant to
|
|
|
|
* the hash module. Only as the hash table expands are less significant bits
|
|
|
|
* examined. Thus a function that has good distribution in its upper bits but
|
|
|
|
* not lower is preferrable to one that has poor distribution in the upper bits
|
|
|
|
* but not the lower ones.
|
|
|
|
*/
|
|
|
|
|
2003-07-30 13:58:22 +00:00
|
|
|
typedef hash_val_t (*hash_fun_t) (const void *);
|
2002-02-27 11:19:15 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* allocator functions
|
|
|
|
*/
|
|
|
|
|
2003-07-30 13:58:22 +00:00
|
|
|
typedef hnode_t *(*hnode_alloc_t) (void *);
|
|
|
|
typedef void (*hnode_free_t) (hnode_t *, void *);
|
2002-02-27 11:19:15 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* This is the hash table control structure. It keeps track of information
|
|
|
|
* about a hash table, as well as the hash table itself.
|
|
|
|
* Notes:
|
|
|
|
* 1. Pointer to the hash table proper. The table is an array of pointers to
|
|
|
|
* hash nodes (of type hnode_t). If the table is empty, every element of
|
|
|
|
* this table is a null pointer. A non-null entry points to the first
|
|
|
|
* element of a chain of nodes.
|
|
|
|
* 2. This member keeps track of the size of the hash table---that is, the
|
|
|
|
* number of chain pointers.
|
|
|
|
* 3. The count member maintains the number of elements that are presently
|
|
|
|
* in the hash table.
|
|
|
|
* 4. The maximum count is the greatest number of nodes that can populate this
|
|
|
|
* table. If the table contains this many nodes, no more can be inserted,
|
|
|
|
* and the hash_isfull() function returns true.
|
|
|
|
* 5. The high mark is a population threshold, measured as a number of nodes,
|
|
|
|
* which, if exceeded, will trigger a table expansion. Only dynamic hash
|
|
|
|
* tables are subject to this expansion.
|
|
|
|
* 6. The low mark is a minimum population threshold, measured as a number of
|
|
|
|
* nodes. If the table population drops below this value, a table shrinkage
|
|
|
|
* will occur. Only dynamic tables are subject to this reduction. No table
|
|
|
|
* will shrink beneath a certain absolute minimum number of nodes.
|
|
|
|
* 7. This is the a pointer to the hash table's comparison function. The
|
|
|
|
* function is set once at initialization or creation time.
|
|
|
|
* 8. Pointer to the table's hashing function, set once at creation or
|
|
|
|
* initialization time.
|
|
|
|
* 9. The current hash table mask. If the size of the hash table is 2^N,
|
|
|
|
* this value has its low N bits set to 1, and the others clear. It is used
|
|
|
|
* to select bits from the result of the hashing function to compute an
|
|
|
|
* index into the table.
|
|
|
|
* 10. A flag which indicates whether the table is to be dynamically resized. It
|
|
|
|
* is set to 1 in dynamically allocated tables, 0 in tables that are
|
|
|
|
* statically allocated.
|
|
|
|
*/
|
|
|
|
|
2003-07-30 13:58:22 +00:00
|
|
|
typedef struct hash_t {
|
|
|
|
#if defined(HASH_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
|
|
|
|
struct hnode_t **hash_table; /* 1 */
|
|
|
|
hashcount_t hash_nchains; /* 2 */
|
|
|
|
hashcount_t hash_nodecount; /* 3 */
|
|
|
|
hashcount_t hash_maxcount; /* 4 */
|
|
|
|
hashcount_t hash_highmark; /* 5 */
|
|
|
|
hashcount_t hash_lowmark; /* 6 */
|
|
|
|
hash_comp_t hash_compare; /* 7 */
|
|
|
|
hash_fun_t hash_function; /* 8 */
|
|
|
|
hnode_alloc_t hash_allocnode;
|
|
|
|
hnode_free_t hash_freenode;
|
|
|
|
void *hash_context;
|
|
|
|
hash_val_t hash_mask; /* 9 */
|
|
|
|
int hash_dynamic; /* 10 */
|
|
|
|
#else
|
|
|
|
int hash_dummy;
|
|
|
|
#endif
|
|
|
|
} hash_t;
|
2002-02-27 11:19:15 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Hash scanner structure, used for traversals of the data structure.
|
|
|
|
* Notes:
|
|
|
|
* 1. Pointer to the hash table that is being traversed.
|
|
|
|
* 2. Reference to the current chain in the table being traversed (the chain
|
|
|
|
* that contains the next node that shall be retrieved).
|
|
|
|
* 3. Pointer to the node that will be retrieved by the subsequent call to
|
|
|
|
* hash_scan_next().
|
|
|
|
*/
|
|
|
|
|
2003-07-30 13:58:22 +00:00
|
|
|
typedef struct hscan_t {
|
|
|
|
#if defined(HASH_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
|
|
|
|
hash_t *hash_table; /* 1 */
|
|
|
|
hash_val_t hash_chain; /* 2 */
|
|
|
|
hnode_t *hash_next; /* 3 */
|
|
|
|
#else
|
|
|
|
int hash_dummy;
|
|
|
|
#endif
|
|
|
|
} hscan_t;
|
2002-02-27 11:19:15 +00:00
|
|
|
|
2003-07-30 13:58:22 +00:00
|
|
|
extern hash_t *hash_create (hashcount_t, hash_comp_t, hash_fun_t);
|
|
|
|
extern void hash_set_allocator (hash_t *, hnode_alloc_t, hnode_free_t, void *);
|
|
|
|
extern void hash_destroy (hash_t *);
|
|
|
|
extern void hash_free_nodes (hash_t *);
|
|
|
|
extern void hash_free (hash_t *);
|
|
|
|
extern hash_t *hash_init (hash_t *, hashcount_t, hash_comp_t, hash_fun_t, hnode_t **, hashcount_t);
|
|
|
|
extern void hash_insert (hash_t *, hnode_t *, const void *);
|
|
|
|
extern hnode_t *hash_lookup (hash_t *, const void *);
|
|
|
|
extern hnode_t *hash_delete (hash_t *, hnode_t *);
|
|
|
|
extern int hash_alloc_insert (hash_t *, const void *, void *);
|
|
|
|
extern void hash_delete_free (hash_t *, hnode_t *);
|
2002-02-27 11:19:15 +00:00
|
|
|
|
2003-07-30 13:58:22 +00:00
|
|
|
extern void hnode_put (hnode_t *, void *);
|
|
|
|
extern void *hnode_get (hnode_t *);
|
|
|
|
extern const void *hnode_getkey (hnode_t *);
|
|
|
|
extern hashcount_t hash_count (hash_t *);
|
|
|
|
extern hashcount_t hash_size (hash_t *);
|
2002-02-27 11:19:15 +00:00
|
|
|
|
2003-07-30 13:58:22 +00:00
|
|
|
extern int hash_isfull (hash_t *);
|
|
|
|
extern int hash_isempty (hash_t *);
|
2002-02-27 11:19:15 +00:00
|
|
|
|
2003-07-30 13:58:22 +00:00
|
|
|
extern void hash_scan_begin (hscan_t *, hash_t *);
|
|
|
|
extern hnode_t *hash_scan_next (hscan_t *);
|
|
|
|
extern hnode_t *hash_scan_delete (hash_t *, hnode_t *);
|
|
|
|
extern void hash_scan_delfree (hash_t *, hnode_t *);
|
2002-02-27 11:19:15 +00:00
|
|
|
|
2003-07-30 13:58:22 +00:00
|
|
|
extern int hash_verify (hash_t *);
|
2002-02-27 11:19:15 +00:00
|
|
|
|
2003-07-30 13:58:22 +00:00
|
|
|
extern hnode_t *hnode_create (void *);
|
|
|
|
extern hnode_t *hnode_init (hnode_t *, void *);
|
|
|
|
extern void hnode_destroy (hnode_t *);
|
2002-02-27 11:19:15 +00:00
|
|
|
|
|
|
|
#if defined(HASH_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
|
|
|
|
#ifdef KAZLIB_SIDEEFFECT_DEBUG
|
|
|
|
#define hash_isfull(H) (SFX_CHECK(H)->hash_nodecount == (H)->hash_maxcount)
|
|
|
|
#else
|
|
|
|
#define hash_isfull(H) ((H)->hash_nodecount == (H)->hash_maxcount)
|
|
|
|
#endif
|
|
|
|
#define hash_isempty(H) ((H)->hash_nodecount == 0)
|
|
|
|
#define hash_count(H) ((H)->hash_nodecount)
|
|
|
|
#define hash_size(H) ((H)->hash_nchains)
|
|
|
|
#define hnode_get(N) ((N)->hash_data)
|
|
|
|
#define hnode_getkey(N) ((N)->hash_key)
|
|
|
|
#define hnode_put(N, V) ((N)->hash_data = (V))
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|