1 /* hashlib.c -- functions to manage and access hash tables for bash. */
3 /* Copyright (C) 1987,1989,1991,1995,1998,2001,2003,2005,2006,2008,2009 Free Software Foundation, Inc.
5 This file is part of GNU Bash, the Bourne Again SHell.
7 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
25 #if defined (HAVE_UNISTD_H)
27 # include <sys/types.h>
37 /* Rely on properties of unsigned division (unsigned/int -> unsigned) and
38 don't discard the upper 32 bits of the value, if present. */
39 #define HASH_BUCKET(s, t, h) (((h) = hash_string (s)) & ((t)->nbuckets - 1))
41 static BUCKET_CONTENTS
*copy_bucket_array
__P((BUCKET_CONTENTS
*, sh_string_func_t
*));
43 /* Make a new hash table with BUCKETS number of buckets. Initialize
44 each slot in the table to NULL. */
49 HASH_TABLE
*new_table
;
52 new_table
= (HASH_TABLE
*)xmalloc (sizeof (HASH_TABLE
));
54 buckets
= DEFAULT_HASH_BUCKETS
;
56 new_table
->bucket_array
=
57 (BUCKET_CONTENTS
**)xmalloc (buckets
* sizeof (BUCKET_CONTENTS
*));
58 new_table
->nbuckets
= buckets
;
59 new_table
->nentries
= 0;
61 for (i
= 0; i
< buckets
; i
++)
62 new_table
->bucket_array
[i
] = (BUCKET_CONTENTS
*)NULL
;
71 return (HASH_ENTRIES(table
));
74 static BUCKET_CONTENTS
*
75 copy_bucket_array (ba
, cpdata
)
77 sh_string_func_t
*cpdata
; /* data copy function */
79 BUCKET_CONTENTS
*new_bucket
, *n
, *e
;
82 return ((BUCKET_CONTENTS
*)0);
84 for (n
= (BUCKET_CONTENTS
*)0, e
= ba
; e
; e
= e
->next
)
88 new_bucket
= (BUCKET_CONTENTS
*)xmalloc (sizeof (BUCKET_CONTENTS
));
93 n
->next
= (BUCKET_CONTENTS
*)xmalloc (sizeof (BUCKET_CONTENTS
));
97 n
->key
= savestring (e
->key
);
98 n
->data
= e
->data
? (cpdata
? (*cpdata
) (e
->data
) : savestring (e
->data
))
101 n
->times_found
= e
->times_found
;
102 n
->next
= (BUCKET_CONTENTS
*)NULL
;
109 hash_copy (table
, cpdata
)
111 sh_string_func_t
*cpdata
;
113 HASH_TABLE
*new_table
;
117 return ((HASH_TABLE
*)NULL
);
119 new_table
= hash_create (table
->nbuckets
);
121 for (i
= 0; i
< table
->nbuckets
; i
++)
122 new_table
->bucket_array
[i
] = copy_bucket_array (table
->bucket_array
[i
], cpdata
);
124 new_table
->nentries
= table
->nentries
;
128 /* The `khash' check below requires that strings that compare equally with
129 strcmp hash to the same value. */
134 register unsigned int i
;
136 /* This is the best string hash function I found.
138 The magic is in the interesting relationship between the special prime
139 16777619 (2^24 + 403) and 2^32 and 2^8. */
150 /* Return the location of the bucket which should contain the data
151 for STRING. TABLE is a pointer to a HASH_TABLE. */
154 hash_bucket (string
, table
)
160 return (HASH_BUCKET (string
, table
, h
));
163 /* Return a pointer to the hashed item. If the HASH_CREATE flag is passed,
164 create a new hash table entry for STRING, otherwise return NULL. */
166 hash_search (string
, table
, flags
)
171 BUCKET_CONTENTS
*list
;
175 if (table
== 0 || ((flags
& HASH_CREATE
) == 0 && HASH_ENTRIES (table
) == 0))
176 return (BUCKET_CONTENTS
*)NULL
;
178 bucket
= HASH_BUCKET (string
, table
, hv
);
180 for (list
= table
->bucket_array
? table
->bucket_array
[bucket
] : 0; list
; list
= list
->next
)
182 if (hv
== list
->khash
&& STREQ (list
->key
, string
))
189 if (flags
& HASH_CREATE
)
191 list
= (BUCKET_CONTENTS
*)xmalloc (sizeof (BUCKET_CONTENTS
));
192 list
->next
= table
->bucket_array
[bucket
];
193 table
->bucket_array
[bucket
] = list
;
196 list
->key
= (char *)string
; /* XXX fix later */
198 list
->times_found
= 0;
204 return (BUCKET_CONTENTS
*)NULL
;
207 /* Remove the item specified by STRING from the hash table TABLE.
208 The item removed is returned, so you can free its contents. If
209 the item isn't in this table NULL is returned. */
211 hash_remove (string
, table
, flags
)
217 BUCKET_CONTENTS
*prev
, *temp
;
220 if (table
== 0 || HASH_ENTRIES (table
) == 0)
221 return (BUCKET_CONTENTS
*)NULL
;
223 bucket
= HASH_BUCKET (string
, table
, hv
);
224 prev
= (BUCKET_CONTENTS
*)NULL
;
225 for (temp
= table
->bucket_array
[bucket
]; temp
; temp
= temp
->next
)
227 if (hv
== temp
->khash
&& STREQ (temp
->key
, string
))
230 prev
->next
= temp
->next
;
232 table
->bucket_array
[bucket
] = temp
->next
;
239 return ((BUCKET_CONTENTS
*) NULL
);
242 /* Create an entry for STRING, in TABLE. If the entry already
243 exists, then return it (unless the HASH_NOSRCH flag is set). */
245 hash_insert (string
, table
, flags
)
250 BUCKET_CONTENTS
*item
;
255 table
= hash_create (0);
257 item
= (flags
& HASH_NOSRCH
) ? (BUCKET_CONTENTS
*)NULL
258 : hash_search (string
, table
, 0);
262 bucket
= HASH_BUCKET (string
, table
, hv
);
264 item
= (BUCKET_CONTENTS
*)xmalloc (sizeof (BUCKET_CONTENTS
));
265 item
->next
= table
->bucket_array
[bucket
];
266 table
->bucket_array
[bucket
] = item
;
271 item
->times_found
= 0;
279 /* Remove and discard all entries in TABLE. If FREE_DATA is non-null, it
280 is a function to call to dispose of a hash item's data. Otherwise,
283 hash_flush (table
, free_data
)
285 sh_free_func_t
*free_data
;
288 register BUCKET_CONTENTS
*bucket
, *item
;
290 if (table
== 0 || HASH_ENTRIES (table
) == 0)
293 for (i
= 0; i
< table
->nbuckets
; i
++)
295 bucket
= table
->bucket_array
[i
];
300 bucket
= bucket
->next
;
303 (*free_data
) (item
->data
);
309 table
->bucket_array
[i
] = (BUCKET_CONTENTS
*)NULL
;
315 /* Free the hash table pointed to by TABLE. */
320 free (table
->bucket_array
);
325 hash_walk (table
, func
)
330 BUCKET_CONTENTS
*item
;
332 if (table
== 0 || HASH_ENTRIES (table
) == 0)
335 for (i
= 0; i
< table
->nbuckets
; i
++)
337 for (item
= hash_items (i
, table
); item
; item
= item
->next
)
338 if ((*func
) (item
) < 0)
343 #if defined (DEBUG) || defined (TEST_HASHING)
345 hash_pstats (table
, name
)
349 register int slot
, bcount
;
350 register BUCKET_CONTENTS
*bc
;
353 name
= "unknown hash table";
355 fprintf (stderr
, "%s: %d buckets; %d items\n", name
, table
->nbuckets
, table
->nentries
);
357 /* Print out a count of how many strings hashed to each bucket, so we can
358 see how even the distribution is. */
359 for (slot
= 0; slot
< table
->nbuckets
; slot
++)
361 bc
= hash_items (slot
, table
);
363 fprintf (stderr
, "\tslot %3d: ", slot
);
364 for (bcount
= 0; bc
; bc
= bc
->next
)
367 fprintf (stderr
, "%d\n", bcount
);
374 /* link with xmalloc.o and lib/malloc/libmalloc.a */
382 HASH_TABLE
*table
, *ntable
;
384 int interrupt_immediately
= 0;
387 signal_is_trapped (s
)
394 programming_error (const char *format
, ...)
400 fatal_error (const char *format
, ...)
411 table
= hash_create (0);
416 if (fgets (string
, sizeof (string
), stdin
) == 0)
420 temp_string
= savestring (string
);
421 tt
= hash_insert (temp_string
, table
, 0);
424 fprintf (stderr
, "You have already added item `%s'\n", string
);
433 hash_pstats (table
, "hash test");
435 ntable
= hash_copy (table
, (sh_string_func_t
*)NULL
);
436 hash_flush (table
, (sh_free_func_t
*)NULL
);
437 hash_pstats (ntable
, "hash copy test");
442 #endif /* TEST_HASHING */