#ifndef ARBUTILS_CONSTSTRING_HPP #define ARBUTILS_CONSTSTRING_HPP #include #include #include #include namespace Arbutils { class ConstString { private: const char* _str; size_t _length; uint32_t _hash; inline static uint32_t constexpr Hash(char const* input) { return (*input) ? static_cast((*input)) + 33 * Hash(input + 1) : 5381; } inline static constexpr char charToLower(const char c) { return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c; } inline static uint32_t constexpr LowercaseHash(char const* input) { return charToLower(*input) ? static_cast(charToLower(*input)) + 33 * LowercaseHash(input + 1) : 5381; } inline static int constexpr Length(const char* str) { return *str ? 1 + Length(str + 1) : 0; } public: constexpr ConstString() : _str(""), _length(0), _hash(Hash("")){}; constexpr explicit ConstString(const char* str) : _str(str), _length(Length(str)), _hash(Hash(str)){}; constexpr explicit ConstString(const std::string& str) : _str(str.c_str()), _length(str.length()), _hash(Hash(str.c_str())){}; constexpr explicit ConstString(const char* str, size_t size) : _str(str), _length(size), _hash(Hash(str)){}; [[nodiscard]] inline constexpr const char* c_str() const noexcept { return _str; } [[nodiscard]] inline std::string std_str() const { return std::string(_str, _length); } [[nodiscard]] inline constexpr size_t Length() const noexcept { return _length; } [[nodiscard]] inline constexpr uint32_t GetHash() const noexcept { return _hash; } constexpr std::size_t operator()(ConstString const& s) const noexcept { return s.GetHash(); } inline constexpr operator uint32_t() const { return _hash; } inline constexpr bool operator==(const ConstString& rhs) const { return _hash == rhs._hash; } inline constexpr bool operator!=(const ConstString& rhs) const { return _hash != rhs._hash; } inline constexpr bool operator==(const std::string& rhs) const { return _hash == Hash(rhs.c_str()); } inline constexpr bool operator!=(const std::string& rhs) const { return _hash != Hash(rhs.c_str()); } inline constexpr bool operator==(const char* rhs) const { return _hash == Hash(rhs); } inline constexpr bool operator!=(const char* rhs) const { return _hash != Hash(rhs); } }; } inline constexpr Arbutils::ConstString operator"" _const(const char* c, size_t l) { return Arbutils::ConstString(c, l); } inline constexpr Arbutils::ConstString operator"" _c(const char* c, size_t l) { return Arbutils::ConstString(c, l); } namespace std { template <> struct hash { constexpr std::size_t operator()(Arbutils::ConstString const& s) const noexcept { return s.GetHash(); } }; } #endif // ARBUTILS_CONSTSTRING_HPP