Limit amount of copies of ConstString by implementing reference counter.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
978fa70473
commit
d6b7344dde
|
@ -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) {
|
||||||
|
|
|
@ -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; } \
|
||||||
\
|
\
|
||||||
|
|
Loading…
Reference in New Issue