Stefan Scholz / ETL
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers hash.h Source File

hash.h

Go to the documentation of this file.
00001 ///\file
00002 
00003 /******************************************************************************
00004 The MIT License(MIT)
00005 
00006 Embedded Template Library.
00007 https://github.com/ETLCPP/etl
00008 http://www.etlcpp.com
00009 
00010 Copyright(c) 2014 jwellbelove
00011 
00012 Permission is hereby granted, free of charge, to any person obtaining a copy
00013 of this software and associated documentation files(the "Software"), to deal
00014 in the Software without restriction, including without limitation the rights
00015 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
00016 copies of the Software, and to permit persons to whom the Software is
00017 furnished to do so, subject to the following conditions :
00018 
00019 The above copyright notice and this permission notice shall be included in all
00020 copies or substantial portions of the Software.
00021 
00022 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00023 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00024 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
00025 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00026 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00027 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00028 SOFTWARE.
00029 ******************************************************************************/
00030 
00031 #ifndef __ETL_HASH__
00032 #define __ETL_HASH__
00033 
00034 #include <stdint.h>
00035 #include <stdlib.h>
00036 
00037 #include "platform.h "
00038 
00039 // The default hash calculation.
00040 #include "fnv_1.h "
00041 #include "type_traits.h "
00042 #include "static_assert.h"
00043 
00044 ///\defgroup hash Standard hash calculations
00045 ///\ingroup maths
00046 
00047 namespace etl
00048 {
00049   namespace __private_hash__
00050   {
00051     //*************************************************************************
00052     /// Hash to use when size_t is 16 bits.
00053     /// T is always expected to be size_t.
00054     //*************************************************************************
00055     template <typename T>
00056     typename enable_if<sizeof(T) == sizeof(uint16_t), size_t>::type
00057     generic_hash(const uint8_t* begin, const uint8_t* end)
00058     {
00059       uint32_t h = fnv_1a_32(begin, end);
00060 
00061       return static_cast<size_t>(h ^ (h >> 16));
00062     }
00063 
00064     //*************************************************************************
00065     /// Hash to use when size_t is 32 bits.
00066     /// T is always expected to be size_t.
00067     //*************************************************************************
00068     template <typename T>
00069     typename enable_if<sizeof(T) == sizeof(uint32_t), size_t>::type
00070     generic_hash(const uint8_t* begin, const uint8_t* end)
00071     {
00072       return fnv_1a_32(begin, end);
00073     }
00074 
00075     //*************************************************************************
00076     /// Hash to use when size_t is 64 bits.
00077     /// T is always expected to be size_t.
00078     //*************************************************************************
00079     template <typename T>
00080     typename enable_if<sizeof(T) == sizeof(uint64_t), size_t>::type
00081     generic_hash(const uint8_t* begin, const uint8_t* end)
00082     {
00083       return fnv_1a_64(begin, end);
00084     }
00085   }
00086 
00087   //***************************************************************************
00088   /// Generic declaration for etl::hash
00089   ///\ingroup hash
00090   //***************************************************************************
00091   template <typename T> struct hash;
00092 
00093   //***************************************************************************
00094   /// Specialisation for bool.
00095   ///\ingroup hash
00096   //***************************************************************************
00097   template <>
00098   struct hash <bool>
00099   {
00100     STATIC_ASSERT(sizeof(size_t) >= sizeof(bool), "size_t smaller than type");
00101 
00102     size_t operator ()(bool v) const
00103     {
00104       return static_cast<size_t>(v);
00105     }
00106   };
00107 
00108   //***************************************************************************
00109   /// Specialisation for char.
00110   ///\ingroup hash
00111   //***************************************************************************
00112   template <>
00113   struct hash<char>
00114   {
00115     STATIC_ASSERT(sizeof(size_t) >= sizeof(char), "size_t smaller than type");
00116 
00117     size_t operator ()(char v) const
00118     {
00119       return static_cast<size_t>(v);
00120     }
00121   };
00122 
00123   //***************************************************************************
00124   /// Specialisation for signed char.
00125   ///\ingroup hash
00126   //***************************************************************************
00127   template<> struct
00128   hash<signed char>
00129   {
00130     STATIC_ASSERT(sizeof(size_t) >= sizeof(signed char), "size_t smaller than type");
00131 
00132     size_t operator ()(signed char v) const
00133     {
00134       return static_cast<size_t>(v);
00135     }
00136   };
00137 
00138   //***************************************************************************
00139   /// Specialisation for unsigned char.
00140   ///\ingroup hash
00141   //***************************************************************************
00142   template<>
00143   struct hash<unsigned char>
00144   {
00145     STATIC_ASSERT(sizeof(size_t) >= sizeof(unsigned char), "size_t smaller than type");
00146 
00147     size_t operator ()(unsigned char v) const
00148     {
00149       return static_cast<size_t>(v);
00150     }
00151   };
00152 
00153   //***************************************************************************
00154   /// Specialisation for wchar_t.
00155   ///\ingroup hash
00156   //***************************************************************************
00157   template<>
00158   struct hash<wchar_t>
00159   {
00160     STATIC_ASSERT(sizeof(size_t) >= sizeof(wchar_t), "size_t smaller than type");
00161 
00162     size_t operator ()(wchar_t v) const
00163     {
00164       return static_cast<size_t>(v);
00165     }
00166   };
00167 
00168   //***************************************************************************
00169   /// Specialisation for short.
00170   ///\ingroup hash
00171   //***************************************************************************
00172   template<>
00173   struct hash<short>
00174   {
00175     STATIC_ASSERT(sizeof(size_t) >= sizeof(short), "size_t smaller than type");
00176 
00177     size_t operator ()(short v) const
00178     {
00179       return static_cast<size_t>(v);
00180     }
00181   };
00182 
00183   //***************************************************************************
00184   /// Specialisation for unsigned short.
00185   ///\ingroup hash
00186   //***************************************************************************
00187   template<>
00188   struct hash<unsigned short>
00189   {
00190     STATIC_ASSERT(sizeof(size_t) >= sizeof(unsigned short), "size_t smaller than type");
00191 
00192     size_t operator ()(unsigned short v) const
00193     {
00194       return static_cast<size_t>(v);
00195     }
00196   };
00197 
00198   //***************************************************************************
00199   /// Specialisation for int.
00200   ///\ingroup hash
00201   //***************************************************************************
00202   template<>
00203   struct hash<int>
00204   {
00205     STATIC_ASSERT(sizeof(size_t) >= sizeof(int), "size_t smaller than type");
00206 
00207     size_t operator ()(int v) const
00208     {
00209       return static_cast<size_t>(v);
00210     }
00211   };
00212 
00213   //***************************************************************************
00214   /// Specialisation for unsigned int.
00215   ///\ingroup hash
00216   //***************************************************************************
00217   template<>
00218   struct hash<unsigned int>
00219   {
00220     STATIC_ASSERT(sizeof(size_t) >= sizeof(unsigned int), "size_t smaller than type");
00221 
00222     size_t operator ()(unsigned int v) const
00223     {
00224       return static_cast<size_t>(v);
00225     }
00226   };
00227 
00228   //***************************************************************************
00229   /// Specialisation for long.
00230   ///\ingroup hash
00231   //***************************************************************************
00232   template<>
00233   struct hash<long>
00234   {
00235     size_t operator ()(long v) const
00236     {
00237       // If it's the same size as a size_t.
00238       if (sizeof(size_t) >= sizeof(v))
00239       {
00240         return static_cast<size_t>(v);
00241       }
00242       else
00243       {
00244         uint8_t* p = reinterpret_cast<uint8_t*>(&v);
00245         return __private_hash__::generic_hash<size_t>(p, p + sizeof(v));
00246       }
00247     }
00248   };
00249 
00250   //***************************************************************************
00251   /// Specialisation for long long.
00252   ///\ingroup hash
00253   //***************************************************************************
00254   template<>
00255   struct hash<long long>
00256   {
00257     size_t operator ()(long long v) const
00258     {
00259       // If it's the same size as a size_t.
00260       if (sizeof(size_t) >= sizeof(v))
00261       {
00262         return static_cast<size_t>(v);
00263       }
00264       else
00265       {
00266         uint8_t* p = reinterpret_cast<uint8_t*>(&v);
00267         return __private_hash__::generic_hash<size_t>(p, p + sizeof(v));
00268       }
00269     }
00270   };
00271 
00272   //***************************************************************************
00273   /// Specialisation for unsigned long.
00274   ///\ingroup hash
00275   //***************************************************************************
00276   template<>
00277   struct hash<unsigned long>
00278   {
00279     size_t  operator ()(unsigned long v) const
00280     {
00281       // If it's the same size as a size_t.
00282       if (sizeof(size_t) >= sizeof(v))
00283       {
00284         return static_cast<size_t>(v);
00285       }
00286       else
00287       {
00288         uint8_t* p = reinterpret_cast<uint8_t*>(&v);
00289         return __private_hash__::generic_hash<size_t>(p, p + sizeof(v));
00290       }
00291     }
00292   };
00293 
00294   //***************************************************************************
00295   /// Specialisation for unsigned long long.
00296   ///\ingroup hash
00297   //***************************************************************************
00298   template<>
00299   struct hash<unsigned long long>
00300   {
00301     size_t  operator ()(unsigned long long v) const
00302     {
00303       // If it's the same size as a size_t.
00304       if (sizeof(size_t) >= sizeof(v))
00305       {
00306         return static_cast<size_t>(v);
00307       }
00308       else
00309       {
00310         uint8_t* p = reinterpret_cast<uint8_t*>(&v);
00311         return __private_hash__::generic_hash<size_t>(p, p + sizeof(v));
00312       }
00313     }
00314   };
00315 
00316   //***************************************************************************
00317   /// Specialisation for float.
00318   ///\ingroup hash
00319   //***************************************************************************
00320   template<>
00321   struct hash<float>
00322   {
00323     size_t operator ()(float v) const
00324     {
00325       // If it's the same size as a size_t.
00326       if (sizeof(size_t) == sizeof(v))
00327       {
00328         union
00329         {
00330           size_t s;
00331           float  v;
00332         } u;
00333 
00334         u.v = v;
00335 
00336         return u.s;
00337       }
00338       else
00339       {
00340         uint8_t* p = reinterpret_cast<uint8_t*>(&v);
00341         return __private_hash__::generic_hash<size_t>(p, p + sizeof(v));
00342       }
00343     }
00344   };
00345 
00346   //***************************************************************************
00347   /// Specialisation for double.
00348   ///\ingroup hash
00349   //***************************************************************************
00350   template<>
00351   struct hash<double>
00352   {
00353     size_t  operator ()(double v) const
00354     {
00355       // If it's the same size as a size_t.
00356       if (sizeof(size_t) == sizeof(v))
00357       {
00358         union
00359         {
00360           size_t s;
00361           double v;
00362         } u;
00363 
00364         u.v = v;
00365         
00366         return u.s;
00367       }
00368       else
00369       {
00370         uint8_t* p = reinterpret_cast<uint8_t*>(&v);
00371         return __private_hash__::generic_hash<size_t>(p, p + sizeof(v));
00372       }
00373     }
00374   };
00375 
00376   //***************************************************************************
00377   /// Specialisation for long double.
00378   ///\ingroup hash
00379   //***************************************************************************
00380   template<>
00381   struct hash<long double>
00382   {
00383     size_t operator ()(long double v) const
00384     {
00385       // If it's the same size as a size_t.
00386       if (sizeof(size_t) == sizeof(v))
00387       {
00388         union
00389         {
00390           size_t s;
00391           long double v;
00392         } u;
00393 
00394         u.v = v;
00395 
00396         return u.s;
00397       }
00398       else
00399       {
00400         uint8_t* p = reinterpret_cast<uint8_t*>(&v);
00401         return __private_hash__::generic_hash<size_t>(p, p + sizeof(v));
00402       }
00403     }
00404   };
00405 
00406   //***************************************************************************
00407   /// Specialisation for pointers.
00408   ///\ingroup hash
00409   //***************************************************************************
00410   template <typename T>
00411   struct hash<T*>
00412   {
00413     size_t operator ()(const T* v) const
00414     {
00415       // If it's the same size as a size_t.
00416       if (sizeof(size_t) == sizeof(T*))
00417       {
00418         union
00419         {
00420           size_t s;
00421           const T* v;
00422         } u;
00423 
00424         u.v = v;
00425 
00426         return u.s;
00427       }
00428       else
00429       {
00430         uint8_t* p = reinterpret_cast<uint8_t*>(&v);
00431         return __private_hash__::generic_hash<size_t>(p, p + sizeof(v));
00432       }
00433     }
00434   };
00435 }
00436 
00437 #endif
00438