Resolve issue where ConstString can lose internal string representation due to not owning it.

This sadly meant most constexpr constructors had to be removed, as it needs to copy the string.
This commit is contained in:
Deukhoofd 2020-04-07 18:54:23 +02:00
parent 460f9308a0
commit 6b4d18f434
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
3 changed files with 37 additions and 10 deletions

View File

@ -15,9 +15,11 @@ ConstStringCore(
inline constexpr Arbutils::ConstString inline constexpr Arbutils::ConstString
operator"" _const(const char* c, size_t l) { operator"" _const(const char* c, size_t l) {
return Arbutils::ConstString(c, l); return Arbutils::ConstString::Literal(c, l);
}
inline constexpr Arbutils::ConstString operator"" _c(const char* c, size_t l) {
return Arbutils::ConstString::Literal(c, l);
} }
inline constexpr Arbutils::ConstString operator"" _c(const char* c, size_t l) { return Arbutils::ConstString(c, l); }
ConstStringCore( ConstStringCore(
CaseInsensitiveConstString, CaseInsensitiveConstString,
@ -28,10 +30,10 @@ ConstStringCore(
};); };);
inline constexpr Arbutils::CaseInsensitiveConstString operator"" _const_nocase(const char* c, size_t l) { inline constexpr Arbutils::CaseInsensitiveConstString operator"" _const_nocase(const char* c, size_t l) {
return Arbutils::CaseInsensitiveConstString(c, l); return Arbutils::CaseInsensitiveConstString::Literal(c, l);
} }
inline constexpr Arbutils::CaseInsensitiveConstString operator"" _cnc(const char* c, size_t l) { inline constexpr Arbutils::CaseInsensitiveConstString operator"" _cnc(const char* c, size_t l) {
return Arbutils::CaseInsensitiveConstString(c, l); return Arbutils::CaseInsensitiveConstString::Literal(c, l);
} }
#endif // ARBUTILS_CONSTSTRING_HPP #endif // ARBUTILS_CONSTSTRING_HPP

View File

@ -11,7 +11,7 @@
namespace Arbutils { \ namespace Arbutils { \
class name { \ class name { \
private: \ private: \
const char* _str; \ char* _str; \
size_t _length; \ size_t _length; \
uint32_t _hash; \ uint32_t _hash; \
\ \
@ -19,12 +19,19 @@
\ \
inline static int constexpr Length(const char* str) { return *str ? 1 + Length(str + 1) : 0; } \ inline static int constexpr Length(const char* str) { return *str ? 1 + Length(str + 1) : 0; } \
\ \
constexpr explicit name(const char* str, size_t size, bool) \
: _str(const_cast<char*>(str)), _length(size), _hash(Hash(str)) {} \
\
public: \ public: \
constexpr name() : _str(""), _length(0), _hash(Hash("")){}; \ explicit name(const char* str, size_t size) : _str(nullptr), _length(size), _hash(Hash(str)) { \
constexpr explicit name(const char* str) : _str(str), _length(Length(str)), _hash(Hash(str)){}; \ _str = new char[size]; \
STDSTRINGCONSTEXPR explicit name(const std::string& str) \ strcpy(_str, 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)){}; \ name() : name("", 0){}; \
explicit name(const char* str) : name(str, Length(str)){}; \
explicit name(const std::string& str) : name(str.c_str(), str.size()){}; \
\
static constexpr inline name Literal(const char* str, size_t size) { return name(str, size, false); } \
\ \
[[nodiscard]] inline constexpr const char* c_str() const noexcept { return _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 std::string std_str() const { return std::string(_str, _length); } \

View File

@ -42,5 +42,23 @@ TEST_CASE("Use case insensitive const string in switch case", "[Utilities]") {
} }
} }
__attribute__((optnone))
static Arbutils::CaseInsensitiveConstString TestCreateConstString(){
char originalVal [6];
originalVal[0] = 'f';
originalVal[1] = 'o';
originalVal[2] = 'o';
originalVal[3] = 'b';
originalVal[4] = 'a';
originalVal[5] = 'r';
return Arbutils::CaseInsensitiveConstString(originalVal);
}
TEST_CASE("Out of scope char* doesn't lose reference", "[Utilities]") {
Arbutils::CaseInsensitiveConstString val = TestCreateConstString();
INFO(val.c_str());
REQUIRE(strcmp(val.c_str(), "foobar") == 0);
}
#endif #endif