From 0149c30df45855e433316c77376cd9f61fa011a3 Mon Sep 17 00:00:00 2001
From: Sam Hocevar <sam@hocevar.net>
Date: Tue, 20 Nov 2012 00:23:15 +0000
Subject: [PATCH] core: refactor the Hash class so that we can hash base types,
 too.

---
 src/Makefile.am     |   8 ++-
 src/core.h          |   2 +-
 src/core/hash.cpp   | 136 ++++++++++++++++++++++++++++++++++++++++++++
 src/gpu/shader.cpp  |  10 ++--
 src/hash.cpp        |  63 --------------------
 src/hash.h          |  31 ----------
 src/lol/core/hash.h |  43 ++++++++++++++
 src/lolcore.vcxproj |   5 +-
 8 files changed, 194 insertions(+), 104 deletions(-)
 create mode 100644 src/core/hash.cpp
 delete mode 100644 src/hash.cpp
 delete mode 100644 src/hash.h
 create mode 100644 src/lol/core/hash.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 925fe1cf..66e6fad7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -6,18 +6,18 @@ SUBDIRS = data
 noinst_LIBRARIES = liblol.a
 
 liblol_a_SOURCES = \
-    core.h tiler.cpp tiler.h dict.cpp dict.h array.h \
+    core.h tiler.cpp tiler.h dict.cpp dict.h \
     audio.cpp audio.h scene.cpp scene.h font.cpp font.h layer.cpp layer.h \
     map.cpp map.h entity.cpp entity.h ticker.cpp ticker.h lolgl.h \
     tileset.cpp tileset.h forge.cpp forge.h video.cpp video.h log.cpp log.h \
     timer.cpp timer.h bitfield.h profiler.cpp profiler.h \
     world.cpp world.h sample.cpp sample.h sampler.cpp sampler.h \
-    text.cpp text.h emitter.cpp emitter.h numeric.h hash.cpp hash.h \
+    text.cpp text.h emitter.cpp emitter.h numeric.h \
     worldentity.cpp worldentity.h gradient.cpp gradient.h gradient.lolfx \
     platform.cpp platform.h sprite.cpp sprite.h camera.cpp camera.h \
     \
     lol/unit.h lol/debug.h \
-    lol/core/array.h lol/core/string.h \
+    lol/core/array.h lol/core/string.h lol/core/hash.h \
     lol/math/vector.h lol/math/half.h lol/math/real.h lol/math/remez.h \
     lol/math/math.h \
     \
@@ -40,6 +40,8 @@ liblol_a_SOURCES = \
     $(android_sources) \
     $(bullet_sources) \
     \
+    core/hash.cpp \
+    \
     thread/threadbase.h thread/thread.h \
     \
     math/vector.cpp math/real.cpp math/half.cpp math/trig.cpp \
diff --git a/src/core.h b/src/core.h
index fab1529f..56117be6 100644
--- a/src/core.h
+++ b/src/core.h
@@ -77,6 +77,7 @@ static inline int isnan(float f)
 #include <lol/debug.h>
 #include <lol/core/array.h>
 #include <lol/core/string.h>
+#include <lol/core/hash.h>
 #include <lol/math/math.h>
 #include <lol/math/half.h>
 #include <lol/math/real.h>
@@ -111,7 +112,6 @@ static inline int isnan(float f)
 #include "world.h"
 
 // Other objects
-#include "hash.h"
 #include "dict.h"
 #include "map.h"
 #include "layer.h"
diff --git a/src/core/hash.cpp b/src/core/hash.cpp
new file mode 100644
index 00000000..55cc9dcd
--- /dev/null
+++ b/src/core/hash.cpp
@@ -0,0 +1,136 @@
+//
+// Lol Engine
+//
+// Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net>
+//   This program is free software; you can redistribute it and/or
+//   modify it under the terms of the Do What The Fuck You Want To
+//   Public License, Version 2, as published by Sam Hocevar. See
+//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
+//
+
+#if defined HAVE_CONFIG_H
+#   include "config.h"
+#endif
+
+#include "core.h"
+
+namespace lol
+{
+
+/*
+ * Hash implementations
+ */
+
+static class HashData
+{
+public:
+    HashData()
+    {
+        /* Initialise CRC32 table */
+        for (int i = 0; i < 256; i++)
+        {
+            uint32_t tmp = i;
+            for (int j = 8; j--; )
+                tmp = (tmp >> 1) ^ ((tmp & 1) ? 0xedb88320 : 0);
+            crc32_table[i] = tmp;
+        }
+    }
+
+    uint32_t crc32_table[256];
+}
+const data;
+
+/*
+ * Public Hash classes
+ */
+
+uint32_t Hash<int8_t>::operator ()(int8_t x)
+{
+    uint32_t ret = 0xffffffffu;
+    ret = data.crc32_table[(uint8_t)(ret ^ x)] ^ (ret >> 8);
+    return ret ^ 0xffffffffu;
+}
+
+uint32_t Hash<uint8_t>::operator ()(uint8_t x)
+{
+    uint32_t ret = 0xffffffffu;
+    ret = data.crc32_table[(uint8_t)(ret ^ x)] ^ (ret >> 8);
+    return ret ^ 0xffffffffu;
+}
+
+uint32_t Hash<int16_t>::operator ()(int16_t x)
+{
+    uint32_t ret = 0xffffffffu;
+    ret = data.crc32_table[(uint8_t)(ret ^ x)] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 8))] ^ (ret >> 8);
+    return ret ^ 0xffffffffu;
+}
+
+uint32_t Hash<uint16_t>::operator ()(uint16_t x)
+{
+    uint32_t ret = 0xffffffffu;
+    ret = data.crc32_table[(uint8_t)(ret ^ x)] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 8))] ^ (ret >> 8);
+    return ret ^ 0xffffffffu;
+}
+
+uint32_t Hash<int32_t>::operator ()(int32_t x)
+{
+    uint32_t ret = 0xffffffffu;
+    ret = data.crc32_table[(uint8_t)(ret ^ x)] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 8))] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 16))] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 24))] ^ (ret >> 8);
+    return ret ^ 0xffffffffu;
+}
+
+uint32_t Hash<uint32_t>::operator ()(uint32_t x)
+{
+    uint32_t ret = 0xffffffffu;
+    ret = data.crc32_table[(uint8_t)(ret ^ x)] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 8))] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 16))] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 24))] ^ (ret >> 8);
+    return ret ^ 0xffffffffu;
+}
+
+uint32_t Hash<int64_t>::operator ()(int64_t x)
+{
+    uint32_t ret = 0xffffffffu;
+    ret = data.crc32_table[(uint8_t)(ret ^ x)] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 8))] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 16))] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 24))] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 32))] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 40))] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 48))] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 56))] ^ (ret >> 8);
+    return ret ^ 0xffffffffu;
+}
+
+uint32_t Hash<uint64_t>::operator ()(uint64_t x)
+{
+    uint32_t ret = 0xffffffffu;
+    ret = data.crc32_table[(uint8_t)(ret ^ x)] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 8))] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 16))] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 24))] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 32))] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 40))] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 48))] ^ (ret >> 8);
+    ret = data.crc32_table[(uint8_t)(ret ^ (x >> 56))] ^ (ret >> 8);
+    return ret ^ 0xffffffffu;
+}
+
+uint32_t Hash<char const *>::operator ()(char const *s)
+{
+    uint32_t ret = 0xffffffffu, ch;
+
+    while ((ch = (uint8_t)*s++))
+        ret = data.crc32_table[(uint8_t)(ret ^ ch)] ^ (ret >> 8);
+
+    return ret ^ 0xffffffffu;
+}
+
+} /* namespace lol */
+
diff --git a/src/gpu/shader.cpp b/src/gpu/shader.cpp
index 9ca003df..67d1abdc 100644
--- a/src/gpu/shader.cpp
+++ b/src/gpu/shader.cpp
@@ -71,10 +71,12 @@ private:
 
     /* Global shader cache */
     static Shader *shaders[];
+    static Hash<char const *> hash;
     static int nshaders;
 };
 
 Shader *ShaderData::shaders[256];
+Hash<char const *> ShaderData::hash;
 int ShaderData::nshaders = 0;
 
 /*
@@ -137,8 +139,8 @@ Shader *Shader::Create(char const *lolfx)
     if (!frag)
         Log::Error("no fragment shader found… sorry, I’m gonna crash now.\n");
 
-    uint32_t new_vert_crc = Hash::Crc32(vert);
-    uint32_t new_frag_crc = Hash::Crc32(frag);
+    uint32_t new_vert_crc = ShaderData::hash(vert);
+    uint32_t new_frag_crc = ShaderData::hash(frag);
 
     for (int n = 0; n < ShaderData::nshaders; n++)
     {
@@ -189,7 +191,7 @@ Shader::Shader(char const *vert, char const *frag)
 #endif
 
     /* Compile vertex shader */
-    data->vert_crc = Hash::Crc32(vert);
+    data->vert_crc = ShaderData::hash(vert);
 #if defined USE_D3D9 || defined _XBOX
     hr = D3DXCompileShader(vert, (UINT)strlen(vert), macros, NULL, "main",
                            "vs_3_0", 0, &shader_code, &error_msg,
@@ -233,7 +235,7 @@ Shader::Shader(char const *vert, char const *frag)
 #endif
 
     /* Compile fragment shader */
-    data->frag_crc = Hash::Crc32(frag);
+    data->frag_crc = ShaderData::hash(frag);
 #if defined USE_D3D9 || defined _XBOX
     hr = D3DXCompileShader(frag, (UINT)strlen(frag), macros, NULL, "main",
                            "ps_3_0", 0, &shader_code, &error_msg,
diff --git a/src/hash.cpp b/src/hash.cpp
deleted file mode 100644
index 95445c9e..00000000
--- a/src/hash.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-//
-// Lol Engine
-//
-// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
-//   This program is free software; you can redistribute it and/or
-//   modify it under the terms of the Do What The Fuck You Want To
-//   Public License, Version 2, as published by Sam Hocevar. See
-//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
-//
-
-#if defined HAVE_CONFIG_H
-#   include "config.h"
-#endif
-
-#include "core.h"
-
-namespace lol
-{
-
-/*
- * Hash implementation class
- */
-
-static class HashData
-{
-    friend class Hash;
-
-public:
-    HashData()
-    {
-        /* Initialise CRC32 table */
-        for (int i = 0; i < 256; i++)
-        {
-            uint32_t tmp = i;
-            for (int j = 8; j--; )
-                tmp = (tmp >> 1) ^ ((tmp & 1) ? 0xedb88320 : 0);
-            crc32_table[i] = tmp;
-        }
-    }
-
-private:
-    uint32_t crc32_table[256];
-}
-hashdata;
-
-static HashData * const data = &hashdata;
-
-/*
- * Public Hash class
- */
-
-uint32_t Hash::Crc32(char const *str)
-{
-    uint32_t ret = 0xffffffff, ch;
-
-    while ((ch = (uint8_t)*str++))
-        ret = data->crc32_table[(uint8_t)(ret ^ ch)] ^ (ret >> 8);
-
-    return ret ^ 0xffffffff;
-}
-
-} /* namespace lol */
-
diff --git a/src/hash.h b/src/hash.h
deleted file mode 100644
index 1ae54cad..00000000
--- a/src/hash.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// Lol Engine
-//
-// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
-//   This program is free software; you can redistribute it and/or
-//   modify it under the terms of the Do What The Fuck You Want To
-//   Public License, Version 2, as published by Sam Hocevar. See
-//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
-//
-
-//
-// The Hash class
-// --------------
-//
-
-#if !defined __LOL_HASH_H__
-#define __LOL_HASH_H__
-
-namespace lol
-{
-
-class Hash
-{
-public:
-    static uint32_t Crc32(char const *data);
-};
-
-} /* namespace lol */
-
-#endif // __LOL_HASH_H__
-
diff --git a/src/lol/core/hash.h b/src/lol/core/hash.h
new file mode 100644
index 00000000..f02196c9
--- /dev/null
+++ b/src/lol/core/hash.h
@@ -0,0 +1,43 @@
+//
+// Lol Engine
+//
+// Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net>
+//   This program is free software; you can redistribute it and/or
+//   modify it under the terms of the Do What The Fuck You Want To
+//   Public License, Version 2, as published by Sam Hocevar. See
+//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
+//
+
+//
+// The Hash class
+// --------------
+// A very simple Hash class.
+//
+
+#if !defined __LOL_HASH_H__
+#define __LOL_HASH_H__
+
+namespace lol
+{
+
+template<typename T> class Hash;
+
+template<> class Hash<int8_t>   { public: uint32_t operator()(int8_t); };
+template<> class Hash<uint8_t>  { public: uint32_t operator()(uint8_t); };
+template<> class Hash<int16_t>  { public: uint32_t operator()(int16_t); };
+template<> class Hash<uint16_t> { public: uint32_t operator()(uint16_t); };
+template<> class Hash<int32_t>  { public: uint32_t operator()(int32_t); };
+template<> class Hash<uint32_t> { public: uint32_t operator()(uint32_t); };
+template<> class Hash<int64_t>  { public: uint32_t operator()(int64_t); };
+template<> class Hash<uint64_t> { public: uint32_t operator()(uint64_t); };
+
+template<> class Hash<char const *>
+{
+public:
+    uint32_t operator()(char const *x);
+};
+
+} /* namespace lol */
+
+#endif // __LOL_HASH_H__
+
diff --git a/src/lolcore.vcxproj b/src/lolcore.vcxproj
index 6cd38a8f..bd98d8b0 100644
--- a/src/lolcore.vcxproj
+++ b/src/lolcore.vcxproj
@@ -234,6 +234,7 @@
     <ClCompile Include="bullet\LinearMath\btQuickprof.cpp" />
     <ClCompile Include="bullet\LinearMath\btSerializer.cpp" />
     <ClCompile Include="camera.cpp" />
+    <ClCompile Include="core\hash.cpp" />
     <ClCompile Include="debug\fps.cpp" />
     <ClCompile Include="debug\record.cpp" />
     <ClCompile Include="debug\stats.cpp" />
@@ -257,7 +258,6 @@
     <ClCompile Include="gpu\texture.cpp" />
     <ClCompile Include="gpu\vertexbuffer.cpp" />
     <ClCompile Include="gradient.cpp" />
-    <ClCompile Include="hash.cpp" />
     <ClCompile Include="image\codec\android-image.cpp" />
     <ClCompile Include="image\codec\dummy-image.cpp" />
     <ClCompile Include="image\codec\gdiplus-image.cpp" />
@@ -572,7 +572,6 @@
     <ClInclude Include="gpu\texture.h" />
     <ClInclude Include="gpu\vertexbuffer.h" />
     <ClInclude Include="gradient.h" />
-    <ClInclude Include="hash.h" />
     <ClInclude Include="image\image-private.h" />
     <ClInclude Include="image\image.h" />
     <ClInclude Include="input\input.h" />
@@ -583,6 +582,8 @@
     <ClInclude Include="loldebug.h" />
     <ClInclude Include="lolgl.h" />
     <ClInclude Include="lol\core\array.h" />
+    <ClInclude Include="lol\core\hash.h" />
+    <ClInclude Include="lol\core\string.h" />
     <ClInclude Include="lol\debug.h" />
     <ClInclude Include="lol\math\half.h" />
     <ClInclude Include="lol\math\math.h" />