diff options
Diffstat (limited to 'libiberty/hashtab.c')
-rw-r--r-- | libiberty/hashtab.c | 433 |
1 files changed, 0 insertions, 433 deletions
diff --git a/libiberty/hashtab.c b/libiberty/hashtab.c deleted file mode 100644 index 6ae34aab0f1..00000000000 --- a/libiberty/hashtab.c +++ /dev/null @@ -1,433 +0,0 @@ -/* An expandable hash tables datatype. - Copyright (C) 1999 Free Software Foundation, Inc. - Contributed by Vladimir Makarov (vmakarov@cygnus.com). - -This file is part of the libiberty library. -Libiberty is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -Libiberty 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 -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with libiberty; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* This package implements basic hash table functionality. It is possible - to search for an entry, create an entry and destroy an entry. - - Elements in the table are generic pointers. - - The size of the table is not fixed; if the occupancy of the table - grows too high the hash table will be expanded. - - The abstract data implementation is based on generalized Algorithm D - from Knuth's book "The art of computer programming". Hash table is - expanded by creation of new hash table and transferring elements from - the old table to the new table. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <sys/types.h> - -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif - -#ifdef HAVE_STRING_H -#include <string.h> -#endif - -#include <stdio.h> - -#include "libiberty.h" -#include "hashtab.h" - -/* This macro defines reserved value for empty table entry. */ - -#define EMPTY_ENTRY ((void *) 0) - -/* This macro defines reserved value for table entry which contained - a deleted element. */ - -#define DELETED_ENTRY ((void *) 1) - -/* The following function returns the nearest prime number which is - greater than given source number. */ - -static unsigned long -higher_prime_number (n) - unsigned long n; -{ - unsigned long i; - - n |= 0x01; /* Force N to be odd. */ - if (n < 9) - return n; /* All odd numbers < 9 are prime. */ - - next: - n += 2; - i = 3; - do - { - if (n % i == 0) - goto next; - i += 2; - } - while ((i * i) <= n); - - return n; -} - -/* This function creates table with length slightly longer than given - source length. Created hash table is initiated as empty (all the - hash table entries are EMPTY_ENTRY). The function returns the - created hash table. */ - -htab_t -htab_create (size, hash_f, eq_f, del_f) - size_t size; - htab_hash hash_f; - htab_eq eq_f; - htab_del del_f; -{ - htab_t result; - - size = higher_prime_number (size); - result = (htab_t) xcalloc (1, sizeof (struct htab)); - result->entries = (void **) xcalloc (size, sizeof (void *)); - result->size = size; - result->hash_f = hash_f; - result->eq_f = eq_f; - result->del_f = del_f; - return result; -} - -/* This function frees all memory allocated for given hash table. - Naturally the hash table must already exist. */ - -void -htab_delete (htab) - htab_t htab; -{ - int i; - if (htab->del_f) - for (i = htab->size - 1; i >= 0; i--) - { - if (htab->entries[i] != EMPTY_ENTRY - && htab->entries[i] != DELETED_ENTRY) - (*htab->del_f) (htab->entries[i]); - } - - free (htab->entries); - free (htab); -} - -/* This function clears all entries in the given hash table. */ - -void -htab_empty (htab) - htab_t htab; -{ - int i; - if (htab->del_f) - for (i = htab->size - 1; i >= 0; i--) - { - if (htab->entries[i] != EMPTY_ENTRY - && htab->entries[i] != DELETED_ENTRY) - (*htab->del_f) (htab->entries[i]); - } - - memset (htab->entries, 0, htab->size * sizeof (void *)); -} - -/* Similar to htab_find_slot, but without several unwanted side effects: - - Does not call htab->eq_f when it finds an existing entry. - - Does not change the count of elements/searches/collisions in the - hash table. - This function also assumes there are no deleted entries in the table. - HASH is the hash value for the element to be inserted. */ -static void ** -find_empty_slot_for_expand (htab, hash) - htab_t htab; - unsigned int hash; -{ - size_t size = htab->size; - unsigned int hash2 = 1 + hash % (size - 2); - unsigned int index = hash % size; - - for (;;) - { - void **slot = htab->entries + index; - if (*slot == EMPTY_ENTRY) - return slot; - - if (*slot == DELETED_ENTRY) - abort (); - - index += hash2; - if (index >= size) - index -= size; - } -} - -/* The following function changes size of memory allocated for the - entries and repeatedly inserts the table elements. The occupancy - of the table after the call will be about 50%. Naturally the hash - table must already exist. Remember also that the place of the - table entries is changed. */ - -static void -htab_expand (htab) - htab_t htab; -{ - void **oentries; - void **olimit; - void **p; - - oentries = htab->entries; - olimit = oentries + htab->size; - - htab->size = higher_prime_number (htab->size * 2); - htab->entries = xcalloc (htab->size, sizeof (void **)); - - htab->n_elements -= htab->n_deleted; - htab->n_deleted = 0; - - p = oentries; - do - { - void *x = *p; - if (x != EMPTY_ENTRY && x != DELETED_ENTRY) - { - void **q = find_empty_slot_for_expand (htab, (*htab->hash_f) (x)); - *q = x; - } - p++; - } - while (p < olimit); - free (oentries); -} - -/* This function searches for a hash table entry equal to the given - element. It cannot be used to insert or delete an element. */ - -void * -htab_find_with_hash (htab, element, hash) - htab_t htab; - const void *element; - unsigned int hash; -{ - unsigned int index, hash2; - size_t size; - - htab->searches++; - size = htab->size; - hash2 = 1 + hash % (size - 2); - index = hash % size; - - for (;;) - { - void *entry = htab->entries[index]; - if (entry == EMPTY_ENTRY) - return NULL; - else if (entry != DELETED_ENTRY && (*htab->eq_f) (entry, element)) - return entry; - - htab->collisions++; - index += hash2; - if (index >= size) - index -= size; - } -} - -/* Like htab_find_slot_with_hash, but compute the hash value from the - element. */ -void * -htab_find (htab, element) - htab_t htab; - const void *element; -{ - return htab_find_with_hash (htab, element, (*htab->hash_f) (element)); -} - -/* This function searches for a hash table slot containing an entry - equal to the given element. To delete an entry, call this with - INSERT = 0, then call htab_clear_slot on the slot returned (possibly - after doing some checks). To insert an entry, call this with - INSERT = 1, then write the value you want into the returned slot. */ - -void ** -htab_find_slot_with_hash (htab, element, hash, insert) - htab_t htab; - const void *element; - unsigned int hash; - int insert; -{ - void **first_deleted_slot; - unsigned int index, hash2; - size_t size; - - if (insert && htab->size * 3 <= htab->n_elements * 4) - htab_expand (htab); - - size = htab->size; - hash2 = 1 + hash % (size - 2); - index = hash % size; - - htab->searches++; - first_deleted_slot = NULL; - - for (;;) - { - void *entry = htab->entries[index]; - if (entry == EMPTY_ENTRY) - { - if (!insert) - return NULL; - - htab->n_elements++; - - if (first_deleted_slot) - { - *first_deleted_slot = EMPTY_ENTRY; - return first_deleted_slot; - } - - return &htab->entries[index]; - } - - if (entry == DELETED_ENTRY) - { - if (!first_deleted_slot) - first_deleted_slot = &htab->entries[index]; - } - else - { - if ((*htab->eq_f) (entry, element)) - return &htab->entries[index]; - } - - htab->collisions++; - index += hash2; - if (index >= size) - index -= size; - } -} - -/* Like htab_find_slot_with_hash, but compute the hash value from the - element. */ -void ** -htab_find_slot (htab, element, insert) - htab_t htab; - const void *element; - int insert; -{ - return htab_find_slot_with_hash (htab, element, (*htab->hash_f) (element), - insert); -} - -/* This function deletes an element with the given value from hash - table. If there is no matching element in the hash table, this - function does nothing. */ - -void -htab_remove_elt (htab, element) - htab_t htab; - void *element; -{ - void **slot; - - slot = htab_find_slot (htab, element, 0); - if (*slot == EMPTY_ENTRY) - return; - - if (htab->del_f) - (*htab->del_f) (*slot); - - *slot = DELETED_ENTRY; - htab->n_deleted++; -} - -/* This function clears a specified slot in a hash table. It is - useful when you've already done the lookup and don't want to do it - again. */ - -void -htab_clear_slot (htab, slot) - htab_t htab; - void **slot; -{ - if (slot < htab->entries || slot >= htab->entries + htab->size - || *slot == EMPTY_ENTRY || *slot == DELETED_ENTRY) - abort (); - if (htab->del_f) - (*htab->del_f) (*slot); - *slot = DELETED_ENTRY; - htab->n_deleted++; -} - -/* This function scans over the entire hash table calling - CALLBACK for each live entry. If CALLBACK returns false, - the iteration stops. INFO is passed as CALLBACK's second - argument. */ - -void -htab_traverse (htab, callback, info) - htab_t htab; - htab_trav callback; - void *info; -{ - void **slot, **limit; - slot = htab->entries; - limit = slot + htab->size; - do - { - void *x = *slot; - if (x != EMPTY_ENTRY && x != DELETED_ENTRY) - if (!(*callback) (slot, info)) - break; - } - while (++slot < limit); -} - -/* The following function returns current size of given hash table. */ - -size_t -htab_size (htab) - htab_t htab; -{ - return htab->size; -} - -/* The following function returns current number of elements in given - hash table. */ - -size_t -htab_elements (htab) - htab_t htab; -{ - return htab->n_elements - htab->n_deleted; -} - -/* The following function returns number of percents of fixed - collisions during all work with given hash table. */ - -double -htab_collisions (htab) - htab_t htab; -{ - int searches; - - searches = htab->searches; - if (searches == 0) - return 0.0; - return (double)htab->collisions / (double)searches; -} |