1#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//-----------------------------------------------------------------------------
375