1*c42dbd0eSchristos /* Copyright (C) 2021 Free Software Foundation, Inc.
2*c42dbd0eSchristos Contributed by Oracle.
3*c42dbd0eSchristos
4*c42dbd0eSchristos This file is part of GNU Binutils.
5*c42dbd0eSchristos
6*c42dbd0eSchristos This program is free software; you can redistribute it and/or modify
7*c42dbd0eSchristos it under the terms of the GNU General Public License as published by
8*c42dbd0eSchristos the Free Software Foundation; either version 3, or (at your option)
9*c42dbd0eSchristos any later version.
10*c42dbd0eSchristos
11*c42dbd0eSchristos This program is distributed in the hope that it will be useful,
12*c42dbd0eSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of
13*c42dbd0eSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*c42dbd0eSchristos GNU General Public License for more details.
15*c42dbd0eSchristos
16*c42dbd0eSchristos You should have received a copy of the GNU General Public License
17*c42dbd0eSchristos along with this program; if not, write to the Free Software
18*c42dbd0eSchristos Foundation, 51 Franklin Street - Fifth Floor, Boston,
19*c42dbd0eSchristos MA 02110-1301, USA. */
20*c42dbd0eSchristos
21*c42dbd0eSchristos #ifndef _DBE_DEFAULTMAP_H
22*c42dbd0eSchristos #define _DBE_DEFAULTMAP_H
23*c42dbd0eSchristos
24*c42dbd0eSchristos #include <assert.h>
25*c42dbd0eSchristos #include <vec.h>
26*c42dbd0eSchristos #include <Map.h>
27*c42dbd0eSchristos
28*c42dbd0eSchristos template <typename Key_t, typename Value_t>
29*c42dbd0eSchristos class DefaultMap : public Map<Key_t, Value_t>
30*c42dbd0eSchristos {
31*c42dbd0eSchristos public:
32*c42dbd0eSchristos
33*c42dbd0eSchristos DefaultMap ();
34*c42dbd0eSchristos ~DefaultMap ();
35*c42dbd0eSchristos void clear ();
36*c42dbd0eSchristos void put (Key_t key, Value_t val);
37*c42dbd0eSchristos Value_t get (Key_t key);
38*c42dbd0eSchristos Value_t get (Key_t key, typename Map<Key_t, Value_t>::Relation rel);
39*c42dbd0eSchristos Value_t remove (Key_t);
40*c42dbd0eSchristos Vector<Key_t> *keySet ();
41*c42dbd0eSchristos Vector<Value_t> *values ();
42*c42dbd0eSchristos
43*c42dbd0eSchristos private:
44*c42dbd0eSchristos
45*c42dbd0eSchristos struct Entry
46*c42dbd0eSchristos {
47*c42dbd0eSchristos Key_t key;
48*c42dbd0eSchristos Value_t val;
49*c42dbd0eSchristos };
50*c42dbd0eSchristos
51*c42dbd0eSchristos static const int CHUNK_SIZE;
52*c42dbd0eSchristos static const int HTABLE_SIZE;
53*c42dbd0eSchristos
54*c42dbd0eSchristos int entries;
55*c42dbd0eSchristos int nchunks;
56*c42dbd0eSchristos Entry **chunks;
57*c42dbd0eSchristos Vector<Entry*> *index;
58*c42dbd0eSchristos Entry **hashTable;
59*c42dbd0eSchristos };
60*c42dbd0eSchristos
61*c42dbd0eSchristos
62*c42dbd0eSchristos template <typename Key_t, typename Value_t>
63*c42dbd0eSchristos const int DefaultMap<Key_t, Value_t>::CHUNK_SIZE = 16384;
64*c42dbd0eSchristos template <typename Key_t, typename Value_t>
65*c42dbd0eSchristos const int DefaultMap<Key_t, Value_t>::HTABLE_SIZE = 1024;
66*c42dbd0eSchristos
67*c42dbd0eSchristos template <typename Key_t, typename Value_t>
DefaultMap()68*c42dbd0eSchristos DefaultMap<Key_t, Value_t>::DefaultMap ()
69*c42dbd0eSchristos {
70*c42dbd0eSchristos entries = 0;
71*c42dbd0eSchristos nchunks = 0;
72*c42dbd0eSchristos chunks = NULL;
73*c42dbd0eSchristos index = new Vector<Entry*>;
74*c42dbd0eSchristos hashTable = new Entry*[HTABLE_SIZE];
75*c42dbd0eSchristos for (int i = 0; i < HTABLE_SIZE; i++)
76*c42dbd0eSchristos hashTable[i] = NULL;
77*c42dbd0eSchristos }
78*c42dbd0eSchristos
79*c42dbd0eSchristos template <typename Key_t, typename Value_t>
~DefaultMap()80*c42dbd0eSchristos DefaultMap<Key_t, Value_t>::~DefaultMap ()
81*c42dbd0eSchristos {
82*c42dbd0eSchristos for (int i = 0; i < nchunks; i++)
83*c42dbd0eSchristos delete[] chunks[i];
84*c42dbd0eSchristos delete[] chunks;
85*c42dbd0eSchristos delete index;
86*c42dbd0eSchristos delete[] hashTable;
87*c42dbd0eSchristos }
88*c42dbd0eSchristos
89*c42dbd0eSchristos template <typename Key_t, typename Value_t>
90*c42dbd0eSchristos void
clear()91*c42dbd0eSchristos DefaultMap<Key_t, Value_t>::clear ()
92*c42dbd0eSchristos {
93*c42dbd0eSchristos entries = 0;
94*c42dbd0eSchristos index->reset ();
95*c42dbd0eSchristos for (int i = 0; i < HTABLE_SIZE; i++)
96*c42dbd0eSchristos hashTable[i] = NULL;
97*c42dbd0eSchristos }
98*c42dbd0eSchristos
99*c42dbd0eSchristos template <typename Key_t>
100*c42dbd0eSchristos inline unsigned
hash(Key_t key)101*c42dbd0eSchristos hash (Key_t key)
102*c42dbd0eSchristos {
103*c42dbd0eSchristos unsigned h = (unsigned) ((unsigned long) key);
104*c42dbd0eSchristos h ^= (h >> 20) ^ (h >> 12);
105*c42dbd0eSchristos return (h ^ (h >> 7) ^ (h >> 4));
106*c42dbd0eSchristos }
107*c42dbd0eSchristos
108*c42dbd0eSchristos template <typename Key_t, typename Value_t>
109*c42dbd0eSchristos void
put(Key_t key,Value_t val)110*c42dbd0eSchristos DefaultMap<Key_t, Value_t>::put (Key_t key, Value_t val)
111*c42dbd0eSchristos {
112*c42dbd0eSchristos unsigned idx = hash (key) % HTABLE_SIZE;
113*c42dbd0eSchristos Entry *entry = hashTable[idx];
114*c42dbd0eSchristos if (entry && entry->key == key)
115*c42dbd0eSchristos {
116*c42dbd0eSchristos entry->val = val;
117*c42dbd0eSchristos return;
118*c42dbd0eSchristos }
119*c42dbd0eSchristos int lo = 0;
120*c42dbd0eSchristos int hi = entries - 1;
121*c42dbd0eSchristos while (lo <= hi)
122*c42dbd0eSchristos {
123*c42dbd0eSchristos int md = (lo + hi) / 2;
124*c42dbd0eSchristos entry = index->fetch (md);
125*c42dbd0eSchristos int cmp = entry->key < key ? -1 : entry->key > key ? 1 : 0;
126*c42dbd0eSchristos if (cmp < 0)
127*c42dbd0eSchristos lo = md + 1;
128*c42dbd0eSchristos else if (cmp > 0)
129*c42dbd0eSchristos hi = md - 1;
130*c42dbd0eSchristos else
131*c42dbd0eSchristos {
132*c42dbd0eSchristos entry->val = val;
133*c42dbd0eSchristos return;
134*c42dbd0eSchristos }
135*c42dbd0eSchristos }
136*c42dbd0eSchristos if (entries >= nchunks * CHUNK_SIZE)
137*c42dbd0eSchristos {
138*c42dbd0eSchristos nchunks++;
139*c42dbd0eSchristos // Reallocate Entry chunk array
140*c42dbd0eSchristos Entry **new_chunks = new Entry*[nchunks];
141*c42dbd0eSchristos for (int i = 0; i < nchunks - 1; i++)
142*c42dbd0eSchristos new_chunks[i] = chunks[i];
143*c42dbd0eSchristos delete[] chunks;
144*c42dbd0eSchristos chunks = new_chunks;
145*c42dbd0eSchristos
146*c42dbd0eSchristos // Allocate new chunk for entries.
147*c42dbd0eSchristos chunks[nchunks - 1] = new Entry[CHUNK_SIZE];
148*c42dbd0eSchristos }
149*c42dbd0eSchristos entry = &chunks[entries / CHUNK_SIZE][entries % CHUNK_SIZE];
150*c42dbd0eSchristos entry->key = key;
151*c42dbd0eSchristos entry->val = val;
152*c42dbd0eSchristos index->insert (lo, entry);
153*c42dbd0eSchristos hashTable[idx] = entry;
154*c42dbd0eSchristos entries++;
155*c42dbd0eSchristos }
156*c42dbd0eSchristos
157*c42dbd0eSchristos template <typename Key_t, typename Value_t>
158*c42dbd0eSchristos Value_t
get(Key_t key)159*c42dbd0eSchristos DefaultMap<Key_t, Value_t>::get (Key_t key)
160*c42dbd0eSchristos {
161*c42dbd0eSchristos unsigned idx = hash (key) % HTABLE_SIZE;
162*c42dbd0eSchristos Entry *entry = hashTable[idx];
163*c42dbd0eSchristos if (entry && entry->key == key)
164*c42dbd0eSchristos return entry->val;
165*c42dbd0eSchristos
166*c42dbd0eSchristos int lo = 0;
167*c42dbd0eSchristos int hi = entries - 1;
168*c42dbd0eSchristos while (lo <= hi)
169*c42dbd0eSchristos {
170*c42dbd0eSchristos int md = (lo + hi) / 2;
171*c42dbd0eSchristos entry = index->fetch (md);
172*c42dbd0eSchristos int cmp = entry->key < key ? -1 : entry->key > key ? 1 : 0;
173*c42dbd0eSchristos if (cmp < 0)
174*c42dbd0eSchristos lo = md + 1;
175*c42dbd0eSchristos else if (cmp > 0)
176*c42dbd0eSchristos hi = md - 1;
177*c42dbd0eSchristos else
178*c42dbd0eSchristos {
179*c42dbd0eSchristos hashTable[idx] = entry;
180*c42dbd0eSchristos return entry->val;
181*c42dbd0eSchristos }
182*c42dbd0eSchristos }
183*c42dbd0eSchristos return (Value_t) 0;
184*c42dbd0eSchristos }
185*c42dbd0eSchristos
186*c42dbd0eSchristos template <typename Key_t, typename Value_t>
187*c42dbd0eSchristos Value_t
get(Key_t key,typename Map<Key_t,Value_t>::Relation rel)188*c42dbd0eSchristos DefaultMap<Key_t, Value_t>::get (Key_t key,
189*c42dbd0eSchristos typename Map<Key_t, Value_t>::Relation rel)
190*c42dbd0eSchristos {
191*c42dbd0eSchristos if (rel != Map<Key_t, Value_t>::REL_EQ)
192*c42dbd0eSchristos return (Value_t) 0;
193*c42dbd0eSchristos return get (key);
194*c42dbd0eSchristos }
195*c42dbd0eSchristos
196*c42dbd0eSchristos template <typename Key_t, typename Value_t>
197*c42dbd0eSchristos Value_t
remove(Key_t)198*c42dbd0eSchristos DefaultMap<Key_t, Value_t>::remove (Key_t)
199*c42dbd0eSchristos {
200*c42dbd0eSchristos // Not implemented
201*c42dbd0eSchristos if (1)
202*c42dbd0eSchristos assert (0);
203*c42dbd0eSchristos return (Value_t) 0;
204*c42dbd0eSchristos }
205*c42dbd0eSchristos
206*c42dbd0eSchristos template <typename Key_t, typename Value_t>
207*c42dbd0eSchristos Vector<Value_t> *
values()208*c42dbd0eSchristos DefaultMap<Key_t, Value_t>::values ()
209*c42dbd0eSchristos {
210*c42dbd0eSchristos Vector<Value_t> *vals = new Vector<Value_t>(entries);
211*c42dbd0eSchristos for (int i = 0; i < entries; ++i)
212*c42dbd0eSchristos {
213*c42dbd0eSchristos Entry *entry = index->fetch (i);
214*c42dbd0eSchristos vals->append (entry->val);
215*c42dbd0eSchristos }
216*c42dbd0eSchristos return vals;
217*c42dbd0eSchristos }
218*c42dbd0eSchristos
219*c42dbd0eSchristos template <typename Key_t, typename Value_t>
220*c42dbd0eSchristos Vector<Key_t> *
keySet()221*c42dbd0eSchristos DefaultMap<Key_t, Value_t>::keySet ()
222*c42dbd0eSchristos {
223*c42dbd0eSchristos Vector<Key_t> *keys = new Vector<Key_t>(entries);
224*c42dbd0eSchristos for (int i = 0; i < entries; ++i)
225*c42dbd0eSchristos {
226*c42dbd0eSchristos Entry *entry = index->fetch (i);
227*c42dbd0eSchristos keys->append (entry->key);
228*c42dbd0eSchristos }
229*c42dbd0eSchristos return keys;
230*c42dbd0eSchristos }
231*c42dbd0eSchristos
232*c42dbd0eSchristos #endif
233