1 ///////////////////////////////////////////////////////////////////////////////
3 ///////////////////////////////////////////////////////////////////////////////
5 #include <AD/generic/ordering.h>
8 ///////////////////////////////////////////////////////////////////////////////
9 // Import some type definitions
10 ///////////////////////////////////////////////////////////////////////////////
11 typedef HashTable::Key Key
;
12 typedef HashTable::Value Value
;
13 typedef HashTable::Entry Entry
;
14 typedef HashTable::HashFunction HashFunction
;
15 typedef HashTable::Equality Equality
;
17 ///////////////////////////////////////////////////////////////////////////////
18 // Constructor and destructor
19 ///////////////////////////////////////////////////////////////////////////////
20 HashTable:: HashTable(HashFunction h
, Equality e
, int n
)
21 : hash(h
), eq(e
), count(0), table(0), capacity(0), growth_limit(0)
23 HashTable::~HashTable() { delete [] table
; }
25 ///////////////////////////////////////////////////////////////////////////////
26 // Check if a key is in the table.
27 ///////////////////////////////////////////////////////////////////////////////
28 Bool
HashTable::contains (Key key
) const { return lookup(key
) != 0; }
30 ///////////////////////////////////////////////////////////////////////////////
32 ///////////////////////////////////////////////////////////////////////////////
33 void HashTable::clear()
34 { for (Entry
* p
= table
, * q
= p
+ capacity
; p
< q
; p
++) p
->hash_val
= -1;
38 ///////////////////////////////////////////////////////////////////////////////
39 // Increase the size of a table.
40 ///////////////////////////////////////////////////////////////////////////////
41 void HashTable::grow(int n
)
42 { if (n
< capacity
) return;
43 Entry
* new_table
= new Entry
[n
];
45 for (i
= 0; i
< n
; i
++) new_table
[i
].hash_val
= -1;
47 for (i
= 0; i
< capacity
; i
++)
48 { if (table
[i
].hash_val
>= 0) {
49 unsigned int j
, h
= (*hash
)(table
[i
].k
) % n
;
51 { if (new_table
[j
].hash_val
< 0)
52 { new_table
[j
].k
= table
[i
].k
;
53 new_table
[j
].v
= table
[i
].v
;
54 new_table
[j
].hash_val
= h
;
62 if (table
) delete [] table
;
65 growth_limit
= n
* 6 / 10;
68 ///////////////////////////////////////////////////////////////////////////////
69 // Lookup a key from the table. Use linear probing. I'm lazy.
70 ///////////////////////////////////////////////////////////////////////////////
71 const Entry
* HashTable::private_lookup (unsigned int h
, Key k
) const
73 register unsigned int i
= h
;
76 { if (table
[i
].hash_val
< 0 ||
77 table
[i
].hash_val
== h
&& (*eq
)(table
[i
].k
,k
))
79 if (++i
>= capacity
) i
= 0;
83 ///////////////////////////////////////////////////////////////////////////////
84 // Lookup an entry from a key
85 ///////////////////////////////////////////////////////////////////////////////
86 Entry
* HashTable::lookup (Key k
) const
87 { unsigned int h
= (*hash
)(k
) % capacity
;
88 Entry
* e
= (Entry
*)private_lookup(h
,k
);
89 return e
->hash_val
>= 0 ? e
: 0;
92 ///////////////////////////////////////////////////////////////////////////////
93 // Insert a new element into the table.
94 ///////////////////////////////////////////////////////////////////////////////
95 void HashTable::insert (Key k
, Value v
)
96 { if (count
>= growth_limit
) grow(capacity
* 7 / 4 + 32);
97 unsigned int h
= (*hash
)(k
) % capacity
;
98 Entry
* e
= (Entry
*)private_lookup(h
,k
);
99 if (e
->hash_val
>= 0) e
->v
= v
;
100 else { e
->k
= k
; e
->v
= v
; e
->hash_val
= h
; count
++; }
103 ///////////////////////////////////////////////////////////////////////////////
104 // Returns the first element of the table.
105 ///////////////////////////////////////////////////////////////////////////////
106 Entry
* HashTable::first() const
107 { if (count
== 0) return 0;
108 register const Entry
* p
, * q
;
109 for (p
= table
, q
= table
+ capacity
; p
< q
; p
++)
110 if (p
->hash_val
>= 0) return (Entry
*)p
;
114 ///////////////////////////////////////////////////////////////////////////////
115 // Returns the next element from the table.
116 ///////////////////////////////////////////////////////////////////////////////
117 Entry
* HashTable::next(Entry
* p
) const
118 { register const Entry
* q
;
119 for (q
= table
+ capacity
, p
++; p
< q
; p
++)
120 if (p
->hash_val
>= 0) return (Entry
*)p
;
124 ///////////////////////////////////////////////////////////////////////////////
125 // Hashing and equality functions
126 ///////////////////////////////////////////////////////////////////////////////
127 unsigned int string_hash(Key k
) { return hash((const char *)k
); }
128 Bool
string_equal(Key a
, Key b
)
129 { return strcmp((const char *)a
, (const char *)b
) == 0; }
130 unsigned int integer_hash(Key k
) { return (unsigned int)k
; }
131 Bool
integer_equal(Key a
, Key b
) { return a
== b
; }