| /* Hash tables for Objective C method dispatch. |
| Copyright (C) 1993-2022 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 */ |