aboutsummaryrefslogtreecommitdiff
path: root/libobjc/objc/hash.h
blob: e3002c4539af67c14f07dd9fd133abdb350db35d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
/* Hash tables for Objective C method dispatch.
   Copyright (C) 1993, 1995, 1996, 2004 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 2, 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.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING.  If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.  */

/* 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.  */


#ifndef __hash_INCLUDE_GNU
#define __hash_INCLUDE_GNU

#include <stddef.h>
#include <string.h>
#include <objc/objc.h>

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/*
 * 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;


/* Two important hash tables.  */
extern cache_ptr module_hash_table, class_hash_table;

/* 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);
}

#ifndef OBJC_IGNORE_DEPRECATED_API
/* Deprecated as of 4.0 */

static inline cache_ptr
hash_new (unsigned int size,
	  hash_func_type hash_func,
	  compare_func_type compare_func) __attribute__ ((deprecated));
static inline cache_ptr
hash_new (unsigned int size,
	  hash_func_type hash_func,
	  compare_func_type compare_func)
{
  return objc_hash_new(size, hash_func, compare_func);
}

static inline void
hash_delete(cache_ptr cache) __attribute__ ((deprecated));
static inline void
hash_delete(cache_ptr cache)
{
  objc_hash_delete(cache);
}

static inline void
hash_add (cache_ptr *cachep,
	  const void *key,
	  void *value) __attribute__ ((deprecated));
static inline void
hash_add (cache_ptr *cachep, const void *key, void *value)
{
  objc_hash_add(cachep, key, value);
}

static inline void
hash_remove (cache_ptr cache, const void *key) __attribute__ ((deprecated));
static inline void
hash_remove (cache_ptr cache, const void *key)
{
  objc_hash_remove (cache, key);
}

static inline node_ptr
hash_next (cache_ptr cache, node_ptr node) __attribute__ ((deprecated));
static inline node_ptr
hash_next (cache_ptr cache, node_ptr node)
{
  return objc_hash_next (cache, node);
}

static inline void *
hash_value_for_key (cache_ptr cache,
		    const void *key) __attribute__ ((deprecated));
static inline void *
hash_value_for_key (cache_ptr cache, const void *key)
{
  return objc_hash_value_for_key (cache, key);
}

static inline BOOL
hash_is_key_in_hash (cache_ptr cache,
		     const void *key) __attribute__ ((deprecated));
static inline BOOL
hash_is_key_in_hash (cache_ptr cache, const void *key)
{
  return objc_hash_is_key_in_hash (cache, key);
}

static inline unsigned int
hash_ptr (cache_ptr cache, const void *key) __attribute__ ((deprecated));
static inline unsigned int
hash_ptr (cache_ptr cache, const void *key)
{
  return objc_hash_ptr (cache, key);
}

static inline unsigned int 
hash_string (cache_ptr cache, const void *key) __attribute__ ((deprecated));
static inline unsigned int 
hash_string (cache_ptr cache, const void *key)
{
  return objc_hash_string (cache, key);
}

static inline int 
compare_ptrs (const void *k1, const void *k2) __attribute__ ((deprecated));
static inline int 
compare_ptrs (const void *k1, const void *k2)
{
  return objc_compare_ptrs (k1, k2);
}

static inline int 
compare_strings (const void *k1, const void *k2) __attribute__ ((deprecated));
static inline int 
compare_strings (const void *k1, const void *k2)
{
  return objc_compare_strings (k1, k2);
}
#endif /* OBJC_IGNORE_DEPRECATED_API */


#ifdef __cplusplus
}
#endif /* __cplusplus */


#endif /* not __hash_INCLUDE_GNU */