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 18 void blackhole ( uint32_t x ); 19 uint32_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 27 extern uint32_t g_verify; 28 29 // Mix the given blob of data into the verification code 30 31 void MixVCode ( const void * blob, int len ); 32 33 34 //----------------------------------------------------------------------------- 35 36 typedef void (*pfHash) ( const void * blob, const int len, const uint32_t seed, void * out ); 37 38 struct 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 47 template< typename hashtype, typename keytype > 48 struct CollisionMap : public std::map< hashtype, std::vector<keytype> > 49 { 50 }; 51 52 template< typename hashtype > 53 struct HashSet : public std::set<hashtype> 54 { 55 }; 56 57 //----------------------------------------------------------------------------- 58 59 template < class T > 60 class hashfunc 61 { 62 public: 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 93 struct 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 117 template<typename hashtype> 118 struct 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 146 private: 147 148 HashCallback & operator = ( const HashCallback & ); 149 }; 150 151 //---------- 152 153 template<typename hashtype> 154 struct 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 184 private: 185 186 CollisionCallback & operator = ( const CollisionCallback & c ); 187 }; 188 189 //----------------------------------------------------------------------------- 190 191 template < int _bits > 192 class Blob 193 { 194 public: 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 366 private: 367 368 uint8_t bytes[(_bits+7)/8]; 369 }; 370 371 typedef Blob<128> uint128_t; 372 typedef Blob<256> uint256_t; 373 374 //----------------------------------------------------------------------------- 375