From d6b7344ddee1f79e58eff8687b6558636483e9ae Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Mon, 13 Apr 2020 13:59:43 +0200 Subject: [PATCH] Limit amount of copies of ConstString by implementing reference counter. --- src/ConstString.hpp | 17 ++++++++++++++++- src/__ConstStringCore.hpp | 33 +++++++++++++++++++-------------- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/ConstString.hpp b/src/ConstString.hpp index 0b58616..62070c7 100644 --- a/src/ConstString.hpp +++ b/src/ConstString.hpp @@ -1,19 +1,34 @@ #ifndef ARBUTILS_CONSTSTRING_HPP #define ARBUTILS_CONSTSTRING_HPP +#include #include #include #include #include #include "__ConstStringCore.hpp" +namespace Arbutils { + struct __ConstStringCharHolder { + char* Value; + std::atomic References; + + __ConstStringCharHolder(const char* value, size_t size) : Value(new char[size + 1]), References(0) { + strncpy(Value, value, size + 1); + } + + ~__ConstStringCharHolder() { delete[] Value; } + }; +} + ConstStringCore( ConstString, inline static uint32_t constexpr Hash(char const* input) { return (*input) ? static_cast((*input)) + 33 * Hash(input + 1) : 5381; };) -inline constexpr Arbutils::ConstString_Literal operator"" _const(const char* c, size_t l) { + inline constexpr Arbutils::ConstString_Literal + operator"" _const(const char* c, size_t l) { return Arbutils::ConstString_Literal(c, l); } inline constexpr Arbutils::ConstString_Literal operator"" _c(const char* c, size_t l) { diff --git a/src/__ConstStringCore.hpp b/src/__ConstStringCore.hpp index cd3ef4f..c28be2c 100644 --- a/src/__ConstStringCore.hpp +++ b/src/__ConstStringCore.hpp @@ -11,7 +11,7 @@ namespace Arbutils { \ class name { \ private: \ - char* _str; \ + __ConstStringCharHolder* _str; \ size_t _length; \ uint32_t _hash; \ \ @@ -19,32 +19,37 @@ \ inline static int constexpr Length(const char* str) { return *str ? 1 + Length(str + 1) : 0; } \ \ - name(const char* str, size_t size, uint32_t hash) : _str(new char[size + 1]), _length(size), _hash(hash) { \ - strncpy(_str, str, size + 1); \ - } \ + name(const char* str, size_t size, uint32_t hash) \ + : _str(new __ConstStringCharHolder(str, size)), _length(size), _hash(hash) {} \ \ public: \ - name(const char* str, size_t size) : _str(new char[size + 1]), _length(size), _hash(Hash(str)) { \ - strncpy(_str, str, size + 1); \ + name(const char* str, size_t size) \ + : _str(new __ConstStringCharHolder(str, size)), _length(size), _hash(Hash(str)) { \ + _str->References++; \ } \ name() : name("", 0){}; \ explicit name(const char* str) : name(str, Length(str)){}; \ explicit name(const std::string& str) : name(str.c_str(), str.size()){}; \ - \ - name(const name& other) : name(other._str, other._length, other._hash) {} \ + name(const name& other) : _str(other._str), _length(other._length), _hash(other._hash) { \ + _str->References++; \ + } \ name& operator=(const name& other) { \ - delete[] _str; \ - _str = new char[other._length + 1]; \ - strncpy(_str, other._str, other._length + 1); \ + if (--_str->References == 0) \ + delete _str; \ + _str = other._str; \ + _str->References++; \ _length = other._length; \ _hash = other._hash; \ return *this; \ } \ \ - ~name() { delete[] _str; } \ + ~name() { \ + if (--_str->References == 0) \ + delete _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 const char* c_str() const noexcept { return _str->Value; } \ + [[nodiscard]] inline std::string std_str() const { return std::string(_str->Value, _length); } \ \ [[nodiscard]] inline constexpr size_t Length() const noexcept { return _length; } \ \