hashed string: added possibility to use both uint32 and uint64

This commit is contained in:
Michele Caini
2019-02-13 22:30:04 +01:00
parent 48dace64e4
commit 8ef818f581
4 changed files with 55 additions and 15 deletions

1
TODO
View File

@@ -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)

View File

@@ -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

View File

@@ -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;
// FowlerNollVo 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}
{}
/**

View File

@@ -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")>{};
}