m_hashtable.c revision 81c00df9ac724e898179dd90e52b2e15deb11fd8
1
2/*--------------------------------------------------------------------*/
3/*--- A separately chained hash table.               m_hashtable.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7   This file is part of Valgrind, a dynamic binary instrumentation
8   framework.
9
10   Copyright (C) 2000-2005 Julian Seward
11      jseward@acm.org
12
13   This program is free software; you can redistribute it and/or
14   modify it under the terms of the GNU General Public License as
15   published by the Free Software Foundation; either version 2 of the
16   License, or (at your option) any later version.
17
18   This program is distributed in the hope that it will be useful, but
19   WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21   General Public License for more details.
22
23   You should have received a copy of the GNU General Public License
24   along with this program; if not, write to the Free Software
25   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26   02111-1307, USA.
27
28   The GNU General Public License is contained in the file COPYING.
29*/
30
31#include "core.h"
32#include "pub_core_hashtable.h"
33
34/*--------------------------------------------------------------------*/
35/*--- Declarations                                                 ---*/
36/*--------------------------------------------------------------------*/
37
38/* Holds malloc'd but not freed blocks.  Static, so zero-inited by default. */
39
40#define VG_N_CHAINS 4999 /* a prime number */
41
42#define VG_CHAIN_NO(aa) (((UWord)(aa)) % VG_N_CHAINS)
43
44/*--------------------------------------------------------------------*/
45/*--- Functions                                                    ---*/
46/*--------------------------------------------------------------------*/
47
48VgHashTable VG_(HT_construct)(void)
49{
50   /* Initialises to zero, ie. all entries NULL */
51   return VG_(calloc)(VG_N_CHAINS, sizeof(VgHashNode*));
52}
53
54Int VG_(HT_count_nodes) ( VgHashTable table )
55{
56   VgHashNode* node;
57   UInt      chain;
58   Int       n = 0;
59
60   for (chain = 0; chain < VG_N_CHAINS; chain++)
61      for (node = table[chain]; node != NULL; node = node->next)
62         n++;
63   return n;
64}
65
66/* Puts a new, heap allocated VgHashNode, into the malloclist. */
67void VG_(HT_add_node) ( VgHashTable table, VgHashNode* node )
68{
69   UInt chain   = VG_CHAIN_NO(node->key);
70   node->next   = table[chain];
71   table[chain] = node;
72}
73
74/* Looks up a VgHashNode in the table.  Also returns the address of
75   the previous node's `next' pointer which allows it to be removed from the
76   list later without having to look it up again.  */
77VgHashNode* VG_(HT_get_node) ( VgHashTable table, UWord key,
78                             /*OUT*/VgHashNode*** next_ptr )
79{
80   VgHashNode *prev, *curr;
81   Int       chain;
82
83   chain = VG_CHAIN_NO(key);
84
85   prev = NULL;
86   curr = table[chain];
87   while (True) {
88      if (curr == NULL)
89         break;
90      if (key == curr->key)
91         break;
92      prev = curr;
93      curr = curr->next;
94   }
95
96   if (NULL == prev)
97      *next_ptr = & table[chain];
98   else
99      *next_ptr = & prev->next;
100
101   return curr;
102}
103
104/* Allocates a suitably-sized array, copies all the malloc'd block
105   shadows into it, then returns both the array and the size of it.  This is
106   used by the memory-leak detector.
107*/
108VgHashNode** VG_(HT_to_array) ( VgHashTable table, /*OUT*/ UInt* n_shadows )
109{
110   UInt       i, j;
111   VgHashNode** arr;
112   VgHashNode*  node;
113
114   *n_shadows = 0;
115   for (i = 0; i < VG_N_CHAINS; i++) {
116      for (node = table[i]; node != NULL; node = node->next) {
117         (*n_shadows)++;
118      }
119   }
120   if (*n_shadows == 0)
121      return NULL;
122
123   arr = VG_(malloc)( *n_shadows * sizeof(VgHashNode*) );
124
125   j = 0;
126   for (i = 0; i < VG_N_CHAINS; i++) {
127      for (node = table[i]; node != NULL; node = node->next) {
128         arr[j++] = node;
129      }
130   }
131   vg_assert(j == *n_shadows);
132
133   return arr;
134}
135
136/* Return the first VgHashNode satisfying the predicate p. */
137VgHashNode* VG_(HT_first_match) ( VgHashTable table,
138                                  Bool (*p) ( VgHashNode*, void* ),
139                                  void* d )
140{
141   UInt      i;
142   VgHashNode* node;
143
144   for (i = 0; i < VG_N_CHAINS; i++)
145      for (node = table[i]; node != NULL; node = node->next)
146         if ( p(node, d) )
147            return node;
148
149   return NULL;
150}
151
152void VG_(HT_apply_to_all_nodes)( VgHashTable table,
153                                 void (*f)(VgHashNode*, void*),
154                                 void* d )
155{
156   UInt      i;
157   VgHashNode* node;
158
159   for (i = 0; i < VG_N_CHAINS; i++) {
160      for (node = table[i]; node != NULL; node = node->next) {
161         f(node, d);
162      }
163   }
164}
165
166void VG_(HT_destruct)(VgHashTable table)
167{
168   UInt      i;
169   VgHashNode* node;
170
171   for (i = 0; i < VG_N_CHAINS; i++) {
172      for (node = table[i]; node != NULL; node = node->next) {
173         VG_(free)(node);
174      }
175   }
176   VG_(free)(table);
177}
178
179/*--------------------------------------------------------------------*/
180/*--- end                                                          ---*/
181/*--------------------------------------------------------------------*/
182