|
@@ -24,6 +24,9 @@
|
|
|
|
|
|
|
|
#include "../Math/MathDefs.h"
|
|
#include "../Math/MathDefs.h"
|
|
|
#include "../Math/StringHash.h"
|
|
#include "../Math/StringHash.h"
|
|
|
|
|
+#include "../Container/HashMap.h"
|
|
|
|
|
+#include "../Core/Mutex.h"
|
|
|
|
|
+#include "../IO/Log.h"
|
|
|
|
|
|
|
|
#include <cstdio>
|
|
#include <cstdio>
|
|
|
|
|
|
|
@@ -32,16 +35,87 @@
|
|
|
namespace Urho3D
|
|
namespace Urho3D
|
|
|
{
|
|
{
|
|
|
|
|
|
|
|
|
|
+#ifdef URHO3D_HASH_DEBUG
|
|
|
|
|
+
|
|
|
|
|
+// Expose map to let Visual Studio debugger access it if Urho3D is linked statically.
|
|
|
|
|
+StringMap* hashReverseMap = nullptr;
|
|
|
|
|
+
|
|
|
|
|
+// Hide static global variables in functions to ensure initialization order.
|
|
|
|
|
+// @{
|
|
|
|
|
+static Mutex& GetHashReverseMapMutex()
|
|
|
|
|
+{
|
|
|
|
|
+ static Mutex mutex;
|
|
|
|
|
+ return mutex;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static StringMap& GetHashReverseMap()
|
|
|
|
|
+{
|
|
|
|
|
+ static StringMap map;
|
|
|
|
|
+ hashReverseMap = ↦
|
|
|
|
|
+ return map;
|
|
|
|
|
+}
|
|
|
|
|
+// @}
|
|
|
|
|
+
|
|
|
|
|
+static void AddStringHash(const StringHash& hash, const char* string)
|
|
|
|
|
+{
|
|
|
|
|
+ Mutex& guard = GetHashReverseMapMutex();
|
|
|
|
|
+ guard.Acquire();
|
|
|
|
|
+
|
|
|
|
|
+ StringMap& map = GetHashReverseMap();
|
|
|
|
|
+ auto iter = map.Find(hash);
|
|
|
|
|
+ if (iter == map.End())
|
|
|
|
|
+ {
|
|
|
|
|
+ map.Populate(hash, string);
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (iter->second_.Compare(string, false) != 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ URHO3D_LOGWARNINGF("String hash collision detected! Both \"%s\" and \"%s\" have hash #%s",
|
|
|
|
|
+ string, iter->second_.CString(), hash.ToString().CString());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ guard.Release();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static String ReverseStringHash(const StringHash& hash)
|
|
|
|
|
+{
|
|
|
|
|
+ Mutex& guard = GetHashReverseMapMutex();
|
|
|
|
|
+ guard.Acquire();
|
|
|
|
|
+
|
|
|
|
|
+ const StringMap& map = GetHashReverseMap();
|
|
|
|
|
+ auto iter = map.Find(hash);
|
|
|
|
|
+ String result = iter == map.End() ? String::EMPTY : iter->second_;
|
|
|
|
|
+
|
|
|
|
|
+ guard.Release();
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#else
|
|
|
|
|
+
|
|
|
|
|
+static void AddStringHash(const StringHash& /*hash*/, const char* /*string*/)
|
|
|
|
|
+{
|
|
|
|
|
+ // Do nothing
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static String ReverseStringHash(const StringHash& /*hash*/)
|
|
|
|
|
+{
|
|
|
|
|
+ // Do nothing
|
|
|
|
|
+ return String::EMPTY;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
const StringHash StringHash::ZERO;
|
|
const StringHash StringHash::ZERO;
|
|
|
|
|
|
|
|
StringHash::StringHash(const char* str) noexcept :
|
|
StringHash::StringHash(const char* str) noexcept :
|
|
|
value_(Calculate(str))
|
|
value_(Calculate(str))
|
|
|
{
|
|
{
|
|
|
|
|
+ AddStringHash(*this, str);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
StringHash::StringHash(const String& str) noexcept :
|
|
StringHash::StringHash(const String& str) noexcept :
|
|
|
value_(Calculate(str.CString()))
|
|
value_(Calculate(str.CString()))
|
|
|
{
|
|
{
|
|
|
|
|
+ AddStringHash(*this, str.CString());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
unsigned StringHash::Calculate(const char* str, unsigned hash)
|
|
unsigned StringHash::Calculate(const char* str, unsigned hash)
|
|
@@ -60,6 +134,15 @@ unsigned StringHash::Calculate(const char* str, unsigned hash)
|
|
|
return hash;
|
|
return hash;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+const StringMap* StringHash::GetHashReverseMap()
|
|
|
|
|
+{
|
|
|
|
|
+#ifdef URHO3D_HASH_DEBUG
|
|
|
|
|
+ return &Urho3D::GetHashReverseMap();
|
|
|
|
|
+#else
|
|
|
|
|
+ return nullptr;
|
|
|
|
|
+#endif
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
String StringHash::ToString() const
|
|
String StringHash::ToString() const
|
|
|
{
|
|
{
|
|
|
char tempBuffer[CONVERSION_BUFFER_LENGTH];
|
|
char tempBuffer[CONVERSION_BUFFER_LENGTH];
|
|
@@ -67,4 +150,9 @@ String StringHash::ToString() const
|
|
|
return String(tempBuffer);
|
|
return String(tempBuffer);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+String StringHash::Reverse() const
|
|
|
|
|
+{
|
|
|
|
|
+ return ReverseStringHash(*this);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
}
|
|
}
|