Split off Case Insensitive const string.
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Deukhoofd 2020-02-27 16:53:30 +01:00
parent 6e4c77d77a
commit 09b6fd92ce
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
3 changed files with 69 additions and 18 deletions

View File

@ -0,0 +1,66 @@
#ifndef ARBUTILS_CASEINSENSITIVECONSTSTRING_HPP
#define ARBUTILS_CASEINSENSITIVECONSTSTRING_HPP
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <string>
namespace Arbutils {
class CaseInsensitiveConstString {
private:
const char* _str;
size_t _length;
uint32_t _hash;
inline static constexpr char charToLower(const char c) { return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c; }
inline static uint32_t constexpr Hash(char const* input) {
return charToLower(*input) ? static_cast<uint32_t>(charToLower(*input)) + 33 * Hash(input + 1) : 5381;
}
inline static int constexpr Length(const char* str) { return *str ? 1 + Length(str + 1) : 0; }
public:
constexpr CaseInsensitiveConstString() : _str(""), _length(0), _hash(Hash("")){};
constexpr explicit CaseInsensitiveConstString(const char* str)
: _str(str), _length(Length(str)), _hash(Hash(str)){};
constexpr explicit CaseInsensitiveConstString(const std::string& str)
: _str(str.c_str()), _length(str.length()), _hash(Hash(str.c_str())){};
constexpr explicit CaseInsensitiveConstString(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()(CaseInsensitiveConstString const& s) const noexcept { return s.GetHash(); }
inline constexpr operator uint32_t() const { return _hash; }
inline constexpr bool operator==(const CaseInsensitiveConstString& rhs) const { return _hash == rhs._hash; }
inline constexpr bool operator!=(const CaseInsensitiveConstString& 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::CaseInsensitiveConstString operator"" _const_nocase(const char* c, size_t l) {
return Arbutils::CaseInsensitiveConstString(c, l);
}
inline constexpr Arbutils::CaseInsensitiveConstString operator"" _cnc(const char* c, size_t l) {
return Arbutils::CaseInsensitiveConstString(c, l);
}
namespace std {
template <> struct hash<Arbutils::CaseInsensitiveConstString> {
constexpr std::size_t operator()(Arbutils::CaseInsensitiveConstString const& s) const noexcept {
return s.GetHash();
}
};
}
#endif // ARBUTILS_CASEINSENSITIVECONSTSTRING_HPP

View File

@ -25,11 +25,6 @@ namespace Arbutils {
inline static int constexpr Length(const char* str) { return *str ? 1 + Length(str + 1) : 0; }
constexpr explicit ConstString(const char* str, bool)
: _str(str), _length(Length(str)), _hash(LowercaseHash(str)){};
constexpr explicit ConstString(const char* str, size_t size, bool)
: _str(str), _length(size), _hash(LowercaseHash(str)){};
public:
constexpr ConstString() : _str(""), _length(0), _hash(Hash("")){};
constexpr explicit ConstString(const char* str) : _str(str), _length(Length(str)), _hash(Hash(str)){};
@ -37,11 +32,6 @@ namespace Arbutils {
: _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)){};
static constexpr inline ConstString CaseInsensitive(const char* str) { return ConstString(str, true); }
static constexpr inline ConstString CaseInsensitive(const char* str, size_t size) {
return ConstString(str, size, true);
}
[[nodiscard]] inline constexpr const char* c_str() const noexcept { return _str; }
[[nodiscard]] inline std::string std_str() const { return std::string(_str, _length); }
@ -65,12 +55,6 @@ 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); }
inline constexpr Arbutils::ConstString operator"" _const_nocase(const char* c, size_t l) {
return Arbutils::ConstString::CaseInsensitive(c, l);
}
inline constexpr Arbutils::ConstString operator"" _cnc(const char* c, size_t l) {
return Arbutils::ConstString::CaseInsensitive(c, l);
}
namespace std {
template <> struct hash<Arbutils::ConstString> {

View File

@ -2,6 +2,7 @@
#include <cstring>
#include <unordered_map>
#include "../extern/catch.hpp"
#include "../src/CaseInsensitiveConstString.hpp"
#include "../src/ConstString.hpp"
TEST_CASE("Use const string in unordered_map", "[Utilities]") {
@ -24,7 +25,7 @@ TEST_CASE("Use const string in switch case", "[Utilities]") {
}
TEST_CASE("Use insensitive const string in unordered_map", "[Utilities]") {
std::unordered_map<Arbutils::ConstString, int32_t> map;
std::unordered_map<Arbutils::CaseInsensitiveConstString, int32_t> map;
map.insert({"foO"_cnc, 1});
map.insert({"bAR"_cnc, 5});
@ -33,7 +34,7 @@ TEST_CASE("Use insensitive const string in unordered_map", "[Utilities]") {
}
TEST_CASE("Use case insensitive const string in switch case", "[Utilities]") {
auto val = Arbutils::ConstString::CaseInsensitive("foobar");
auto val = Arbutils::CaseInsensitiveConstString("foobar");
switch (val){
case "foo"_cnc: FAIL(); break;
case "bar"_cnc: FAIL(); break;