| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- #ifndef ENTT_CORE_HASHED_STRING_HPP
- #define ENTT_CORE_HASHED_STRING_HPP
- #include <cstddef>
- #include <cstdint>
- #include "../config/config.h"
- #include "fwd.hpp"
- namespace entt {
- /**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
- namespace internal {
- template<typename>
- struct fnv1a_traits;
- template<>
- struct fnv1a_traits<std::uint32_t> {
- using type = std::uint32_t;
- static constexpr std::uint32_t offset = 2166136261;
- static constexpr std::uint32_t prime = 16777619;
- };
- template<>
- struct fnv1a_traits<std::uint64_t> {
- using type = std::uint64_t;
- static constexpr std::uint64_t offset = 14695981039346656037ull;
- static constexpr std::uint64_t prime = 1099511628211ull;
- };
- } // namespace internal
- /**
- * Internal details not to be documented.
- * @endcond
- */
- /**
- * @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
- * counterparts at runtime.<br/>
- * Because of that, a hashed string can also be used in constant expressions if
- * required.
- *
- * @warning
- * This class doesn't take ownership of user-supplied strings nor does it make a
- * copy of them.
- *
- * @tparam Char Character type.
- */
- template<typename Char>
- class basic_hashed_string {
- using hs_traits = internal::fnv1a_traits<id_type>;
- struct const_wrapper {
- // non-explicit constructor on purpose
- constexpr const_wrapper(const Char *curr) ENTT_NOEXCEPT: str{curr} {}
- const Char *str;
- };
- // Fowler–Noll–Vo hash function v. 1a - the good
- [[nodiscard]] static constexpr id_type helper(const Char *curr) ENTT_NOEXCEPT {
- auto value = hs_traits::offset;
- while(*curr != 0) {
- value = (value ^ static_cast<hs_traits::type>(*(curr++))) * hs_traits::prime;
- }
- return value;
- }
- public:
- /*! @brief Character type. */
- using value_type = Char;
- /*! @brief Unsigned integer type. */
- using hash_type = id_type;
- /**
- * @brief Returns directly the numeric representation of a string view.
- * @param str Human-readable identifer.
- * @param size Length of the string to hash.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const value_type *str, std::size_t size) ENTT_NOEXCEPT {
- id_type partial{hs_traits::offset};
- while(size--) { partial = (partial ^ (str++)[0]) * hs_traits::prime; }
- return partial;
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- *
- * Forcing template resolution avoids implicit conversions. An
- * human-readable identifier can be anything but a plain, old bunch of
- * characters.<br/>
- * Example of use:
- * @code{.cpp}
- * const auto value = basic_hashed_string<char>::value("my.png");
- * @endcode
- *
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifer.
- * @return The numeric representation of the string.
- */
- template<std::size_t N>
- [[nodiscard]] static constexpr hash_type value(const value_type (&str)[N]) ENTT_NOEXCEPT {
- return helper(str);
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- * @param wrapper Helps achieving the purpose by relying on overloading.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static hash_type value(const_wrapper wrapper) ENTT_NOEXCEPT {
- return helper(wrapper.str);
- }
- /*! @brief Constructs an empty hashed string. */
- constexpr basic_hashed_string() ENTT_NOEXCEPT
- : str{nullptr},
- hash{} {}
- /**
- * @brief Constructs a hashed string from an array of const characters.
- *
- * Forcing template resolution avoids implicit conversions. An
- * human-readable identifier can be anything but a plain, old bunch of
- * characters.<br/>
- * Example of use:
- * @code{.cpp}
- * basic_hashed_string<char> hs{"my.png"};
- * @endcode
- *
- * @tparam N Number of characters of the identifier.
- * @param curr Human-readable identifer.
- */
- template<std::size_t N>
- constexpr basic_hashed_string(const value_type (&curr)[N]) ENTT_NOEXCEPT
- : str{curr},
- hash{helper(curr)} {}
- /**
- * @brief Explicit constructor on purpose to avoid constructing a hashed
- * string directly from a `const value_type *`.
- *
- * @warning
- * The lifetime of the string is not extended nor is it copied.
- *
- * @param wrapper Helps achieving the purpose by relying on overloading.
- */
- explicit constexpr basic_hashed_string(const_wrapper wrapper) ENTT_NOEXCEPT
- : str{wrapper.str},
- hash{helper(wrapper.str)} {}
- /**
- * @brief Returns the human-readable representation of a hashed string.
- * @return The string used to initialize the instance.
- */
- [[nodiscard]] constexpr const value_type *data() const ENTT_NOEXCEPT {
- return str;
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the instance.
- */
- [[nodiscard]] constexpr hash_type value() const ENTT_NOEXCEPT {
- return hash;
- }
- /*! @copydoc data */
- [[nodiscard]] constexpr operator const value_type *() const ENTT_NOEXCEPT {
- return data();
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the instance.
- */
- [[nodiscard]] constexpr operator hash_type() const ENTT_NOEXCEPT {
- return value();
- }
- private:
- const value_type *str;
- hash_type hash;
- };
- /**
- * @brief Deduction guide.
- *
- * It allows to deduce the character type of the hashed string directly from a
- * human-readable identifer provided to the constructor.
- *
- * @tparam Char Character type.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifer.
- */
- template<typename Char, std::size_t N>
- basic_hashed_string(const Char (&str)[N]) -> basic_hashed_string<Char>;
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the two hashed strings are identical, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator==(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) ENTT_NOEXCEPT {
- return lhs.value() == rhs.value();
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the two hashed strings differ, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator!=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) ENTT_NOEXCEPT {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is less than the second, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator<(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) ENTT_NOEXCEPT {
- return lhs.value() < rhs.value();
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is less than or equal to the second, false
- * otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator<=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) ENTT_NOEXCEPT {
- return !(rhs < lhs);
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is greater than the second, false
- * otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator>(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) ENTT_NOEXCEPT {
- return rhs < lhs;
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is greater than or equal to the second,
- * false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator>=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) ENTT_NOEXCEPT {
- return !(lhs < rhs);
- }
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- inline namespace literals {
- /**
- * @brief User defined literal for hashed strings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed string.
- */
- [[nodiscard]] constexpr entt::hashed_string operator"" _hs(const char *str, std::size_t) ENTT_NOEXCEPT {
- return entt::hashed_string{str};
- }
- /**
- * @brief User defined literal for hashed wstrings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed wstring.
- */
- [[nodiscard]] constexpr entt::hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) ENTT_NOEXCEPT {
- return entt::hashed_wstring{str};
- }
- } // namespace literals
- } // namespace entt
- #endif
|