#ifndef ARBUTILS_CONSTSTRINGCORE_HPP #define ARBUTILS_CONSTSTRINGCORE_HPP #if WINDOWS #define STDSTRINGCONSTEXPR #else #define STDSTRINGCONSTEXPR constexpr #endif #define ConstStringCore(name, hashFunction) \ namespace Arbutils { \ class name { \ private: \ const char* _str; \ size_t _length; \ uint32_t _hash; \ \ hashFunction; \ \ inline static int constexpr Length(const char* str) { return *str ? 1 + Length(str + 1) : 0; } \ \ public: \ constexpr name() : _str(""), _length(0), _hash(Hash("")){}; \ constexpr explicit name(const char* str) : _str(str), _length(Length(str)), _hash(Hash(str)){}; \ STDSTRINGCONSTEXPR explicit name(const std::string& str) \ : _str(str.c_str()), _length(str.length()), _hash(Hash(str.c_str())){}; \ constexpr explicit name(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; } \ inline constexpr bool Empty() const noexcept { return _length == 0; } \ \ constexpr std::size_t operator()(name const& s) const noexcept { return s.GetHash(); } \ inline constexpr operator uint32_t() const { return _hash; } \ \ inline constexpr bool operator==(const name& rhs) const { return _hash == rhs._hash; } \ inline constexpr bool operator!=(const name& rhs) const { return _hash != rhs._hash; } \ inline STDSTRINGCONSTEXPR bool operator==(const std::string& rhs) const { \ return _hash == Hash(rhs.c_str()); \ } \ inline STDSTRINGCONSTEXPR 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 static constexpr uint32_t GetHash(const char* val) { return Hash(val); } \ inline static STDSTRINGCONSTEXPR uint32_t GetHash(const std::string& val) { return Hash(val.c_str()); } \ }; \ } \ \ namespace std { \ template <> struct hash { \ constexpr std::size_t operator()(Arbutils::name const& s) const noexcept { return s.GetHash(); } \ }; \ } #endif