1 |
/* hash.h -- decls for hash table |
/* hash - hashing table processing. |
2 |
Copyright 1995, 2001 Free Software Foundation, Inc. |
Copyright (C) 1998, 1999 Free Software Foundation, Inc. |
3 |
Written by Greg McGary <gkm@gnu.ai.mit.edu> |
Written by Jim Meyering <meyering@ascend.com>, 1998. |
4 |
|
|
5 |
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
6 |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
13 |
GNU General Public License for more details. |
GNU General Public License for more details. |
14 |
|
|
15 |
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
16 |
along with this program; if not, write to the Free Software |
along with this program; if not, write to the Free Software Foundation, |
17 |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
18 |
|
|
19 |
#ifndef _hash_h_ |
/* A generic hash table package. */ |
|
#define _hash_h_ |
|
20 |
|
|
21 |
#include <stdio.h> |
/* Make sure USE_OBSTACK is defined to 1 if you want the allocator to use |
22 |
|
obstacks instead of malloc, and recompile `hash.c' with same setting. */ |
23 |
|
|
24 |
#ifndef PARAMS |
#ifndef PARAMS |
25 |
# if defined PROTOTYPES || defined __STDC__ |
# if PROTOTYPES || __STDC__ |
26 |
# define PARAMS(Args) Args |
# define PARAMS(Args) Args |
27 |
# else |
# else |
28 |
# define PARAMS(Args) () |
# define PARAMS(Args) () |
29 |
# endif |
# endif |
30 |
#endif |
#endif |
31 |
|
|
32 |
typedef unsigned long (*hash_func_t) PARAMS((void const *key)); |
typedef unsigned (*Hash_hasher) PARAMS ((const void *, unsigned)); |
33 |
typedef int (*hash_cmp_func_t) PARAMS((void const *x, void const *y)); |
typedef bool (*Hash_comparator) PARAMS ((const void *, const void *)); |
34 |
typedef void (*hash_map_func_t) PARAMS((void const *item)); |
typedef void (*Hash_data_freer) PARAMS ((void *)); |
35 |
|
typedef bool (*Hash_processor) PARAMS ((void *, void *)); |
36 |
|
|
37 |
|
struct hash_entry |
38 |
|
{ |
39 |
|
void *data; |
40 |
|
struct hash_entry *next; |
41 |
|
}; |
42 |
|
|
43 |
|
struct hash_tuning |
44 |
|
{ |
45 |
|
/* This structure is mainly used for `hash_initialize', see the block |
46 |
|
documentation of `hash_reset_tuning' for more complete comments. */ |
47 |
|
|
48 |
|
float shrink_threshold; /* ratio of used buckets to trigger a shrink */ |
49 |
|
float shrink_factor; /* ratio of new smaller size to original size */ |
50 |
|
float growth_threshold; /* ratio of used buckets to trigger a growth */ |
51 |
|
float growth_factor; /* ratio of new bigger size to original size */ |
52 |
|
bool is_n_buckets; /* if CANDIDATE really means table size */ |
53 |
|
}; |
54 |
|
|
55 |
|
typedef struct hash_tuning Hash_tuning; |
56 |
|
|
57 |
struct hash_table |
struct hash_table |
58 |
{ |
{ |
59 |
void **ht_vec; |
/* The array of buckets starts at BUCKET and extends to BUCKET_LIMIT-1, |
60 |
unsigned long ht_size; /* total number of slots (power of 2) */ |
for a possibility of N_BUCKETS. Among those, N_BUCKETS_USED buckets |
61 |
unsigned long ht_capacity; /* usable slots, limited by loading-factor */ |
are not empty, there are N_ENTRIES active entries in the table. */ |
62 |
unsigned long ht_fill; /* items in table */ |
struct hash_entry *bucket; |
63 |
unsigned long ht_collisions; /* # of failed calls to comparison function */ |
struct hash_entry *bucket_limit; |
64 |
unsigned long ht_lookups; /* # of queries */ |
unsigned n_buckets; |
65 |
unsigned int ht_rehashes; /* # of times we've expanded table */ |
unsigned n_buckets_used; |
66 |
hash_func_t ht_hash_1; /* primary hash function */ |
unsigned n_entries; |
67 |
hash_func_t ht_hash_2; /* secondary hash function */ |
|
68 |
hash_cmp_func_t ht_compare; /* comparison function */ |
/* Tuning arguments, kept in a physicaly separate structure. */ |
69 |
}; |
const Hash_tuning *tuning; |
70 |
|
|
71 |
typedef int (*qsort_cmp_t) PARAMS((void const *, void const *)); |
/* Three functions are given to `hash_initialize', see the documentation |
72 |
|
block for this function. In a word, HASHER randomizes a user entry |
73 |
void hash_init PARAMS((struct hash_table *ht, unsigned long size, |
into a number up from 0 up to some maximum minus 1; COMPARATOR returns |
74 |
hash_func_t hash_1, hash_func_t hash_2, hash_cmp_func_t hash_cmp)); |
true if two user entries compare equally; and DATA_FREER is the cleanup |
75 |
void hash_load PARAMS((struct hash_table *ht, void *item_table, |
function for a user entry. */ |
76 |
unsigned long cardinality, unsigned long size)); |
Hash_hasher hasher; |
77 |
void **hash_find_slot PARAMS((struct hash_table *ht, void const *key)); |
Hash_comparator comparator; |
78 |
void *hash_find_item PARAMS((struct hash_table *ht, void const *key)); |
Hash_data_freer data_freer; |
79 |
const void *hash_insert PARAMS((struct hash_table *ht, void *item)); |
|
80 |
const void *hash_insert_at PARAMS((struct hash_table *ht, void *item, void const *slot)); |
/* A linked list of freed struct hash_entry structs. */ |
81 |
const void *hash_delete PARAMS((struct hash_table *ht, void const *item)); |
struct hash_entry *free_entry_list; |
82 |
const void *hash_delete_at PARAMS((struct hash_table *ht, void const *slot)); |
|
83 |
void hash_delete_items PARAMS((struct hash_table *ht)); |
#if USE_OBSTACK |
84 |
void hash_free_items PARAMS((struct hash_table *ht)); |
/* Whenever obstacks are used, it is possible to allocate all overflowed |
85 |
void hash_free PARAMS((struct hash_table *ht, int free_items)); |
entries into a single stack, so they all can be freed in a single |
86 |
void hash_map PARAMS((struct hash_table *ht, hash_map_func_t map)); |
operation. It is not clear if the speedup is worth the trouble. */ |
87 |
void hash_print_stats PARAMS((struct hash_table *ht, FILE *out_FILE)); |
struct obstack entry_stack; |
88 |
void **hash_dump PARAMS((struct hash_table *ht, void **vector_0, qsort_cmp_t compare)); |
#endif |
89 |
|
}; |
90 |
extern void *hash_deleted_item; |
|
91 |
#define HASH_VACANT(item) \ |
typedef struct hash_table Hash_table; |
|
((item) == 0 || (const void *) (item) == hash_deleted_item) |
|
|
|
|
|
|
|
|
/* hash and comparison macros for string keys. */ |
|
|
|
|
|
#define STRING_HASH_1(_key_, _result_) { \ |
|
|
unsigned char const *kk = (unsigned char const *) (_key_) - 1; \ |
|
|
while (*++kk) \ |
|
|
(_result_) += (*kk << (kk[1] & 0xf)); \ |
|
|
} while (0) |
|
|
#define return_STRING_HASH_1(_key_) do { \ |
|
|
unsigned long result = 0; \ |
|
|
STRING_HASH_1 ((_key_), result); \ |
|
|
return result; \ |
|
|
} while (0) |
|
|
|
|
|
#define STRING_HASH_2(_key_, _result_) do { \ |
|
|
unsigned char const *kk = (unsigned char const *) (_key_) - 1; \ |
|
|
while (*++kk) \ |
|
|
(_result_) += (*kk << (kk[1] & 0x7)); \ |
|
|
} while (0) |
|
|
#define return_STRING_HASH_2(_key_) do { \ |
|
|
unsigned long result = 0; \ |
|
|
STRING_HASH_2 ((_key_), result); \ |
|
|
return result; \ |
|
|
} while (0) |
|
|
|
|
|
#define STRING_COMPARE(_x_, _y_, _result_) do { \ |
|
|
unsigned char const *xx = (unsigned char const *) (_x_) - 1; \ |
|
|
unsigned char const *yy = (unsigned char const *) (_y_) - 1; \ |
|
|
do { \ |
|
|
if (*++xx == '\0') { \ |
|
|
yy++; \ |
|
|
break; \ |
|
|
} \ |
|
|
} while (*xx == *++yy); \ |
|
|
(_result_) = *xx - *yy; \ |
|
|
} while (0) |
|
|
#define return_STRING_COMPARE(_x_, _y_) do { \ |
|
|
int result; \ |
|
|
STRING_COMPARE (_x_, _y_, result); \ |
|
|
return result; \ |
|
|
} while (0) |
|
|
|
|
|
/* hash and comparison macros for integer keys. */ |
|
|
|
|
|
#define INTEGER_HASH_1(_key_, _result_) do { \ |
|
|
(_result_) += ((unsigned long)(_key_)); \ |
|
|
} while (0) |
|
|
#define return_INTEGER_HASH_1(_key_) do { \ |
|
|
unsigned long result = 0; \ |
|
|
INTEGER_HASH_1 ((_key_), result); \ |
|
|
return result; \ |
|
|
} while (0) |
|
|
|
|
|
#define INTEGER_HASH_2(_key_, _result_) do { \ |
|
|
(_result_) += ~((unsigned long)(_key_)); \ |
|
|
} while (0) |
|
|
#define return_INTEGER_HASH_2(_key_) do { \ |
|
|
unsigned long result = 0; \ |
|
|
INTEGER_HASH_2 ((_key_), result); \ |
|
|
return result; \ |
|
|
} while (0) |
|
|
|
|
|
#define INTEGER_COMPARE(_x_, _y_, _result_) do { \ |
|
|
(_result_) = _x_ - _y_; \ |
|
|
} while (0) |
|
|
#define return_INTEGER_COMPARE(_x_, _y_) do { \ |
|
|
int result; \ |
|
|
INTEGER_COMPARE (_x_, _y_, result); \ |
|
|
return result; \ |
|
|
} while (0) |
|
|
|
|
|
/* hash and comparison macros for address keys. */ |
|
|
|
|
|
#define ADDRESS_HASH_1(_key_, _result_) INTEGER_HASH_1 (((unsigned long)(_key_)) >> 3, (_result_)) |
|
|
#define ADDRESS_HASH_2(_key_, _result_) INTEGER_HASH_2 (((unsigned long)(_key_)) >> 3, (_result_)) |
|
|
#define ADDRESS_COMPARE(_x_, _y_, _result_) INTEGER_COMPARE ((_x_), (_y_), (_result_)) |
|
|
#define return_ADDRESS_HASH_1(_key_) return_INTEGER_HASH_1 (((unsigned long)(_key_)) >> 3) |
|
|
#define return_ADDRESS_HASH_2(_key_) return_INTEGER_HASH_2 (((unsigned long)(_key_)) >> 3) |
|
|
#define return_ADDRESS_COMPARE(_x_, _y_) return_INTEGER_COMPARE ((_x_), (_y_)) |
|
92 |
|
|
93 |
#endif /* not _hash_h_ */ |
/* Information and lookup. */ |
94 |
|
unsigned hash_get_n_buckets PARAMS ((const Hash_table *)); |
95 |
|
unsigned hash_get_n_buckets_used PARAMS ((const Hash_table *)); |
96 |
|
unsigned hash_get_n_entries PARAMS ((const Hash_table *)); |
97 |
|
unsigned hash_get_max_bucket_length PARAMS ((const Hash_table *)); |
98 |
|
bool hash_table_ok PARAMS ((const Hash_table *)); |
99 |
|
void hash_print_statistics PARAMS ((const Hash_table *, FILE *)); |
100 |
|
void *hash_lookup PARAMS ((const Hash_table *, const void *)); |
101 |
|
|
102 |
|
/* Walking. */ |
103 |
|
void *hash_get_first PARAMS ((const Hash_table *)); |
104 |
|
void *hash_get_next PARAMS ((const Hash_table *, const void *)); |
105 |
|
unsigned hash_get_entries PARAMS ((const Hash_table *, void **, unsigned)); |
106 |
|
unsigned hash_do_for_each PARAMS ((const Hash_table *, Hash_processor, void *)); |
107 |
|
|
108 |
|
/* Allocation and clean-up. */ |
109 |
|
unsigned hash_string PARAMS ((const char *, unsigned)); |
110 |
|
void hash_reset_tuning PARAMS ((Hash_tuning *)); |
111 |
|
Hash_table *hash_initialize PARAMS ((unsigned, const Hash_tuning *, |
112 |
|
Hash_hasher, Hash_comparator, |
113 |
|
Hash_data_freer)); |
114 |
|
void hash_clear PARAMS ((Hash_table *)); |
115 |
|
void hash_free PARAMS ((Hash_table *)); |
116 |
|
|
117 |
|
/* Insertion and deletion. */ |
118 |
|
bool hash_rehash PARAMS ((Hash_table *, unsigned)); |
119 |
|
void *hash_insert PARAMS ((Hash_table *, const void *)); |
120 |
|
void *hash_delete PARAMS ((Hash_table *, const void *)); |