Embedded Template Library 1.0
Loading...
Searching...
No Matches
hash.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2014 John Wellbelove
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_HASH_INCLUDED
32#define ETL_HASH_INCLUDED
33
34#include "platform.h"
35
36#if ETL_USING_8BIT_TYPES
37
38 // The default hash calculation.
39 #include "fnv_1.h"
40 #include "math.h"
41 #include "static_assert.h"
42 #include "type_traits.h"
43
44 #include <stdint.h>
45 #include <stdlib.h>
46
49
51
52namespace etl
53{
54 namespace private_hash
55 {
56 //*************************************************************************
59 //*************************************************************************
60 template <typename T>
61 typename enable_if<sizeof(T) == sizeof(uint16_t), size_t>::type generic_hash(const uint8_t* begin, const uint8_t* end)
62 {
63 uint32_t h = fnv_1a_32(begin, end);
64
65 return static_cast<size_t>(h ^ (h >> 16U));
66 }
67
68 //*************************************************************************
71 //*************************************************************************
72 template <typename T>
73 typename enable_if<sizeof(T) == sizeof(uint32_t), size_t>::type generic_hash(const uint8_t* begin, const uint8_t* end)
74 {
75 return fnv_1a_32(begin, end);
76 }
77
78 #if ETL_USING_64BIT_TYPES
79 //*************************************************************************
82 //*************************************************************************
83 template <typename T>
84 typename enable_if<sizeof(T) == sizeof(uint64_t), size_t>::type generic_hash(const uint8_t* begin, const uint8_t* end)
85 {
86 return fnv_1a_64(begin, end);
87 }
88 #endif
89
90 //*************************************************************************
92 //*************************************************************************
93 template <typename T, bool Is_Enum = false>
94 struct hash_base
95 {
96 private:
97
98 hash_base(); // Can't default construct
99 hash_base(const hash_base& other); // Can't copy construct
100 hash_base& operator=(const hash_base& other); // Can't copy assign
101
102 #if ETL_USING_CPP11
103 hash_base(hash_base&& other); // Can't move construct
104 hash_base& operator=(hash_base&& other); // Can't move assign
105 #endif
106 };
107
108 // Specialization for enums depends on definitions for integers, so it comes
109 // later
110 } // namespace private_hash
111
112 #if ETL_USING_CPP11
113 //***************************************************************************
116 //***************************************************************************
117 template <typename T>
118 struct hash : private_hash::hash_base<T, etl::is_enum<T>::value>
119 {
120 };
121 #else
122 //***************************************************************************
125 //***************************************************************************
126 template <typename T>
127 struct hash;
128 #endif
129
130 //***************************************************************************
133 //***************************************************************************
134 template <>
135 struct hash<bool>
136 {
137 ETL_STATIC_ASSERT(sizeof(size_t) >= sizeof(bool), "size_t smaller than type");
138
139 size_t operator()(bool v) const
140 {
141 return static_cast<size_t>(v);
142 }
143 };
144
145 //***************************************************************************
148 //***************************************************************************
149 template <>
150 struct hash<char>
151 {
152 ETL_STATIC_ASSERT(sizeof(size_t) >= sizeof(char), "size_t smaller than type");
153
154 size_t operator()(char v) const
155 {
156 return static_cast<size_t>(v);
157 }
158 };
159
160 //***************************************************************************
163 //***************************************************************************
164 template <>
165 struct hash<signed char>
166 {
167 ETL_STATIC_ASSERT(sizeof(size_t) >= sizeof(signed char), "size_t smaller than type");
168
169 size_t operator()(signed char v) const
170 {
171 return static_cast<size_t>(v);
172 }
173 };
174
175 //***************************************************************************
178 //***************************************************************************
179 template <>
180 struct hash<unsigned char>
181 {
182 ETL_STATIC_ASSERT(sizeof(size_t) >= sizeof(unsigned char), "size_t smaller than type");
183
184 size_t operator()(unsigned char v) const
185 {
186 return static_cast<size_t>(v);
187 }
188 };
189
190 //***************************************************************************
193 //***************************************************************************
194 template <>
195 struct hash<wchar_t>
196 {
197 size_t operator()(wchar_t v) const
198 {
199 // If it's the same size as a size_t.
200 if ETL_IF_CONSTEXPR (sizeof(size_t) >= sizeof(v))
201 {
202 return static_cast<size_t>(v);
203 }
204 else
205 {
206 uint8_t* p = reinterpret_cast<uint8_t*>(&v);
207 return private_hash::generic_hash<size_t>(p, p + sizeof(v));
208 }
209 }
210 };
211
212 //***************************************************************************
215 //***************************************************************************
216 template <>
217 struct hash<short>
218 {
219 size_t operator()(short v) const
220 {
221 // If it's the same size as a size_t.
222 if ETL_IF_CONSTEXPR (sizeof(size_t) >= sizeof(v))
223 {
224 return static_cast<size_t>(v);
225 }
226 else
227 {
228 uint8_t* p = reinterpret_cast<uint8_t*>(&v);
229 return private_hash::generic_hash<size_t>(p, p + sizeof(v));
230 }
231 }
232 };
233
234 //***************************************************************************
237 //***************************************************************************
238 template <>
239 struct hash<unsigned short>
240 {
241 size_t operator()(unsigned short v) const
242 {
243 // If it's the same size as a size_t.
244 if ETL_IF_CONSTEXPR (sizeof(size_t) >= sizeof(v))
245 {
246 return static_cast<size_t>(v);
247 }
248 else
249 {
250 uint8_t* p = reinterpret_cast<uint8_t*>(&v);
251 return private_hash::generic_hash<size_t>(p, p + sizeof(v));
252 }
253 }
254 };
255
256 //***************************************************************************
259 //***************************************************************************
260 template <>
261 struct hash<int>
262 {
263 size_t operator()(int v) const
264 {
265 // If it's the same size as a size_t.
266 if ETL_IF_CONSTEXPR (sizeof(size_t) >= sizeof(v))
267 {
268 return static_cast<size_t>(v);
269 }
270 else
271 {
272 uint8_t* p = reinterpret_cast<uint8_t*>(&v);
273 return private_hash::generic_hash<size_t>(p, p + sizeof(v));
274 }
275 }
276 };
277
278 //***************************************************************************
281 //***************************************************************************
282 template <>
283 struct hash<unsigned int>
284 {
285 size_t operator()(unsigned int v) const
286 {
287 // If it's the same size as a size_t.
288 if ETL_IF_CONSTEXPR (sizeof(size_t) >= sizeof(v))
289 {
290 return static_cast<size_t>(v);
291 }
292 else
293 {
294 uint8_t* p = reinterpret_cast<uint8_t*>(&v);
295 return private_hash::generic_hash<size_t>(p, p + sizeof(v));
296 }
297 }
298 };
299
300 //***************************************************************************
303 //***************************************************************************
304 template <>
305 struct hash<long>
306 {
307 size_t operator()(long v) const
308 {
309 // If it's the same size as a size_t.
310 if ETL_IF_CONSTEXPR (sizeof(size_t) >= sizeof(v))
311 {
312 return static_cast<size_t>(v);
313 }
314 else
315 {
316 uint8_t* p = reinterpret_cast<uint8_t*>(&v);
317 return private_hash::generic_hash<size_t>(p, p + sizeof(v));
318 }
319 }
320 };
321
322 //***************************************************************************
325 //***************************************************************************
326 template <>
327 struct hash<long long>
328 {
329 size_t operator()(long long v) const
330 {
331 // If it's the same size as a size_t.
332 if ETL_IF_CONSTEXPR (sizeof(size_t) >= sizeof(v))
333 {
334 return static_cast<size_t>(v);
335 }
336 else
337 {
338 uint8_t* p = reinterpret_cast<uint8_t*>(&v);
339 return private_hash::generic_hash<size_t>(p, p + sizeof(v));
340 }
341 }
342 };
343
344 //***************************************************************************
347 //***************************************************************************
348 template <>
349 struct hash<unsigned long>
350 {
351 size_t operator()(unsigned long v) const
352 {
353 // If it's the same size as a size_t.
354 if ETL_IF_CONSTEXPR (sizeof(size_t) >= sizeof(v))
355 {
356 return static_cast<size_t>(v);
357 }
358 else
359 {
360 uint8_t* p = reinterpret_cast<uint8_t*>(&v);
361 return private_hash::generic_hash<size_t>(p, p + sizeof(v));
362 }
363 }
364 };
365
366 //***************************************************************************
369 //***************************************************************************
370 template <>
371 struct hash<unsigned long long>
372 {
373 size_t operator()(unsigned long long v) const
374 {
375 // If it's the same size as a size_t.
376 if ETL_IF_CONSTEXPR (sizeof(size_t) >= sizeof(v))
377 {
378 return static_cast<size_t>(v);
379 }
380 else
381 {
382 uint8_t* p = reinterpret_cast<uint8_t*>(&v);
383 return private_hash::generic_hash<size_t>(p, p + sizeof(v));
384 }
385 }
386 };
387
388 //***************************************************************************
391 //***************************************************************************
392 template <>
393 struct hash<float>
394 {
395 size_t operator()(float v) const
396 {
397 // If it's the same size as a size_t.
398 if ETL_IF_CONSTEXPR (sizeof(size_t) == sizeof(v))
399 {
400 union
401 {
402 size_t s;
403 float v;
404 } u;
405
406 if (etl::is_zero(v))
407 { // -0.0 and 0.0 are represented differently at bit level
408 v = 0.0f;
409 }
410 u.v = v;
411
412 return u.s;
413 }
414 else
415 {
416 uint8_t* p = reinterpret_cast<uint8_t*>(&v);
417 return private_hash::generic_hash<size_t>(p, p + sizeof(v));
418 }
419 }
420 };
421
422 //***************************************************************************
425 //***************************************************************************
426 template <>
427 struct hash<double>
428 {
429 size_t operator()(double v) const
430 {
431 // If it's the same size as a size_t.
432 if ETL_IF_CONSTEXPR (sizeof(size_t) == sizeof(v))
433 {
434 union
435 {
436 size_t s;
437 double v;
438 } u;
439
440 if (etl::is_zero(v))
441 { // -0.0 and 0.0 are represented differently at bit level
442 v = 0.0;
443 }
444 u.v = v;
445
446 return u.s;
447 }
448 else
449 {
450 uint8_t* p = reinterpret_cast<uint8_t*>(&v);
451 return private_hash::generic_hash<size_t>(p, p + sizeof(v));
452 }
453 }
454 };
455
456 //***************************************************************************
459 //***************************************************************************
460 template <>
461 struct hash<long double>
462 {
463 size_t operator()(long double v) const
464 {
465 // If it's the same size as a size_t.
466 if ETL_IF_CONSTEXPR (sizeof(size_t) == sizeof(v))
467 {
468 union
469 {
470 size_t s;
471 long double v;
472 } u;
473
474 if (etl::is_zero(v))
475 { // -0.0 and 0.0 are represented differently at bit level
476 v = 0.0L;
477 }
478 u.v = v;
479
480 return u.s;
481 }
482 else
483 {
484 uint8_t* p = reinterpret_cast<uint8_t*>(&v);
485 return private_hash::generic_hash<size_t>(p, p + sizeof(v));
486 }
487 }
488 };
489
490 //***************************************************************************
493 //***************************************************************************
494 template <typename T>
495 struct hash<T*>
496 {
497 size_t operator()(const T* v) const
498 {
499 // If it's the same size as a size_t.
500 if (sizeof(size_t) == sizeof(T*))
501 {
502 union
503 {
504 size_t s;
505 const T* v;
506 } u;
507
508 u.v = v;
509
510 return u.s;
511 }
512 else
513 {
514 uint8_t* p = reinterpret_cast<uint8_t*>(&v);
515 return private_hash::generic_hash<size_t>(p, p + sizeof(v));
516 }
517 }
518 };
519
520 namespace private_hash
521 {
522 //*************************************************************************
524 //*************************************************************************
525 template <typename T>
526 struct hash_base<T, true>
527 {
528 size_t operator()(T v) const
529 {
530 if (sizeof(size_t) >= sizeof(T))
531 {
532 return static_cast<size_t>(v);
533 }
534 else
535 {
536 return ::etl::hash<unsigned long long>()(static_cast<unsigned long long>(v));
537 }
538 }
539 };
540 } // namespace private_hash
541} // namespace etl
542
543 #include "private/diagnostic_pop.h"
544
545#endif // ETL_USING_8BIT_TYPES
546
547#endif
bitset_ext
Definition absolute.h:40