X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=libobjc%2Fhash.c;h=733fc65019b7124b08edcdeaa5f78a2ba9e82f9b;hb=2c6c4996dd9e4b6cc96639b270954405c79f648d;hp=223991f97f3ed26b38ab9bfbbaaaf10194de1eaa;hpb=265ab036ba930e88825e04a0c4684adb2b4a858a;p=pf3gnuchains%2Fgcc-fork.git diff --git a/libobjc/hash.c b/libobjc/hash.c index 223991f97f3..733fc65019b 100644 --- a/libobjc/hash.c +++ b/libobjc/hash.c @@ -1,34 +1,33 @@ /* Hash tables for Objective C internal structures - Copyright (C) 1993, 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 1993, 1996, 1997, 2004, 2009, 2010 + Free Software Foundation, Inc. -This file is part of GNU CC. +This file is part of GCC. -GNU CC is free software; you can redistribute it and/or modify +GCC 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, or (at your option) +the Free Software Foundation; either version 3, or (at your option) any later version. -GNU CC is distributed in the hope that it will be useful, +GCC 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 GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. -/* As a special exception, if you link this library with files - compiled with GCC to produce an executable, this does not cause - the resulting executable to be covered by the GNU General Public License. - This exception does not however invalidate any other reasons why - the executable file might be covered by the GNU General Public License. */ +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ -#include "assert.h" +#include "objc-private/common.h" +#include /* For assert. */ -#include "hash.h" - -#include "runtime.h" /* for DEBUG_PRINTF */ +#include "objc/runtime.h" /* For objc_calloc. */ +#include "objc-private/hash.h" /* These two macros determine when a hash table is full and by how much it should be expanded respectively. @@ -40,36 +39,36 @@ Boston, MA 02111-1307, USA. */ ((cache)->size * 2) cache_ptr -hash_new (unsigned int size, hash_func_type hash_func, - compare_func_type compare_func) +objc_hash_new (unsigned int size, hash_func_type hash_func, + compare_func_type compare_func) { cache_ptr cache; /* Pass me a value greater than 0 and a power of 2. */ assert (size); - assert (!(size & (size - 1))); + assert (! (size & (size - 1))); - /* Allocate the cache structure. calloc insures - its initialization for default values. */ + /* Allocate the cache structure. calloc insures its initialization + for default values. */ cache = (cache_ptr) objc_calloc (1, sizeof (struct cache)); assert (cache); - /* Allocate the array of buckets for the cache. - calloc initializes all of the pointers to NULL. */ + /* Allocate the array of buckets for the cache. calloc initializes + all of the pointers to NULL. */ cache->node_table = (node_ptr *) objc_calloc (size, sizeof (node_ptr)); assert (cache->node_table); cache->size = size; - /* This should work for all processor architectures? */ + /* This should work for all processor architectures (?). */ cache->mask = (size - 1); /* Store the hashing function so that codes can be computed. */ cache->hash_func = hash_func; - /* Store the function that compares hash keys to - determine if they are equal. */ + /* Store the function that compares hash keys to determine if they + are equal. */ cache->compare_func = compare_func; return cache; @@ -77,7 +76,7 @@ hash_new (unsigned int size, hash_func_type hash_func, void -hash_delete (cache_ptr cache) +objc_hash_delete (cache_ptr cache) { node_ptr node; node_ptr next_node; @@ -85,19 +84,22 @@ hash_delete (cache_ptr cache) /* Purge all key/value pairs from the table. */ /* Step through the nodes one by one and remove every node WITHOUT - using hash_next. this makes hash_delete much more efficient. */ - for (i = 0;i < cache->size;i++) { - if ((node = cache->node_table[i])) { - /* an entry in the hash table has been found, now step through the - nodes next in the list and free them. */ - while ((next_node = node->next)) { - hash_remove (cache,node->key); - node = next_node; - } - - hash_remove (cache,node->key); + using objc_hash_next. this makes objc_hash_delete much more + efficient. */ + for (i = 0; i < cache->size; i++) + { + if ((node = cache->node_table[i])) + { + /* An entry in the hash table has been found. Now step + through the nodes next in the list and free them. */ + while ((next_node = node->next)) + { + objc_hash_remove (cache,node->key); + node = next_node; + } + objc_hash_remove (cache,node->key); + } } - } /* Release the array of nodes and the cache itself. */ objc_free(cache->node_table); @@ -106,12 +108,11 @@ hash_delete (cache_ptr cache) void -hash_add (cache_ptr *cachep, const void *key, void *value) +objc_hash_add (cache_ptr *cachep, const void *key, void *value) { - size_t indx = (*(*cachep)->hash_func)(*cachep, key); + size_t indx = (*(*cachep)->hash_func) (*cachep, key); node_ptr node = (node_ptr) objc_calloc (1, sizeof (struct cache_node)); - assert (node); /* Initialize the new node. */ @@ -119,16 +120,15 @@ hash_add (cache_ptr *cachep, const void *key, void *value) node->value = value; node->next = (*cachep)->node_table[indx]; - /* Debugging. - Check the list for another key. */ + /* Debugging. Check the list for another key. */ #ifdef DEBUG - { node_ptr node1 = (*cachep)->node_table[indx]; - - while (node1) { - - assert (node1->key != key); - node1 = node1->next; - } + { + node_ptr node1 = (*cachep)->node_table[indx]; + while (node1) + { + assert (node1->key != key); + node1 = node1->next; + } } #endif @@ -137,147 +137,159 @@ hash_add (cache_ptr *cachep, const void *key, void *value) /* Bump the number of entries in the cache. */ ++(*cachep)->used; - - /* Check the hash table's fullness. We're going - to expand if it is above the fullness level. */ - if (FULLNESS (*cachep)) { - - /* The hash table has reached its fullness level. Time to - expand it. - - I'm using a slow method here but is built on other - primitive functions thereby increasing its - correctness. */ - node_ptr node1 = NULL; - cache_ptr new = hash_new (EXPANSION (*cachep), - (*cachep)->hash_func, - (*cachep)->compare_func); - - DEBUG_PRINTF ("Expanding cache %#x from %d to %d\n", - *cachep, (*cachep)->size, new->size); - - /* Copy the nodes from the first hash table to the new one. */ - while ((node1 = hash_next (*cachep, node1))) - hash_add (&new, node1->key, node1->value); - - /* Trash the old cache. */ - hash_delete (*cachep); - - /* Return a pointer to the new hash table. */ - *cachep = new; - } + + /* Check the hash table's fullness. We're going to expand if it is + above the fullness level. */ + if (FULLNESS (*cachep)) + { + /* The hash table has reached its fullness level. Time to + expand it. + + I'm using a slow method here but is built on other primitive + functions thereby increasing its correctness. */ + node_ptr node1 = NULL; + cache_ptr new = objc_hash_new (EXPANSION (*cachep), + (*cachep)->hash_func, + (*cachep)->compare_func); + + DEBUG_PRINTF ("Expanding cache %#x from %d to %d\n", + (int) *cachep, (*cachep)->size, new->size); + + /* Copy the nodes from the first hash table to the new one. */ + while ((node1 = objc_hash_next (*cachep, node1))) + objc_hash_add (&new, node1->key, node1->value); + + /* Trash the old cache. */ + objc_hash_delete (*cachep); + + /* Return a pointer to the new hash table. */ + *cachep = new; + } } - void -hash_remove (cache_ptr cache, const void *key) +objc_hash_remove (cache_ptr cache, const void *key) { - size_t indx = (*cache->hash_func)(cache, key); + size_t indx = (*cache->hash_func) (cache, key); node_ptr node = cache->node_table[indx]; - - /* We assume there is an entry in the table. Error if it is not. */ + /* We assume there is an entry in the table. Error if it is + not. */ assert (node); - /* Special case. First element is the key/value pair to be removed. */ - if ((*cache->compare_func)(node->key, key)) { - cache->node_table[indx] = node->next; - objc_free(node); - } else { - - /* Otherwise, find the hash entry. */ - node_ptr prev = node; - BOOL removed = NO; - - do { - - if ((*cache->compare_func)(node->key, key)) { - prev->next = node->next, removed = YES; - objc_free(node); - } else - prev = node, node = node->next; - } while (!removed && node); - assert (removed); - } - + /* Special case. First element is the key/value pair to be + removed. */ + if ((*cache->compare_func) (node->key, key)) + { + cache->node_table[indx] = node->next; + objc_free(node); + } + else + { + /* Otherwise, find the hash entry. */ + node_ptr prev = node; + BOOL removed = NO; + do + { + if ((*cache->compare_func) (node->key, key)) + { + prev->next = node->next, removed = YES; + objc_free(node); + } + else + prev = node, node = node->next; + } + while (!removed && node); + assert (removed); + } + /* Decrement the number of entries in the hash table. */ --cache->used; } node_ptr -hash_next (cache_ptr cache, node_ptr node) +objc_hash_next (cache_ptr cache, node_ptr node) { - /* If the scan is being started then reset the last node - visitied pointer and bucket index. */ + /* If the scan is being started then reset the last node visitied + pointer and bucket index. */ if (!node) cache->last_bucket = 0; - - /* If there is a node visited last then check for another - entry in the same bucket; Otherwise step to the next bucket. */ - if (node) { - if (node->next) - /* There is a node which follows the last node - returned. Step to that node and retun it. */ - return node->next; - else - ++cache->last_bucket; - } - - /* If the list isn't exhausted then search the buckets for - other nodes. */ - if (cache->last_bucket < cache->size) { - /* Scan the remainder of the buckets looking for an entry - at the head of the list. Return the first item found. */ - while (cache->last_bucket < cache->size) - if (cache->node_table[cache->last_bucket]) - return cache->node_table[cache->last_bucket]; + + /* If there is a node visited last then check for another entry in + the same bucket. Otherwise step to the next bucket. */ + if (node) + { + if (node->next) + { + /* There is a node which follows the last node returned. + Step to that node and retun it. */ + return node->next; + } else - ++cache->last_bucket; + ++cache->last_bucket; + } - /* No further nodes were found in the hash table. */ - return NULL; - } else + /* If the list isn't exhausted then search the buckets for other + nodes. */ + if (cache->last_bucket < cache->size) + { + /* Scan the remainder of the buckets looking for an entry at + the head of the list. Return the first item found. */ + while (cache->last_bucket < cache->size) + if (cache->node_table[cache->last_bucket]) + return cache->node_table[cache->last_bucket]; + else + ++cache->last_bucket; + + /* No further nodes were found in the hash table. */ + return NULL; + } + else return NULL; } -/* Given KEY, return corresponding value for it in CACHE. - Return NULL if the KEY is not recorded. */ - +/* Given KEY, return corresponding value for it in CACHE. Return NULL + if the KEY is not recorded. */ void * -hash_value_for_key (cache_ptr cache, const void *key) +objc_hash_value_for_key (cache_ptr cache, const void *key) { - node_ptr node = cache->node_table[(*cache->hash_func)(cache, key)]; + node_ptr node = cache->node_table[(*cache->hash_func) (cache, key)]; void *retval = NULL; if (node) - do { - if ((*cache->compare_func)(node->key, key)) { - retval = node->value; - break; - } else - node = node->next; - } while (!retval && node); - + do + { + if ((*cache->compare_func) (node->key, key)) + { + retval = node->value; + break; + } + else + node = node->next; + } + while (! retval && node); + return retval; } -/* Given KEY, return YES if it exists in the CACHE. - Return NO if it does not */ - +/* Given KEY, return YES if it exists in the CACHE. Return NO if it + does not */ BOOL -hash_is_key_in_hash (cache_ptr cache, const void *key) +objc_hash_is_key_in_hash (cache_ptr cache, const void *key) { - node_ptr node = cache->node_table[(*cache->hash_func)(cache, key)]; - + node_ptr node = cache->node_table[(*cache->hash_func) (cache, key)]; + if (node) - do { - if ((*cache->compare_func)(node->key, key)) + do + { + if ((*cache->compare_func)(node->key, key)) return YES; - else - node = node->next; - } while (node); + else + node = node->next; + } + while (node); return NO; }