Просмотр исходного кода

hashed string: added possibility to use both uint32 and uint64

Michele Caini 7 лет назад
Родитель
Сommit
8ef818f581
4 измененных файлов с 55 добавлено и 15 удалено
  1. 0 1
      TODO
  2. 6 0
      src/entt/config/config.h
  3. 46 11
      src/entt/core/hashed_string.hpp
  4. 3 3
      test/entt/core/hashed_string.cpp

+ 0 - 1
TODO

@@ -19,5 +19,4 @@
 * empty components model allows for shared components and prefabs unity-like
 * provide create with a pack of default constructible components to assign
 * allow to replace std:: with custom implementations
-* allow user to use also uint32 for hashed strings type if possible
 * allow to sort groups (::respect can already work with begin/end instead of a whole sparse set)

+ 6 - 0
src/entt/config/config.h

@@ -22,4 +22,10 @@ using maybe_atomic_t = Type;
 #endif // ENTT_USE_ATOMIC
 
 
+#ifndef ENTT_HASH_TYPE
+#include <cstdint>
+#define ENTT_HASH_TYPE std::uint32_t
+#endif
+
+
 #endif // ENTT_CONFIG_CONFIG_H

+ 46 - 11
src/entt/core/hashed_string.hpp

@@ -11,7 +11,43 @@ namespace entt {
 
 
 /**
- * @brief Zero overhead resource identifier.
+ * @cond TURN_OFF_DOXYGEN
+ * Internal details not to be documented.
+ */
+
+
+namespace internal {
+
+
+template<typename>
+struct fnv1a_traits;
+
+
+template<>
+struct fnv1a_traits<std::uint32_t> {
+    static constexpr std::uint32_t offset = 2166136261;
+    static constexpr std::uint32_t prime = 16777619;
+};
+
+
+template<>
+struct fnv1a_traits<std::uint64_t> {
+    static constexpr std::uint64_t offset = 14695981039346656037ull;
+    static constexpr std::uint64_t prime = 1099511628211ull;
+};
+
+
+}
+
+
+/**
+ * Internal details not to be documented.
+ * @endcond TURN_OFF_DOXYGEN
+ */
+
+
+/**
+ * @brief Zero overhead unique identifier.
  *
  * A hashed string is a compile-time tool that allows users to use
  * human-readable identifers in the codebase while using their numeric
@@ -20,23 +56,22 @@ namespace entt {
  * required.
  */
 class hashed_string {
+    using traits_type = internal::fnv1a_traits<ENTT_HASH_TYPE>;
+
     struct const_wrapper {
         // non-explicit constructor on purpose
         constexpr const_wrapper(const char *str) ENTT_NOEXCEPT: str{str} {}
         const char *str;
     };
 
-    static constexpr std::uint64_t offset = 14695981039346656037ull;
-    static constexpr std::uint64_t prime = 1099511628211ull;
-
     // Fowler–Noll–Vo hash function v. 1a - the good
-    inline static constexpr std::uint64_t helper(std::uint64_t partial, const char *str) ENTT_NOEXCEPT {
-        return str[0] == 0 ? partial : helper((partial^str[0])*prime, str+1);
+    inline static constexpr ENTT_HASH_TYPE helper(ENTT_HASH_TYPE partial, const char *str) ENTT_NOEXCEPT {
+        return str[0] == 0 ? partial : helper((partial^str[0])*traits_type::prime, str+1);
     }
 
 public:
     /*! @brief Unsigned integer type. */
-    using hash_type = std::uint64_t;
+    using hash_type = ENTT_HASH_TYPE;
 
     /**
      * @brief Returns directly the numeric representation of a string.
@@ -55,7 +90,7 @@ public:
      */
     template<std::size_t N>
     inline static constexpr hash_type to_value(const char (&str)[N]) ENTT_NOEXCEPT {
-        return helper(offset, str);
+        return helper(traits_type::offset, str);
     }
 
     /**
@@ -64,7 +99,7 @@ public:
      * @return The numeric representation of the string.
      */
     inline static hash_type to_value(const_wrapper wrapper) ENTT_NOEXCEPT {
-        return helper(offset, wrapper.str);
+        return helper(traits_type::offset, wrapper.str);
     }
 
     /*! @brief Constructs an empty hashed string. */
@@ -88,7 +123,7 @@ public:
      */
     template<std::size_t N>
     constexpr hashed_string(const char (&str)[N]) ENTT_NOEXCEPT
-        : hash{helper(offset, str)}, str{str}
+        : hash{helper(traits_type::offset, str)}, str{str}
     {}
 
     /**
@@ -98,7 +133,7 @@ public:
      * @param wrapper Helps achieving the purpose by relying on overloading.
      */
     explicit constexpr hashed_string(const_wrapper wrapper) ENTT_NOEXCEPT
-        : hash{helper(offset, wrapper.str)}, str{wrapper.str}
+        : hash{helper(traits_type::offset, wrapper.str)}, str{wrapper.str}
     {}
 
     /**

+ 3 - 3
test/entt/core/hashed_string.cpp

@@ -21,8 +21,8 @@ TEST(HashedString, Functionalities) {
 
     entt::hashed_string hs{"foobar"};
 
-    ASSERT_EQ(static_cast<hash_type>(hs), 0x85944171f73967e8);
-    ASSERT_EQ(hs.value(), 0x85944171f73967e8);
+    ASSERT_EQ(static_cast<hash_type>(hs), 0xbf9cf968);
+    ASSERT_EQ(hs.value(), 0xbf9cf968);
 
     ASSERT_EQ(foo_hs, "foo"_hs);
     ASSERT_NE(bar_hs, "foo"_hs);
@@ -50,7 +50,7 @@ TEST(HashedString, ToValue) {
 
     const char *foobar = "foobar";
 
-    ASSERT_EQ(entt::hashed_string::to_value(foobar), 0x85944171f73967e8);
+    ASSERT_EQ(entt::hashed_string::to_value(foobar), 0xbf9cf968);
     // how would you test a constexpr otherwise?
     (void)std::integral_constant<hash_type, entt::hashed_string::to_value("quux")>{};
 }