xref: /netbsd-src/external/gpl3/binutils.old/dist/gprofng/src/DefaultMap.h (revision c42dbd0ed2e61fe6eda8590caa852ccf34719964)
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