133 lines
5.6 KiB
C++
133 lines
5.6 KiB
C++
#ifndef ARBUTILS_STRINGVIEW_HPP
|
|
#define ARBUTILS_STRINGVIEW_HPP
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <memory>
|
|
#include <string_view>
|
|
#include "BasicStringView.hpp"
|
|
|
|
#if WINDOWS
|
|
#define STDSTRINGCONSTEXPR
|
|
#else
|
|
#define STDSTRINGCONSTEXPR constexpr
|
|
#endif
|
|
|
|
namespace ArbUt {
|
|
class __ConstStringCharHolder {
|
|
char* _value = 0;
|
|
|
|
__ConstStringCharHolder(const __ConstStringCharHolder& o) = delete;
|
|
__ConstStringCharHolder& operator=(const __ConstStringCharHolder& other) = delete;
|
|
|
|
public:
|
|
__ConstStringCharHolder(const char* value, size_t length) noexcept : _value(new char[length + 1]) {
|
|
strncpy(_value, value, length + 1);
|
|
}
|
|
~__ConstStringCharHolder() noexcept { delete[] _value; }
|
|
inline constexpr const char* GetValue() const noexcept { return _value; }
|
|
};
|
|
}
|
|
|
|
inline static constexpr char charToLower(const char c) { return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c; }
|
|
static uint32_t constexpr Hash(char const* input) {
|
|
return charToLower(*input) ? static_cast<uint32_t>(charToLower(*input)) + 33 * Hash(input + 1) : 5381;
|
|
};
|
|
static int constexpr CalcLength(const char* str) { return *str ? 1 + CalcLength(str + 1) : 0; }
|
|
|
|
namespace ArbUt {
|
|
/// \ingroup Strings
|
|
/// @brief A constant, non-editable string that allows copies to share the same string object.
|
|
class StringView final : public BasicStringView {
|
|
private:
|
|
static std::shared_ptr<__ConstStringCharHolder> __emptyString;
|
|
static inline const std::shared_ptr<__ConstStringCharHolder>& GetEmptyString() { return __emptyString; }
|
|
|
|
std::shared_ptr<__ConstStringCharHolder> _str = GetEmptyString();
|
|
|
|
public:
|
|
/// @brief Instantiate a StringView using a C string.
|
|
/// @param str A null-terminated C string.
|
|
StringView(const char* str) noexcept
|
|
: BasicStringView(CalcLength(str), Hash(str)), _str(new __ConstStringCharHolder(str, CalcLength(str))) {}
|
|
/// @brief Instantiate a StringView using a C string, as well as it's length.
|
|
/// @param str A null-terminated C string.
|
|
/// @param length The length of the C string
|
|
StringView(const char* str, size_t length) noexcept
|
|
: BasicStringView(length, Hash(str)), _str(new __ConstStringCharHolder(str, length)) {}
|
|
StringView() noexcept : BasicStringView(0, Hash("")) {}
|
|
|
|
/* Copy operators */
|
|
/// @brief Copy operator
|
|
/// @param other Other StringView
|
|
StringView(const StringView& other) noexcept : BasicStringView(other._length, other._hash), _str(other._str) {}
|
|
/// @brief Special constructor of stringview, specifically designed for use of conversion from StringViewLiteral
|
|
/// to StringView.
|
|
/// @param other Other StringView
|
|
/// @param c A null-terminated C string.
|
|
/// @param length The length of the C string.
|
|
StringView(const BasicStringView& other, const char* c, size_t length) noexcept
|
|
: BasicStringView(length, other.GetHash()), _str(new __ConstStringCharHolder(c, length)) {}
|
|
|
|
/// @brief Assignment operator.
|
|
/// @param other Stringview to assign.
|
|
/// @return current stringview.
|
|
StringView& operator=(const StringView& other) noexcept {
|
|
if (this == &other || _str == other._str) {
|
|
return *this;
|
|
}
|
|
_str = other._str;
|
|
_length = other._length;
|
|
_hash = other._hash;
|
|
return *this;
|
|
}
|
|
|
|
/// @brief Returns null-terminated C string.
|
|
/// @return Null-terminated C string.
|
|
[[nodiscard]] inline const char* c_str() const noexcept override { return _str->GetValue(); }
|
|
/// @brief Returns std string_view of internal C string.
|
|
/// @return std::string_view.
|
|
[[nodiscard]] inline std::string_view std_str() const noexcept override { return _str->GetValue(); }
|
|
|
|
inline constexpr bool operator==(const std::string_view& rhs) const noexcept override {
|
|
return _hash == Hash(rhs.data());
|
|
}
|
|
inline constexpr bool operator!=(const std::string_view& rhs) const noexcept override {
|
|
return _hash != Hash(rhs.data());
|
|
}
|
|
inline constexpr bool operator==(const char* rhs) const noexcept override { return _hash == Hash(rhs); }
|
|
inline constexpr bool operator!=(const char* rhs) const noexcept override { return _hash != Hash(rhs); }
|
|
|
|
/// @brief Calculates the hash for a given C string.
|
|
/// @param val A null-terminated C string.
|
|
/// @return A hash of the given string.
|
|
[[maybe_unused]] [[nodiscard]] inline static constexpr uint32_t CalculateHash(const char* val) noexcept {
|
|
return Hash(val);
|
|
}
|
|
|
|
/// @brief Calculates the hash for a given std string.
|
|
/// @param val A std string.
|
|
/// @return A hash of the given string.
|
|
[[maybe_unused]] [[nodiscard]] inline static constexpr uint32_t
|
|
CalculateHash(const std::string_view& val) noexcept {
|
|
return Hash(val.data());
|
|
}
|
|
|
|
/// @brief Returns an empty string.
|
|
/// @return An empty string.
|
|
static const StringView& EmptyString();
|
|
};
|
|
}
|
|
|
|
namespace std {
|
|
/// @brief Helper class for hashing string views.
|
|
template <> struct hash<ArbUt::StringView> {
|
|
/// @brief Returns the hash of a stringview.
|
|
/// @param s a StringView.
|
|
/// @return The hash of the StringView.
|
|
constexpr std::size_t operator()(ArbUt::StringView const& s) const noexcept { return s.GetHash(); }
|
|
};
|
|
}
|
|
#endif // ARBUTILS_STRINGVIEW_HPP
|