From 6b4d18f43447b7bce5e5236faa11b5742ba320ea Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Tue, 7 Apr 2020 18:54:23 +0200 Subject: [PATCH] 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. --- src/ConstString.hpp | 10 ++++++---- src/__ConstStringCore.hpp | 19 +++++++++++++------ tests/ConstStringTests.cpp | 18 ++++++++++++++++++ 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/ConstString.hpp b/src/ConstString.hpp index cf979d5..ce45b47 100644 --- a/src/ConstString.hpp +++ b/src/ConstString.hpp @@ -15,9 +15,11 @@ ConstStringCore( inline constexpr Arbutils::ConstString 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( CaseInsensitiveConstString, @@ -28,10 +30,10 @@ ConstStringCore( };); 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) { - return Arbutils::CaseInsensitiveConstString(c, l); + return Arbutils::CaseInsensitiveConstString::Literal(c, l); } #endif // ARBUTILS_CONSTSTRING_HPP diff --git a/src/__ConstStringCore.hpp b/src/__ConstStringCore.hpp index 814fdf6..abdab50 100644 --- a/src/__ConstStringCore.hpp +++ b/src/__ConstStringCore.hpp @@ -11,7 +11,7 @@ namespace Arbutils { \ class name { \ private: \ - const char* _str; \ + char* _str; \ size_t _length; \ uint32_t _hash; \ \ @@ -19,12 +19,19 @@ \ 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(str)), _length(size), _hash(Hash(str)) {} \ + \ 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)){}; \ + explicit name(const char* str, size_t size) : _str(nullptr), _length(size), _hash(Hash(str)) { \ + _str = new char[size]; \ + strcpy(_str, 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 std::string std_str() const { return std::string(_str, _length); } \ diff --git a/tests/ConstStringTests.cpp b/tests/ConstStringTests.cpp index a4a4653..7596c46 100644 --- a/tests/ConstStringTests.cpp +++ b/tests/ConstStringTests.cpp @@ -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 \ No newline at end of file