| /* Hash tables for Objective C method dispatch. | |
| Copyright (C) 1993-2026 Free Software Foundation, Inc. | |
| This file is part of GCC. | |
| 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 3, or (at your option) | |
| any later version. | |
| 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. | |
| 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. | |
| 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 | |
| <http://www.gnu.org/licenses/>. */ | |
| /* You need to include this file after including objc.h */ | |
| #ifndef __hash_INCLUDE_GNU | |
| #define __hash_INCLUDE_GNU | |
| #include <stddef.h> | |
| #include <string.h> | |
| /* | |
| * This data structure is used to hold items | |
| * stored in a hash table. Each node holds | |
| * a key/value pair. | |
| * | |
| * Items in the cache are really of type void *. | |
| */ | |
| typedef struct cache_node | |
| { | |
| struct cache_node *next; /* Pointer to next entry on the list. | |
| NULL indicates end of list. */ | |
| const void *key; /* Key used to locate the value. Used | |
| to locate value when more than one | |
| key computes the same hash | |
| value. */ | |
| void *value; /* Value stored for the key. */ | |
| } *node_ptr; | |
| /* | |
| * This data type is the function that computes a hash code given a key. | |
| * Therefore, the key can be a pointer to anything and the function specific | |
| * to the key type. | |
| * | |
| * Unfortunately there is a mutual data structure reference problem with this | |
| * typedef. Therefore, to remove compiler warnings the functions passed to | |
| * objc_hash_new will have to be casted to this type. | |
| */ | |
| typedef unsigned int (*hash_func_type) (void *, const void *); | |
| /* | |
| * This data type is the function that compares two hash keys and returns an | |
| * integer greater than, equal to, or less than 0, according as the first | |
| * parameter is lexicographically greater than, equal to, or less than the | |
| * second. | |
| */ | |
| typedef int (*compare_func_type) (const void *, const void *); | |
| /* | |
| * This data structure is the cache. | |
| * | |
| * It must be passed to all of the hashing routines | |
| * (except for new). | |
| */ | |
| typedef struct cache | |
| { | |
| /* Variables used to implement the hash itself. */ | |
| node_ptr *node_table; /* Pointer to an array of hash nodes. */ | |
| /* Variables used to track the size of the hash table so to determine | |
| when to resize it. */ | |
| unsigned int size; /* Number of buckets allocated for the hash table | |
| (number of array entries allocated for | |
| "node_table"). Must be a power of two. */ | |
| unsigned int used; /* Current number of entries in the hash table. */ | |
| unsigned int mask; /* Precomputed mask. */ | |
| /* Variables used to implement indexing through the hash table. */ | |
| unsigned int last_bucket; /* Tracks which entry in the array where | |
| the last value was returned. */ | |
| /* Function used to compute a hash code given a key. | |
| This function is specified when the hash table is created. */ | |
| hash_func_type hash_func; | |
| /* Function used to compare two hash keys to see if they are equal. */ | |
| compare_func_type compare_func; | |
| } *cache_ptr; | |
| /* Allocate and initialize a hash table. */ | |
| cache_ptr objc_hash_new (unsigned int size, | |
| hash_func_type hash_func, | |
| compare_func_type compare_func); | |
| /* Deallocate all of the hash nodes and the cache itself. */ | |
| void objc_hash_delete (cache_ptr cache); | |
| /* Add the key/value pair to the hash table. If the | |
| hash table reaches a level of fullness then it will be resized. | |
| assert if the key is already in the hash. */ | |
| void objc_hash_add (cache_ptr *cachep, const void *key, void *value); | |
| /* Remove the key/value pair from the hash table. | |
| assert if the key isn't in the table. */ | |
| void objc_hash_remove (cache_ptr cache, const void *key); | |
| /* Used to index through the hash table. Start with NULL | |
| to get the first entry. | |
| Successive calls pass the value returned previously. | |
| ** Don't modify the hash during this operation *** | |
| Cache nodes are returned such that key or value can | |
| be extracted. */ | |
| node_ptr objc_hash_next (cache_ptr cache, node_ptr node); | |
| /* Used to return a value from a hash table using a given key. */ | |
| void *objc_hash_value_for_key (cache_ptr cache, const void *key); | |
| /* Used to determine if the given key exists in the hash table */ | |
| BOOL objc_hash_is_key_in_hash (cache_ptr cache, const void *key); | |
| /************************************************ | |
| Useful hashing functions. | |
| Declared inline for your pleasure. | |
| ************************************************/ | |
| /* Calculate a hash code by performing some | |
| manipulation of the key pointer. (Use the lowest bits | |
| except for those likely to be 0 due to alignment.) */ | |
| static inline unsigned int | |
| objc_hash_ptr (cache_ptr cache, const void *key) | |
| { | |
| return ((size_t)key / sizeof (void *)) & cache->mask; | |
| } | |
| /* Calculate a hash code by iterating over a NULL | |
| terminate string. */ | |
| static inline unsigned int | |
| objc_hash_string (cache_ptr cache, const void *key) | |
| { | |
| unsigned int ret = 0; | |
| unsigned int ctr = 0; | |
| const char *ckey = (const char *) key; | |
| while (*ckey) { | |
| ret ^= *ckey++ << ctr; | |
| ctr = (ctr + 1) % sizeof (void *); | |
| } | |
| return ret & cache->mask; | |
| } | |
| /* Compare two pointers for equality. */ | |
| static inline int | |
| objc_compare_ptrs (const void *k1, const void *k2) | |
| { | |
| return (k1 == k2); | |
| } | |
| /* Compare two strings. */ | |
| static inline int | |
| objc_compare_strings (const void *k1, const void *k2) | |
| { | |
| if (k1 == k2) | |
| return 1; | |
| else if (k1 == 0 || k2 == 0) | |
| return 0; | |
| else | |
| return ! strcmp ((const char *) k1, (const char *) k2); | |
| } | |
| #endif /* not __hash_INCLUDE_GNU */ |