blob: 91e7206724a028a9922355d544f8dcdaef6fabb2 [file] [log] [blame]
tanjent@gmail.comf3b78972012-03-01 03:38:55 +00001#pragma once
2
3#include "Platform.h"
4#include "Bitvec.h"
5
6#include <memory.h>
7#include <vector>
8#include <map>
9#include <set>
10
11//-----------------------------------------------------------------------------
12// If the optimizer detects that a value in a speed test is constant or unused,
13// the optimizer may remove references to it or otherwise create code that
14// would not occur in a real-world application. To prevent the optimizer from
15// doing this we declare two trivial functions that either sink or source data,
16// and bar the compiler from optimizing them.
17
18void blackhole ( uint32_t x );
19uint32_t whitehole ( void );
20
21//-----------------------------------------------------------------------------
22// We want to verify that every test produces the same result on every platform
23// To do this, we hash the results of every test to produce an overall
24// verification value for the whole test suite. If two runs produce the same
25// verification value, then every test in both run produced the same results
26
27extern uint32_t g_verify;
28
29// Mix the given blob of data into the verification code
30
31void MixVCode ( const void * blob, int len );
32
33
34//-----------------------------------------------------------------------------
35
36typedef void (*pfHash) ( const void * blob, const int len, const uint32_t seed, void * out );
37
38struct ByteVec : public std::vector<uint8_t>
39{
40 ByteVec ( const void * key, int len )
41 {
42 resize(len);
43 memcpy(&front(),key,len);
44 }
45};
46
47template< typename hashtype, typename keytype >
48struct CollisionMap : public std::map< hashtype, std::vector<keytype> >
49{
50};
51
52template< typename hashtype >
53struct HashSet : public std::set<hashtype>
54{
55};
56
57//-----------------------------------------------------------------------------
58
59template < class T >
60class hashfunc
61{
62public:
63
64 hashfunc ( pfHash h ) : m_hash(h)
65 {
66 }
67
68 inline void operator () ( const void * key, const int len, const uint32_t seed, uint32_t * out )
69 {
70 m_hash(key,len,seed,out);
71 }
72
73 inline operator pfHash ( void ) const
74 {
75 return m_hash;
76 }
77
78 inline T operator () ( const void * key, const int len, const uint32_t seed )
79 {
80 T result;
81
82 m_hash(key,len,seed,(uint32_t*)&result);
83
84 return result;
85 }
86
87 pfHash m_hash;
88};
89
90//-----------------------------------------------------------------------------
91// Key-processing callback objects. Simplifies keyset testing a bit.
92
93struct KeyCallback
94{
95 KeyCallback() : m_count(0)
96 {
97 }
98
99 virtual ~KeyCallback()
100 {
101 }
102
103 virtual void operator() ( const void * key, int len )
104 {
105 m_count++;
106 }
107
108 virtual void reserve ( int keycount )
109 {
110 };
111
112 int m_count;
113};
114
115//----------
116
117template<typename hashtype>
118struct HashCallback : public KeyCallback
119{
120 typedef std::vector<hashtype> hashvec;
121
122 HashCallback ( pfHash hash, hashvec & hashes ) : m_hashes(hashes), m_pfHash(hash)
123 {
124 m_hashes.clear();
125 }
126
127 virtual void operator () ( const void * key, int len )
128 {
129 size_t newsize = m_hashes.size() + 1;
130
131 m_hashes.resize(newsize);
132
133 m_pfHash(key,len,0,&m_hashes.back());
134 }
135
136 virtual void reserve ( int keycount )
137 {
138 m_hashes.reserve(keycount);
139 }
140
141 hashvec & m_hashes;
142 pfHash m_pfHash;
143
144 //----------
145
146private:
147
148 HashCallback & operator = ( const HashCallback & );
149};
150
151//----------
152
153template<typename hashtype>
154struct CollisionCallback : public KeyCallback
155{
156 typedef HashSet<hashtype> hashset;
157 typedef CollisionMap<hashtype,ByteVec> collmap;
158
159 CollisionCallback ( pfHash hash, hashset & collisions, collmap & cmap )
160 : m_pfHash(hash),
161 m_collisions(collisions),
162 m_collmap(cmap)
163 {
164 }
165
166 virtual void operator () ( const void * key, int len )
167 {
168 hashtype h;
169
170 m_pfHash(key,len,0,&h);
171
172 if(m_collisions.count(h))
173 {
174 m_collmap[h].push_back( ByteVec(key,len) );
175 }
176 }
177
178 //----------
179
180 pfHash m_pfHash;
181 hashset & m_collisions;
182 collmap & m_collmap;
183
184private:
185
186 CollisionCallback & operator = ( const CollisionCallback & c );
187};
188
189//-----------------------------------------------------------------------------
190
191template < int _bits >
192class Blob
193{
194public:
195
196 Blob()
197 {
198 for(size_t i = 0; i < sizeof(bytes); i++)
199 {
200 bytes[i] = 0;
201 }
202 }
203
204 Blob ( int x )
205 {
206 for(size_t i = 0; i < sizeof(bytes); i++)
207 {
208 bytes[i] = 0;
209 }
210
211 *(int*)bytes = x;
212 }
213
214 Blob ( const Blob & k )
215 {
216 for(size_t i = 0; i < sizeof(bytes); i++)
217 {
218 bytes[i] = k.bytes[i];
219 }
220 }
221
222 Blob & operator = ( const Blob & k )
223 {
224 for(size_t i = 0; i < sizeof(bytes); i++)
225 {
226 bytes[i] = k.bytes[i];
227 }
228
229 return *this;
230 }
231
232 Blob ( uint64_t a, uint64_t b )
233 {
234 uint64_t t[2] = {a,b};
235 set(&t,16);
236 }
237
238 void set ( const void * blob, size_t len )
239 {
240 const uint8_t * k = (const uint8_t*)blob;
241
242 len = len > sizeof(bytes) ? sizeof(bytes) : len;
243
244 for(size_t i = 0; i < len; i++)
245 {
246 bytes[i] = k[i];
247 }
248
249 for(size_t i = len; i < sizeof(bytes); i++)
250 {
251 bytes[i] = 0;
252 }
253 }
254
255 uint8_t & operator [] ( int i )
256 {
257 return bytes[i];
258 }
259
260 const uint8_t & operator [] ( int i ) const
261 {
262 return bytes[i];
263 }
264
265 //----------
266 // boolean operations
267
268 bool operator < ( const Blob & k ) const
269 {
270 for(size_t i = 0; i < sizeof(bytes); i++)
271 {
272 if(bytes[i] < k.bytes[i]) return true;
273 if(bytes[i] > k.bytes[i]) return false;
274 }
275
276 return false;
277 }
278
279 bool operator == ( const Blob & k ) const
280 {
281 for(size_t i = 0; i < sizeof(bytes); i++)
282 {
283 if(bytes[i] != k.bytes[i]) return false;
284 }
285
286 return true;
287 }
288
289 bool operator != ( const Blob & k ) const
290 {
291 return !(*this == k);
292 }
293
294 //----------
295 // bitwise operations
296
297 Blob operator ^ ( const Blob & k ) const
298 {
299 Blob t;
300
301 for(size_t i = 0; i < sizeof(bytes); i++)
302 {
303 t.bytes[i] = bytes[i] ^ k.bytes[i];
304 }
305
306 return t;
307 }
308
309 Blob & operator ^= ( const Blob & k )
310 {
311 for(size_t i = 0; i < sizeof(bytes); i++)
312 {
313 bytes[i] ^= k.bytes[i];
314 }
315
316 return *this;
317 }
318
319 int operator & ( int x )
320 {
321 return (*(int*)bytes) & x;
322 }
323
324 Blob & operator &= ( const Blob & k )
325 {
326 for(size_t i = 0; i < sizeof(bytes); i++)
327 {
328 bytes[i] &= k.bytes[i];
329 }
330 }
331
332 Blob operator << ( int c )
333 {
334 Blob t = *this;
335
336 lshift(&t.bytes[0],sizeof(bytes),c);
337
338 return t;
339 }
340
341 Blob operator >> ( int c )
342 {
343 Blob t = *this;
344
345 rshift(&t.bytes[0],sizeof(bytes),c);
346
347 return t;
348 }
349
350 Blob & operator <<= ( int c )
351 {
352 lshift(&bytes[0],sizeof(bytes),c);
353
354 return *this;
355 }
356
357 Blob & operator >>= ( int c )
358 {
359 rshift(&bytes[0],sizeof(bytes),c);
360
361 return *this;
362 }
363
364 //----------
365
366private:
367
368 uint8_t bytes[(_bits+7)/8];
369};
370
371typedef Blob<128> uint128_t;
372typedef Blob<256> uint256_t;
373
374//-----------------------------------------------------------------------------