Limit amount of copies of ConstString by implementing reference counter.
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2020-04-13 13:59:43 +02:00
parent 978fa70473
commit d6b7344dde
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
2 changed files with 35 additions and 15 deletions

View File

@ -1,19 +1,34 @@
#ifndef ARBUTILS_CONSTSTRING_HPP #ifndef ARBUTILS_CONSTSTRING_HPP
#define ARBUTILS_CONSTSTRING_HPP #define ARBUTILS_CONSTSTRING_HPP
#include <atomic>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include <string> #include <string>
#include "__ConstStringCore.hpp" #include "__ConstStringCore.hpp"
namespace Arbutils {
struct __ConstStringCharHolder {
char* Value;
std::atomic<size_t> References;
__ConstStringCharHolder(const char* value, size_t size) : Value(new char[size + 1]), References(0) {
strncpy(Value, value, size + 1);
}
~__ConstStringCharHolder() { delete[] Value; }
};
}
ConstStringCore( ConstStringCore(
ConstString, ConstString,
inline static uint32_t constexpr Hash(char const* input) { inline static uint32_t constexpr Hash(char const* input) {
return (*input) ? static_cast<uint32_t>((*input)) + 33 * Hash(input + 1) : 5381; return (*input) ? static_cast<uint32_t>((*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); return Arbutils::ConstString_Literal(c, l);
} }
inline constexpr Arbutils::ConstString_Literal operator"" _c(const char* c, size_t l) { inline constexpr Arbutils::ConstString_Literal operator"" _c(const char* c, size_t l) {

View File

@ -11,7 +11,7 @@
namespace Arbutils { \ namespace Arbutils { \
class name { \ class name { \
private: \ private: \
char* _str; \ __ConstStringCharHolder* _str; \
size_t _length; \ size_t _length; \
uint32_t _hash; \ uint32_t _hash; \
\ \
@ -19,32 +19,37 @@
\ \
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; } \
\ \
name(const char* str, size_t size, uint32_t hash) : _str(new char[size + 1]), _length(size), _hash(hash) { \ name(const char* str, size_t size, uint32_t hash) \
strncpy(_str, str, size + 1); \ : _str(new __ConstStringCharHolder(str, size)), _length(size), _hash(hash) {} \
} \
\ \
public: \ public: \
name(const char* str, size_t size) : _str(new char[size + 1]), _length(size), _hash(Hash(str)) { \ name(const char* str, size_t size) \
strncpy(_str, str, size + 1); \ : _str(new __ConstStringCharHolder(str, size)), _length(size), _hash(Hash(str)) { \
_str->References++; \
} \ } \
name() : name("", 0){}; \ name() : name("", 0){}; \
explicit name(const char* str) : name(str, Length(str)){}; \ explicit name(const char* str) : name(str, Length(str)){}; \
explicit name(const std::string& str) : name(str.c_str(), str.size()){}; \ explicit name(const std::string& str) : name(str.c_str(), str.size()){}; \
\ name(const name& other) : _str(other._str), _length(other._length), _hash(other._hash) { \
name(const name& other) : name(other._str, other._length, other._hash) {} \ _str->References++; \
} \
name& operator=(const name& other) { \ name& operator=(const name& other) { \
delete[] _str; \ if (--_str->References == 0) \
_str = new char[other._length + 1]; \ delete _str; \
strncpy(_str, other._str, other._length + 1); \ _str = other._str; \
_str->References++; \
_length = other._length; \ _length = other._length; \
_hash = other._hash; \ _hash = other._hash; \
return *this; \ 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 constexpr const char* c_str() const noexcept { return _str->Value; } \
[[nodiscard]] inline std::string std_str() const { return std::string(_str, _length); } \ [[nodiscard]] inline std::string std_str() const { return std::string(_str->Value, _length); } \
\ \
[[nodiscard]] inline constexpr size_t Length() const noexcept { return _length; } \ [[nodiscard]] inline constexpr size_t Length() const noexcept { return _length; } \
\ \