blob: 57def383f5584e2bfac7be050bd6d4754dad5c15 [file] [log] [blame]
njn3e884182003-04-15 13:03:23 +00001
2/*--------------------------------------------------------------------*/
3/*--- A separately chained hash table. vg_hashtable.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, an extensible x86 protected-mode
8 emulator for monitoring program execution on x86-Unixes.
9
njn0e1b5142003-04-15 14:58:06 +000010 Copyright (C) 2000-2003 Julian Seward
njn3e884182003-04-15 13:03:23 +000011 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 "vg_include.h"
32
33/*--------------------------------------------------------------------*/
34/*--- Declarations ---*/
35/*--------------------------------------------------------------------*/
36
37/* Holds malloc'd but not freed blocks. Static, so zero-inited by default. */
38
sewardj59fb25c2003-09-28 16:32:58 +000039#define VG_N_CHAINS 4999 /* a prime number */
njn3e884182003-04-15 13:03:23 +000040
41#define VG_CHAIN_NO(aa) (((UInt)(aa)) % VG_N_CHAINS)
42
43/*--------------------------------------------------------------------*/
44/*--- Functions ---*/
45/*--------------------------------------------------------------------*/
46
47VgHashTable VG_(HT_construct)(void)
48{
njnce46c2a2003-07-21 10:52:07 +000049 /* Initialises to zero, ie. all entries NULL */
njn84d669f2003-07-21 11:42:27 +000050 return VG_(calloc)(VG_N_CHAINS, sizeof(VgHashNode*));
njn3e884182003-04-15 13:03:23 +000051}
52
53Int VG_(HT_count_nodes) ( VgHashTable table )
54{
55 VgHashNode* node;
56 UInt chain;
57 Int n = 0;
58
59 for (chain = 0; chain < VG_N_CHAINS; chain++)
60 for (node = table[chain]; node != NULL; node = node->next)
61 n++;
62 return n;
63}
64
65/* Puts a new, heap allocated VgHashNode, into the malloclist. */
66void VG_(HT_add_node) ( VgHashTable table, VgHashNode* node )
67{
68 UInt chain = VG_CHAIN_NO(node->key);
69 node->next = table[chain];
70 table[chain] = node;
71}
72
73/* Looks up a VgHashNode in the table. Also returns the address of
74 the previous node's `next' pointer which allows it to be removed from the
75 list later without having to look it up again. */
76VgHashNode* VG_(HT_get_node) ( VgHashTable table, UInt key,
77 /*OUT*/VgHashNode*** next_ptr )
78{
79 VgHashNode *prev, *curr;
80 Int chain;
81
82 chain = VG_CHAIN_NO(key);
83
84 prev = NULL;
85 curr = table[chain];
86 while (True) {
87 if (curr == NULL)
88 break;
89 if (key == curr->key)
90 break;
91 prev = curr;
92 curr = curr->next;
93 }
94
95 if (NULL == prev)
96 *next_ptr = & table[chain];
97 else
98 *next_ptr = & prev->next;
99
100 return curr;
101}
102
njn3e884182003-04-15 13:03:23 +0000103/* Allocates a suitably-sized array, copies all the malloc'd block
njn06072ec2003-09-30 15:35:13 +0000104 shadows into it, then returns both the array and the size of it. This is
105 used by the memory-leak detector.
njn3e884182003-04-15 13:03:23 +0000106*/
njn06072ec2003-09-30 15:35:13 +0000107VgHashNode** VG_(HT_to_array) ( VgHashTable table, /*OUT*/ UInt* n_shadows )
njn3e884182003-04-15 13:03:23 +0000108{
109 UInt i, j;
110 VgHashNode** arr;
111 VgHashNode* node;
112
113 *n_shadows = 0;
114 for (i = 0; i < VG_N_CHAINS; i++) {
115 for (node = table[i]; node != NULL; node = node->next) {
116 (*n_shadows)++;
117 }
118 }
119 if (*n_shadows == 0)
120 return NULL;
121
122 arr = VG_(malloc)( *n_shadows * sizeof(VgHashNode*) );
123
124 j = 0;
125 for (i = 0; i < VG_N_CHAINS; i++) {
126 for (node = table[i]; node != NULL; node = node->next) {
127 arr[j++] = node;
128 }
129 }
njn8372b7f2003-05-14 12:42:14 +0000130 vg_assert(j == *n_shadows);
njn3e884182003-04-15 13:03:23 +0000131
njn3e884182003-04-15 13:03:23 +0000132 return arr;
133}
134
135/* Return the first VgHashNode satisfying the predicate p. */
136VgHashNode* VG_(HT_first_match) ( VgHashTable table, Bool (*p) ( VgHashNode* ))
137{
138 UInt i;
139 VgHashNode* node;
140
141 for (i = 0; i < VG_N_CHAINS; i++)
142 for (node = table[i]; node != NULL; node = node->next)
143 if ( p(node) )
144 return node;
145
146 return NULL;
147}
148
149void VG_(HT_apply_to_all_nodes)( VgHashTable table, void (*f)(VgHashNode*) )
150{
151 UInt i;
152 VgHashNode* node;
153
154 for (i = 0; i < VG_N_CHAINS; i++) {
155 for (node = table[i]; node != NULL; node = node->next) {
156 f(node);
157 }
158 }
159}
160
161void VG_(HT_destruct)(VgHashTable table)
162{
163 UInt i;
164 VgHashNode* node;
165
166 for (i = 0; i < VG_N_CHAINS; i++) {
167 for (node = table[i]; node != NULL; node = node->next) {
168 VG_(free)(node);
169 }
170 }
171 VG_(free)(table);
172}
173
174/*--------------------------------------------------------------------*/
175/*--- end vg_hashtable.c ---*/
176/*--------------------------------------------------------------------*/