Embedded Template Library 1.0
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 "type_traits.h"
41#include "static_assert.h"
42
43#include <stdint.h>
44#include <stdlib.h>
45
48
49namespace etl
50{
51 namespace private_hash
52 {
53 //*************************************************************************
56 //*************************************************************************
57 template <typename T>
58 typename enable_if<sizeof(T) == sizeof(uint16_t), size_t>::type
59 generic_hash(const uint8_t* begin, const uint8_t* end)
60 {
61 uint32_t h = fnv_1a_32(begin, end);
62
63 return static_cast<size_t>(h ^ (h >> 16U));
64 }
65
66 //*************************************************************************
69 //*************************************************************************
70 template <typename T>
71 typename enable_if<sizeof(T) == sizeof(uint32_t), size_t>::type
72 generic_hash(const uint8_t* begin, const uint8_t* end)
73 {
74 return fnv_1a_32(begin, end);
75 }
76
77#if ETL_USING_64BIT_TYPES
78 //*************************************************************************
81 //*************************************************************************
82 template <typename T>
83 typename enable_if<sizeof(T) == sizeof(uint64_t), size_t>::type
84 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 IsEnum=false>
94 struct hash_base
95 {
96 private:
97 hash_base(); // Can't default construct
98 hash_base(const hash_base& other); // Can't copy construct
99 hash_base& operator=(const hash_base& other); // Can't copy assign
100
101#if ETL_USING_CPP11
102 hash_base(hash_base&& other); // Can't move construct
103 hash_base& operator=(hash_base&& other); // Can't move assign
104#endif
105 };
106
107 // Specialization for enums depends on definitions for integers, so it comes later
108 }
109
110#if ETL_USING_CPP11
111 //***************************************************************************
114 //***************************************************************************
115 template <typename T>
116 struct hash : private_hash::hash_base<T, etl::is_enum<T>::value>{};
117#else
118 //***************************************************************************
121 //***************************************************************************
122 template <typename T> struct hash;
123#endif
124
125 //***************************************************************************
128 //***************************************************************************
129 template <>
130 struct hash <bool>
131 {
132 ETL_STATIC_ASSERT(sizeof(size_t) >= sizeof(bool), "size_t smaller than type");
133
134 size_t operator ()(bool v) const
135 {
136 return static_cast<size_t>(v);
137 }
138 };
139
140 //***************************************************************************
143 //***************************************************************************
144 template <>
145 struct hash<char>
146 {
147 ETL_STATIC_ASSERT(sizeof(size_t) >= sizeof(char), "size_t smaller than type");
148
149 size_t operator ()(char v) const
150 {
151 return static_cast<size_t>(v);
152 }
153 };
154
155 //***************************************************************************
158 //***************************************************************************
159 template<> struct
160 hash<signed char>
161 {
162 ETL_STATIC_ASSERT(sizeof(size_t) >= sizeof(signed char), "size_t smaller than type");
163
164 size_t operator ()(signed char v) const
165 {
166 return static_cast<size_t>(v);
167 }
168 };
169
170 //***************************************************************************
173 //***************************************************************************
174 template<>
175 struct hash<unsigned char>
176 {
177 ETL_STATIC_ASSERT(sizeof(size_t) >= sizeof(unsigned char), "size_t smaller than type");
178
179 size_t operator ()(unsigned char v) const
180 {
181 return static_cast<size_t>(v);
182 }
183 };
184
185 //***************************************************************************
188 //***************************************************************************
189 template<>
190 struct hash<wchar_t>
191 {
192 ETL_STATIC_ASSERT(sizeof(size_t) >= sizeof(wchar_t), "size_t smaller than type");
193
194 size_t operator ()(wchar_t v) const
195 {
196 return static_cast<size_t>(v);
197 }
198 };
199
200 //***************************************************************************
203 //***************************************************************************
204 template<>
205 struct hash<short>
206 {
207 ETL_STATIC_ASSERT(sizeof(size_t) >= sizeof(short), "size_t smaller than type");
208
209 size_t operator ()(short v) const
210 {
211 return static_cast<size_t>(v);
212 }
213 };
214
215 //***************************************************************************
218 //***************************************************************************
219 template<>
220 struct hash<unsigned short>
221 {
222 ETL_STATIC_ASSERT(sizeof(size_t) >= sizeof(unsigned short), "size_t smaller than type");
223
224 size_t operator ()(unsigned short v) const
225 {
226 return static_cast<size_t>(v);
227 }
228 };
229
230 //***************************************************************************
233 //***************************************************************************
234 template<>
235 struct hash<int>
236 {
237 ETL_STATIC_ASSERT(sizeof(size_t) >= sizeof(int), "size_t smaller than type");
238
239 size_t operator ()(int v) const
240 {
241 return static_cast<size_t>(v);
242 }
243 };
244
245 //***************************************************************************
248 //***************************************************************************
249 template<>
250 struct hash<unsigned int>
251 {
252 ETL_STATIC_ASSERT(sizeof(size_t) >= sizeof(unsigned int), "size_t smaller than type");
253
254 size_t operator ()(unsigned int v) const
255 {
256 return static_cast<size_t>(v);
257 }
258 };
259
260 //***************************************************************************
263 //***************************************************************************
264 template<>
265 struct hash<long>
266 {
267 size_t operator ()(long v) const
268 {
269 // If it's the same size as a size_t.
270 if ETL_IF_CONSTEXPR(sizeof(size_t) >= sizeof(v))
271 {
272 return static_cast<size_t>(v);
273 }
274 else
275 {
276 uint8_t* p = reinterpret_cast<uint8_t*>(&v);
277 return private_hash::generic_hash<size_t>(p, p + sizeof(v));
278 }
279 }
280 };
281
282 //***************************************************************************
285 //***************************************************************************
286 template<>
287 struct hash<long long>
288 {
289 size_t operator ()(long long v) const
290 {
291 // If it's the same size as a size_t.
292 if ETL_IF_CONSTEXPR(sizeof(size_t) >= sizeof(v))
293 {
294 return static_cast<size_t>(v);
295 }
296 else
297 {
298 uint8_t* p = reinterpret_cast<uint8_t*>(&v);
299 return private_hash::generic_hash<size_t>(p, p + sizeof(v));
300 }
301 }
302 };
303
304 //***************************************************************************
307 //***************************************************************************
308 template<>
309 struct hash<unsigned long>
310 {
311 size_t operator ()(unsigned long v) const
312 {
313 // If it's the same size as a size_t.
314 if ETL_IF_CONSTEXPR(sizeof(size_t) >= sizeof(v))
315 {
316 return static_cast<size_t>(v);
317 }
318 else
319 {
320 uint8_t* p = reinterpret_cast<uint8_t*>(&v);
321 return private_hash::generic_hash<size_t>(p, p + sizeof(v));
322 }
323 }
324 };
325
326 //***************************************************************************
329 //***************************************************************************
330 template<>
331 struct hash<unsigned long long>
332 {
333 size_t operator ()(unsigned long long v) const
334 {
335 // If it's the same size as a size_t.
336 if ETL_IF_CONSTEXPR(sizeof(size_t) >= sizeof(v))
337 {
338 return static_cast<size_t>(v);
339 }
340 else
341 {
342 uint8_t* p = reinterpret_cast<uint8_t*>(&v);
343 return private_hash::generic_hash<size_t>(p, p + sizeof(v));
344 }
345 }
346 };
347
348 //***************************************************************************
351 //***************************************************************************
352 template<>
353 struct hash<float>
354 {
355 size_t operator ()(float v) const
356 {
357 // If it's the same size as a size_t.
358 if ETL_IF_CONSTEXPR(sizeof(size_t) == sizeof(v))
359 {
360 union
361 {
362 size_t s;
363 float v;
364 } u;
365
366 if (v == -0.0f)
367 { // -0.0 and 0.0 are represented differently at bit level
368 v = 0.0f;
369 }
370 u.v = v;
371
372 return u.s;
373 }
374 else
375 {
376 uint8_t* p = reinterpret_cast<uint8_t*>(&v);
377 return private_hash::generic_hash<size_t>(p, p + sizeof(v));
378 }
379 }
380 };
381
382 //***************************************************************************
385 //***************************************************************************
386 template<>
387 struct hash<double>
388 {
389 size_t operator ()(double v) const
390 {
391 // If it's the same size as a size_t.
392 if ETL_IF_CONSTEXPR(sizeof(size_t) == sizeof(v))
393 {
394 union
395 {
396 size_t s;
397 double v;
398 } u;
399
400 if (v == -0.0)
401 { // -0.0 and 0.0 are represented differently at bit level
402 v = 0.0;
403 }
404 u.v = v;
405
406 return u.s;
407 }
408 else
409 {
410 uint8_t* p = reinterpret_cast<uint8_t*>(&v);
411 return private_hash::generic_hash<size_t>(p, p + sizeof(v));
412 }
413 }
414 };
415
416 //***************************************************************************
419 //***************************************************************************
420 template<>
421 struct hash<long double>
422 {
423 size_t operator ()(long double v) const
424 {
425 // If it's the same size as a size_t.
426 if ETL_IF_CONSTEXPR(sizeof(size_t) == sizeof(v))
427 {
428 union
429 {
430 size_t s;
431 long double v;
432 } u;
433
434 if (v == -0.0L)
435 { // -0.0 and 0.0 are represented differently at bit level
436 v = 0.0L;
437 }
438 u.v = v;
439
440 return u.s;
441 }
442 else
443 {
444 uint8_t* p = reinterpret_cast<uint8_t*>(&v);
445 return private_hash::generic_hash<size_t>(p, p + sizeof(v));
446 }
447 }
448 };
449
450 //***************************************************************************
453 //***************************************************************************
454 template <typename T>
455 struct hash<T*>
456 {
457 size_t operator ()(const T* v) const
458 {
459 // If it's the same size as a size_t.
460 if (sizeof(size_t) == sizeof(T*))
461 {
462 union
463 {
464 size_t s;
465 const T* v;
466 } u;
467
468 u.v = v;
469
470 return u.s;
471 }
472 else
473 {
474 uint8_t* p = reinterpret_cast<uint8_t*>(&v);
475 return private_hash::generic_hash<size_t>(p, p + sizeof(v));
476 }
477 }
478 };
479
480 namespace private_hash
481 {
482 //*************************************************************************
484 //*************************************************************************
485 template<typename T>
486 struct hash_base<T, true>
487 {
488 size_t operator()(T v) const
489 {
490 if (sizeof(size_t) >= sizeof(T))
491 {
492 return static_cast<size_t>(v);
493 }
494 else
495 {
496 return ::etl::hash<unsigned long long>()(static_cast<unsigned long long>(v));
497 }
498 }
499 };
500 }
501}
502
503#endif // ETL_USING_8BIT_TYPES
504
505#endif
bitset_ext
Definition: absolute.h:38
ETL_CONSTEXPR TContainer::iterator begin(TContainer &container)
Definition: iterator.h:931
ETL_CONSTEXPR TContainer::iterator end(TContainer &container)
Definition: iterator.h:961