1*e4b17023SJohn Marino /* Hash tables for Objective C method dispatch.
2*e4b17023SJohn Marino Copyright (C) 1993, 1995, 1996, 2004, 2009 Free Software Foundation, Inc.
3*e4b17023SJohn Marino
4*e4b17023SJohn Marino This file is part of GCC.
5*e4b17023SJohn Marino
6*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify
7*e4b17023SJohn Marino it under the terms of the GNU General Public License as published by
8*e4b17023SJohn Marino the Free Software Foundation; either version 3, or (at your option)
9*e4b17023SJohn Marino any later version.
10*e4b17023SJohn Marino
11*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful,
12*e4b17023SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
13*e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*e4b17023SJohn Marino GNU General Public License for more details.
15*e4b17023SJohn Marino
16*e4b17023SJohn Marino Under Section 7 of GPL version 3, you are granted additional
17*e4b17023SJohn Marino permissions described in the GCC Runtime Library Exception, version
18*e4b17023SJohn Marino 3.1, as published by the Free Software Foundation.
19*e4b17023SJohn Marino
20*e4b17023SJohn Marino You should have received a copy of the GNU General Public License and
21*e4b17023SJohn Marino a copy of the GCC Runtime Library Exception along with this program;
22*e4b17023SJohn Marino see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
24*e4b17023SJohn Marino
25*e4b17023SJohn Marino /* You need to include this file after including objc.h */
26*e4b17023SJohn Marino
27*e4b17023SJohn Marino #ifndef __hash_INCLUDE_GNU
28*e4b17023SJohn Marino #define __hash_INCLUDE_GNU
29*e4b17023SJohn Marino
30*e4b17023SJohn Marino #include <stddef.h>
31*e4b17023SJohn Marino #include <string.h>
32*e4b17023SJohn Marino
33*e4b17023SJohn Marino /*
34*e4b17023SJohn Marino * This data structure is used to hold items
35*e4b17023SJohn Marino * stored in a hash table. Each node holds
36*e4b17023SJohn Marino * a key/value pair.
37*e4b17023SJohn Marino *
38*e4b17023SJohn Marino * Items in the cache are really of type void *.
39*e4b17023SJohn Marino */
40*e4b17023SJohn Marino typedef struct cache_node
41*e4b17023SJohn Marino {
42*e4b17023SJohn Marino struct cache_node *next; /* Pointer to next entry on the list.
43*e4b17023SJohn Marino NULL indicates end of list. */
44*e4b17023SJohn Marino const void *key; /* Key used to locate the value. Used
45*e4b17023SJohn Marino to locate value when more than one
46*e4b17023SJohn Marino key computes the same hash
47*e4b17023SJohn Marino value. */
48*e4b17023SJohn Marino void *value; /* Value stored for the key. */
49*e4b17023SJohn Marino } *node_ptr;
50*e4b17023SJohn Marino
51*e4b17023SJohn Marino
52*e4b17023SJohn Marino /*
53*e4b17023SJohn Marino * This data type is the function that computes a hash code given a key.
54*e4b17023SJohn Marino * Therefore, the key can be a pointer to anything and the function specific
55*e4b17023SJohn Marino * to the key type.
56*e4b17023SJohn Marino *
57*e4b17023SJohn Marino * Unfortunately there is a mutual data structure reference problem with this
58*e4b17023SJohn Marino * typedef. Therefore, to remove compiler warnings the functions passed to
59*e4b17023SJohn Marino * objc_hash_new will have to be casted to this type.
60*e4b17023SJohn Marino */
61*e4b17023SJohn Marino typedef unsigned int (*hash_func_type) (void *, const void *);
62*e4b17023SJohn Marino
63*e4b17023SJohn Marino /*
64*e4b17023SJohn Marino * This data type is the function that compares two hash keys and returns an
65*e4b17023SJohn Marino * integer greater than, equal to, or less than 0, according as the first
66*e4b17023SJohn Marino * parameter is lexicographically greater than, equal to, or less than the
67*e4b17023SJohn Marino * second.
68*e4b17023SJohn Marino */
69*e4b17023SJohn Marino
70*e4b17023SJohn Marino typedef int (*compare_func_type) (const void *, const void *);
71*e4b17023SJohn Marino
72*e4b17023SJohn Marino
73*e4b17023SJohn Marino /*
74*e4b17023SJohn Marino * This data structure is the cache.
75*e4b17023SJohn Marino *
76*e4b17023SJohn Marino * It must be passed to all of the hashing routines
77*e4b17023SJohn Marino * (except for new).
78*e4b17023SJohn Marino */
79*e4b17023SJohn Marino typedef struct cache
80*e4b17023SJohn Marino {
81*e4b17023SJohn Marino /* Variables used to implement the hash itself. */
82*e4b17023SJohn Marino node_ptr *node_table; /* Pointer to an array of hash nodes. */
83*e4b17023SJohn Marino /* Variables used to track the size of the hash table so to determine
84*e4b17023SJohn Marino when to resize it. */
85*e4b17023SJohn Marino unsigned int size; /* Number of buckets allocated for the hash table
86*e4b17023SJohn Marino (number of array entries allocated for
87*e4b17023SJohn Marino "node_table"). Must be a power of two. */
88*e4b17023SJohn Marino unsigned int used; /* Current number of entries in the hash table. */
89*e4b17023SJohn Marino unsigned int mask; /* Precomputed mask. */
90*e4b17023SJohn Marino
91*e4b17023SJohn Marino /* Variables used to implement indexing through the hash table. */
92*e4b17023SJohn Marino
93*e4b17023SJohn Marino unsigned int last_bucket; /* Tracks which entry in the array where
94*e4b17023SJohn Marino the last value was returned. */
95*e4b17023SJohn Marino /* Function used to compute a hash code given a key.
96*e4b17023SJohn Marino This function is specified when the hash table is created. */
97*e4b17023SJohn Marino hash_func_type hash_func;
98*e4b17023SJohn Marino /* Function used to compare two hash keys to see if they are equal. */
99*e4b17023SJohn Marino compare_func_type compare_func;
100*e4b17023SJohn Marino } *cache_ptr;
101*e4b17023SJohn Marino
102*e4b17023SJohn Marino
103*e4b17023SJohn Marino /* Allocate and initialize a hash table. */
104*e4b17023SJohn Marino
105*e4b17023SJohn Marino cache_ptr objc_hash_new (unsigned int size,
106*e4b17023SJohn Marino hash_func_type hash_func,
107*e4b17023SJohn Marino compare_func_type compare_func);
108*e4b17023SJohn Marino
109*e4b17023SJohn Marino /* Deallocate all of the hash nodes and the cache itself. */
110*e4b17023SJohn Marino
111*e4b17023SJohn Marino void objc_hash_delete (cache_ptr cache);
112*e4b17023SJohn Marino
113*e4b17023SJohn Marino /* Add the key/value pair to the hash table. If the
114*e4b17023SJohn Marino hash table reaches a level of fullness then it will be resized.
115*e4b17023SJohn Marino
116*e4b17023SJohn Marino assert if the key is already in the hash. */
117*e4b17023SJohn Marino
118*e4b17023SJohn Marino void objc_hash_add (cache_ptr *cachep, const void *key, void *value);
119*e4b17023SJohn Marino
120*e4b17023SJohn Marino /* Remove the key/value pair from the hash table.
121*e4b17023SJohn Marino assert if the key isn't in the table. */
122*e4b17023SJohn Marino
123*e4b17023SJohn Marino void objc_hash_remove (cache_ptr cache, const void *key);
124*e4b17023SJohn Marino
125*e4b17023SJohn Marino /* Used to index through the hash table. Start with NULL
126*e4b17023SJohn Marino to get the first entry.
127*e4b17023SJohn Marino
128*e4b17023SJohn Marino Successive calls pass the value returned previously.
129*e4b17023SJohn Marino ** Don't modify the hash during this operation ***
130*e4b17023SJohn Marino
131*e4b17023SJohn Marino Cache nodes are returned such that key or value can
132*e4b17023SJohn Marino be extracted. */
133*e4b17023SJohn Marino
134*e4b17023SJohn Marino node_ptr objc_hash_next (cache_ptr cache, node_ptr node);
135*e4b17023SJohn Marino
136*e4b17023SJohn Marino /* Used to return a value from a hash table using a given key. */
137*e4b17023SJohn Marino
138*e4b17023SJohn Marino void *objc_hash_value_for_key (cache_ptr cache, const void *key);
139*e4b17023SJohn Marino
140*e4b17023SJohn Marino /* Used to determine if the given key exists in the hash table */
141*e4b17023SJohn Marino
142*e4b17023SJohn Marino BOOL objc_hash_is_key_in_hash (cache_ptr cache, const void *key);
143*e4b17023SJohn Marino
144*e4b17023SJohn Marino /************************************************
145*e4b17023SJohn Marino
146*e4b17023SJohn Marino Useful hashing functions.
147*e4b17023SJohn Marino
148*e4b17023SJohn Marino Declared inline for your pleasure.
149*e4b17023SJohn Marino
150*e4b17023SJohn Marino ************************************************/
151*e4b17023SJohn Marino
152*e4b17023SJohn Marino /* Calculate a hash code by performing some
153*e4b17023SJohn Marino manipulation of the key pointer. (Use the lowest bits
154*e4b17023SJohn Marino except for those likely to be 0 due to alignment.) */
155*e4b17023SJohn Marino
156*e4b17023SJohn Marino static inline unsigned int
objc_hash_ptr(cache_ptr cache,const void * key)157*e4b17023SJohn Marino objc_hash_ptr (cache_ptr cache, const void *key)
158*e4b17023SJohn Marino {
159*e4b17023SJohn Marino return ((size_t)key / sizeof (void *)) & cache->mask;
160*e4b17023SJohn Marino }
161*e4b17023SJohn Marino
162*e4b17023SJohn Marino
163*e4b17023SJohn Marino /* Calculate a hash code by iterating over a NULL
164*e4b17023SJohn Marino terminate string. */
165*e4b17023SJohn Marino static inline unsigned int
objc_hash_string(cache_ptr cache,const void * key)166*e4b17023SJohn Marino objc_hash_string (cache_ptr cache, const void *key)
167*e4b17023SJohn Marino {
168*e4b17023SJohn Marino unsigned int ret = 0;
169*e4b17023SJohn Marino unsigned int ctr = 0;
170*e4b17023SJohn Marino const char *ckey = (const char *) key;
171*e4b17023SJohn Marino
172*e4b17023SJohn Marino while (*ckey) {
173*e4b17023SJohn Marino ret ^= *ckey++ << ctr;
174*e4b17023SJohn Marino ctr = (ctr + 1) % sizeof (void *);
175*e4b17023SJohn Marino }
176*e4b17023SJohn Marino
177*e4b17023SJohn Marino return ret & cache->mask;
178*e4b17023SJohn Marino }
179*e4b17023SJohn Marino
180*e4b17023SJohn Marino
181*e4b17023SJohn Marino /* Compare two pointers for equality. */
182*e4b17023SJohn Marino static inline int
objc_compare_ptrs(const void * k1,const void * k2)183*e4b17023SJohn Marino objc_compare_ptrs (const void *k1, const void *k2)
184*e4b17023SJohn Marino {
185*e4b17023SJohn Marino return (k1 == k2);
186*e4b17023SJohn Marino }
187*e4b17023SJohn Marino
188*e4b17023SJohn Marino
189*e4b17023SJohn Marino /* Compare two strings. */
190*e4b17023SJohn Marino static inline int
objc_compare_strings(const void * k1,const void * k2)191*e4b17023SJohn Marino objc_compare_strings (const void *k1, const void *k2)
192*e4b17023SJohn Marino {
193*e4b17023SJohn Marino if (k1 == k2)
194*e4b17023SJohn Marino return 1;
195*e4b17023SJohn Marino else if (k1 == 0 || k2 == 0)
196*e4b17023SJohn Marino return 0;
197*e4b17023SJohn Marino else
198*e4b17023SJohn Marino return ! strcmp ((const char *) k1, (const char *) k2);
199*e4b17023SJohn Marino }
200*e4b17023SJohn Marino
201*e4b17023SJohn Marino #endif /* not __hash_INCLUDE_GNU */
202