OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [branches/] [oc/] [gdb-5.0/] [libiberty/] [hashtab.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 106 markom
/* An expandable hash tables datatype.
2
   Copyright (C) 1999 Free Software Foundation, Inc.
3
   Contributed by Vladimir Makarov (vmakarov@cygnus.com).
4
 
5
This file is part of the libiberty library.
6
Libiberty is free software; you can redistribute it and/or
7
modify it under the terms of the GNU Library General Public
8
License as published by the Free Software Foundation; either
9
version 2 of the License, or (at your option) any later version.
10
 
11
Libiberty is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
Library General Public License for more details.
15
 
16
You should have received a copy of the GNU Library General Public
17
License along with libiberty; see the file COPYING.LIB.  If
18
not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19
Boston, MA 02111-1307, USA.  */
20
 
21
/* This package implements basic hash table functionality.  It is possible
22
   to search for an entry, create an entry and destroy an entry.
23
 
24
   Elements in the table are generic pointers.
25
 
26
   The size of the table is not fixed; if the occupancy of the table
27
   grows too high the hash table will be expanded.
28
 
29
   The abstract data implementation is based on generalized Algorithm D
30
   from Knuth's book "The art of computer programming".  Hash table is
31
   expanded by creation of new hash table and transferring elements from
32
   the old table to the new table. */
33
 
34
#ifdef HAVE_CONFIG_H
35
#include "config.h"
36
#endif
37
 
38
#include <sys/types.h>
39
 
40
#ifdef HAVE_STDLIB_H
41
#include <stdlib.h>
42
#endif
43
 
44
#include <stdio.h>
45
 
46
#include "libiberty.h"
47
#include "hashtab.h"
48
 
49
/* This macro defines reserved value for empty table entry. */
50
 
51
#define EMPTY_ENTRY    ((void *) 0)
52
 
53
/* This macro defines reserved value for table entry which contained
54
   a deleted element. */
55
 
56
#define DELETED_ENTRY  ((void *) 1)
57
 
58
/* The following function returns the nearest prime number which is
59
   greater than given source number. */
60
 
61
static unsigned long
62
higher_prime_number (n)
63
     unsigned long n;
64
{
65
  unsigned long i;
66
 
67
  n |= 0x01;  /* Force N to be odd.  */
68
  if (n < 9)
69
    return n; /* All odd numbers < 9 are prime.  */
70
 
71
 next:
72
  n += 2;
73
  i = 3;
74
  do
75
    {
76
      if (n % i == 0)
77
        goto next;
78
      i += 2;
79
    }
80
  while ((i * i) <= n);
81
 
82
  return n;
83
}
84
 
85
/* This function creates table with length slightly longer than given
86
   source length.  Created hash table is initiated as empty (all the
87
   hash table entries are EMPTY_ENTRY).  The function returns the
88
   created hash table. */
89
 
90
htab_t
91
htab_create (size, hash_f, eq_f, del_f)
92
     size_t size;
93
     htab_hash hash_f;
94
     htab_eq eq_f;
95
     htab_del del_f;
96
{
97
  htab_t result;
98
 
99
  size = higher_prime_number (size);
100
  result = (htab_t) xcalloc (1, sizeof (struct htab));
101
  result->entries = (void **) xcalloc (size, sizeof (void *));
102
  result->size = size;
103
  result->hash_f = hash_f;
104
  result->eq_f = eq_f;
105
  result->del_f = del_f;
106
  return result;
107
}
108
 
109
/* This function frees all memory allocated for given hash table.
110
   Naturally the hash table must already exist. */
111
 
112
void
113
htab_delete (htab)
114
     htab_t htab;
115
{
116
  int i;
117
  if (htab->del_f)
118
    for (i = htab->size - 1; i >= 0; i--)
119
      {
120
        if (htab->entries[i] != EMPTY_ENTRY
121
            && htab->entries[i] != DELETED_ENTRY)
122
          (*htab->del_f) (htab->entries[i]);
123
      }
124
 
125
  free (htab->entries);
126
  free (htab);
127
}
128
 
129
/* This function clears all entries in the given hash table.  */
130
 
131
void
132
htab_empty (htab)
133
     htab_t htab;
134
{
135
  int i;
136
  if (htab->del_f)
137
    for (i = htab->size - 1; i >= 0; i--)
138
      {
139
        if (htab->entries[i] != EMPTY_ENTRY
140
            && htab->entries[i] != DELETED_ENTRY)
141
          (*htab->del_f) (htab->entries[i]);
142
      }
143
 
144
  memset (htab->entries, 0, htab->size * sizeof (void *));
145
}
146
 
147
/* Similar to htab_find_slot, but without several unwanted side effects:
148
    - Does not call htab->eq_f when it finds an existing entry.
149
    - Does not change the count of elements/searches/collisions in the
150
      hash table.
151
   This function also assumes there are no deleted entries in the table.
152
   HASH is the hash value for the element to be inserted.  */
153
static void **
154
find_empty_slot_for_expand (htab, hash)
155
     htab_t htab;
156
     unsigned int hash;
157
{
158
  size_t size = htab->size;
159
  unsigned int hash2 = 1 + hash % (size - 2);
160
  unsigned int index = hash % size;
161
 
162
  for (;;)
163
    {
164
      void **slot = htab->entries + index;
165
      if (*slot == EMPTY_ENTRY)
166
        return slot;
167
 
168
      if (*slot == DELETED_ENTRY)
169
        abort ();
170
 
171
      index += hash2;
172
      if (index >= size)
173
        index -= size;
174
    }
175
}
176
 
177
/* The following function changes size of memory allocated for the
178
   entries and repeatedly inserts the table elements.  The occupancy
179
   of the table after the call will be about 50%.  Naturally the hash
180
   table must already exist.  Remember also that the place of the
181
   table entries is changed. */
182
 
183
static void
184
htab_expand (htab)
185
     htab_t htab;
186
{
187
  void **oentries;
188
  void **olimit;
189
  void **p;
190
 
191
  oentries = htab->entries;
192
  olimit = oentries + htab->size;
193
 
194
  htab->size = higher_prime_number (htab->size * 2);
195
  htab->entries = xcalloc (htab->size, sizeof (void **));
196
 
197
  htab->n_elements -= htab->n_deleted;
198
  htab->n_deleted = 0;
199
 
200
  p = oentries;
201
  do
202
    {
203
      void *x = *p;
204
      if (x != EMPTY_ENTRY && x != DELETED_ENTRY)
205
        {
206
          void **q = find_empty_slot_for_expand (htab, (*htab->hash_f) (x));
207
          *q = x;
208
        }
209
      p++;
210
    }
211
  while (p < olimit);
212
  free (oentries);
213
}
214
 
215
/* This function searches for a hash table entry equal to the given
216
   element.  It cannot be used to insert or delete an element.  */
217
 
218
void *
219
htab_find_with_hash (htab, element, hash)
220
     htab_t htab;
221
     const void *element;
222
     unsigned int hash;
223
{
224
  unsigned int index, hash2;
225
  size_t size;
226
 
227
  htab->searches++;
228
  size = htab->size;
229
  hash2 = 1 + hash % (size - 2);
230
  index = hash % size;
231
 
232
  for (;;)
233
    {
234
      void *entry = htab->entries[index];
235
      if (entry == EMPTY_ENTRY)
236
        return NULL;
237
      else if (entry != DELETED_ENTRY && (*htab->eq_f) (entry, element))
238
        return entry;
239
 
240
      htab->collisions++;
241
      index += hash2;
242
      if (index >= size)
243
        index -= size;
244
    }
245
}
246
 
247
/* Like htab_find_slot_with_hash, but compute the hash value from the
248
   element.  */
249
void *
250
htab_find (htab, element)
251
     htab_t htab;
252
     const void *element;
253
{
254
  return htab_find_with_hash (htab, element, (*htab->hash_f) (element));
255
}
256
 
257
/* This function searches for a hash table slot containing an entry
258
   equal to the given element.  To delete an entry, call this with
259
   INSERT = 0, then call htab_clear_slot on the slot returned (possibly
260
   after doing some checks).  To insert an entry, call this with
261
   INSERT = 1, then write the value you want into the returned slot.  */
262
 
263
void **
264
htab_find_slot_with_hash (htab, element, hash, insert)
265
     htab_t htab;
266
     const void *element;
267
     unsigned int hash;
268
     int insert;
269
{
270
  void **first_deleted_slot;
271
  unsigned int index, hash2;
272
  size_t size;
273
 
274
  if (insert && htab->size * 3 <= htab->n_elements * 4)
275
    htab_expand (htab);
276
 
277
  size = htab->size;
278
  hash2 = 1 + hash % (size - 2);
279
  index = hash % size;
280
 
281
  htab->searches++;
282
  first_deleted_slot = NULL;
283
 
284
  for (;;)
285
    {
286
      void *entry = htab->entries[index];
287
      if (entry == EMPTY_ENTRY)
288
        {
289
          if (!insert)
290
            return NULL;
291
 
292
          htab->n_elements++;
293
 
294
          if (first_deleted_slot)
295
            {
296
              *first_deleted_slot = EMPTY_ENTRY;
297
              return first_deleted_slot;
298
            }
299
 
300
          return &htab->entries[index];
301
        }
302
 
303
      if (entry == DELETED_ENTRY)
304
        {
305
          if (!first_deleted_slot)
306
            first_deleted_slot = &htab->entries[index];
307
        }
308
      else
309
        {
310
          if ((*htab->eq_f) (entry, element))
311
            return &htab->entries[index];
312
        }
313
 
314
      htab->collisions++;
315
      index += hash2;
316
      if (index >= size)
317
        index -= size;
318
    }
319
}
320
 
321
/* Like htab_find_slot_with_hash, but compute the hash value from the
322
   element.  */
323
void **
324
htab_find_slot (htab, element, insert)
325
     htab_t htab;
326
     const void *element;
327
     int insert;
328
{
329
  return htab_find_slot_with_hash (htab, element, (*htab->hash_f) (element),
330
                                   insert);
331
}
332
 
333
/* This function deletes an element with the given value from hash
334
   table.  If there is no matching element in the hash table, this
335
   function does nothing.  */
336
 
337
void
338
htab_remove_elt (htab, element)
339
     htab_t htab;
340
     void *element;
341
{
342
  void **slot;
343
 
344
  slot = htab_find_slot (htab, element, 0);
345
  if (*slot == EMPTY_ENTRY)
346
    return;
347
 
348
  if (htab->del_f)
349
    (*htab->del_f) (*slot);
350
 
351
  *slot = DELETED_ENTRY;
352
  htab->n_deleted++;
353
}
354
 
355
/* This function clears a specified slot in a hash table.  It is
356
   useful when you've already done the lookup and don't want to do it
357
   again.  */
358
 
359
void
360
htab_clear_slot (htab, slot)
361
     htab_t htab;
362
     void **slot;
363
{
364
  if (slot < htab->entries || slot >= htab->entries + htab->size
365
      || *slot == EMPTY_ENTRY || *slot == DELETED_ENTRY)
366
    abort ();
367
  if (htab->del_f)
368
    (*htab->del_f) (*slot);
369
  *slot = DELETED_ENTRY;
370
  htab->n_deleted++;
371
}
372
 
373
/* This function scans over the entire hash table calling
374
   CALLBACK for each live entry.  If CALLBACK returns false,
375
   the iteration stops.  INFO is passed as CALLBACK's second
376
   argument.  */
377
 
378
void
379
htab_traverse (htab, callback, info)
380
     htab_t htab;
381
     htab_trav callback;
382
     void *info;
383
{
384
  void **slot, **limit;
385
  slot = htab->entries;
386
  limit = slot + htab->size;
387
  do
388
    {
389
      void *x = *slot;
390
      if (x != EMPTY_ENTRY && x != DELETED_ENTRY)
391
        if (!(*callback) (slot, info))
392
          break;
393
    }
394
  while (++slot < limit);
395
}
396
 
397
/* The following function returns current size of given hash table. */
398
 
399
size_t
400
htab_size (htab)
401
     htab_t htab;
402
{
403
  return htab->size;
404
}
405
 
406
/* The following function returns current number of elements in given
407
   hash table. */
408
 
409
size_t
410
htab_elements (htab)
411
     htab_t htab;
412
{
413
  return htab->n_elements - htab->n_deleted;
414
}
415
 
416
/* The following function returns number of percents of fixed
417
   collisions during all work with given hash table. */
418
 
419
double
420
htab_collisions (htab)
421
     htab_t htab;
422
{
423
  int searches;
424
 
425
  searches = htab->searches;
426
  if (searches == 0)
427
    return 0.0;
428
  return (double)htab->collisions / (double)searches;
429
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.