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