From c6e47c232e278362a85261a6e0a96ffe080cdedf Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 28 Jul 2023 16:14:31 -0500 Subject: [PATCH] refactor: use std::variant in tr_variant, pt 1: make tr_variant_string private (#5832) --- libtransmission/variant.cc | 124 +++++++------------------------------ libtransmission/variant.h | 102 ++++++++++++++++++++---------- 2 files changed, 93 insertions(+), 133 deletions(-) diff --git a/libtransmission/variant.cc b/libtransmission/variant.cc index 8de3f3b00..0b443d326 100644 --- a/libtransmission/variant.cc +++ b/libtransmission/variant.cc @@ -37,88 +37,6 @@ constexpr bool tr_variantIsContainer(tr_variant const* v) // --- -auto constexpr StringInit = tr_variant_string{ - TR_STRING_TYPE_QUARK, - 0, - {}, -}; - -void tr_variant_string_clear(struct tr_variant_string* str) -{ - if (str->type == TR_STRING_TYPE_HEAP) - { - delete[] const_cast(str->str.str); - } - - *str = StringInit; -} - -/* returns a const pointer to the variant's string */ -constexpr char const* tr_variant_string_get_string(struct tr_variant_string const* str) -{ - switch (str->type) - { - case TR_STRING_TYPE_BUF: - return str->str.buf; - - case TR_STRING_TYPE_HEAP: - case TR_STRING_TYPE_QUARK: - case TR_STRING_TYPE_VIEW: - return str->str.str; - - default: - return nullptr; - } -} - -void tr_variant_string_set_quark(struct tr_variant_string* str, tr_quark quark) -{ - tr_variant_string_clear(str); - - str->type = TR_STRING_TYPE_QUARK; - auto const sv = tr_quark_get_string_view(quark); - str->str.str = std::data(sv); - str->len = std::size(sv); -} - -void tr_variant_string_set_string(struct tr_variant_string* str, std::string_view in) -{ - tr_variant_string_clear(str); - - auto const* const bytes = std::data(in); - auto const len = std::size(in); - - if (len < sizeof(str->str.buf)) - { - str->type = TR_STRING_TYPE_BUF; - if (len > 0) - { - std::copy_n(bytes, len, str->str.buf); - } - - str->str.buf[len] = '\0'; - str->len = len; - } - else - { - auto* tmp = new char[len + 1]; - std::copy_n(bytes, len, tmp); - tmp[len] = '\0'; - str->type = TR_STRING_TYPE_HEAP; - str->str.str = tmp; - str->len = len; - } -} - -// --- - -constexpr char const* getStr(tr_variant const* v) -{ - TR_ASSERT(tr_variantIsString(v)); - - return tr_variant_string_get_string(&v->val.s); -} - constexpr int dictIndexOf(tr_variant const* dict, tr_quark key) { if (tr_variantIsDict(dict)) @@ -178,7 +96,7 @@ tr_variant* dictFindOrAdd(tr_variant* dict, tr_quark key, int type) } else if (child->type == TR_VARIANT_TYPE_STR) { - tr_variant_string_clear(&child->val.s); + child->val.s.clear(); } } @@ -262,36 +180,32 @@ bool tr_variantGetStrView(tr_variant const* v, std::string_view* setme) return false; } - char const* const str = tr_variant_string_get_string(&v->val.s); - size_t const len = v->val.s.len; - *setme = std::string_view{ str, len }; + *setme = v->val.s.get(); return true; } bool tr_variantGetRaw(tr_variant const* v, std::byte const** setme_raw, size_t* setme_len) { - bool const success = tr_variantIsString(v); - - if (success) + if (auto sv = std::string_view{}; tr_variantGetStrView(v, &sv)) { - *setme_raw = reinterpret_cast(getStr(v)); - *setme_len = v->val.s.len; + *setme_raw = reinterpret_cast(std::data(sv)); + *setme_len = std::size(sv); + return true; } - return success; + return false; } bool tr_variantGetRaw(tr_variant const* v, uint8_t const** setme_raw, size_t* setme_len) { - bool const success = tr_variantIsString(v); - - if (success) + if (auto sv = std::string_view{}; tr_variantGetStrView(v, &sv)) { - *setme_raw = reinterpret_cast(getStr(v)); - *setme_len = v->val.s.len; + *setme_raw = reinterpret_cast(std::data(sv)); + *setme_len = std::size(sv); + return true; } - return success; + return false; } bool tr_variantGetBool(tr_variant const* v, bool* setme) @@ -405,22 +319,28 @@ bool tr_variantDictFindRaw(tr_variant* dict, tr_quark key, std::byte const** set // --- +void tr_variantInitStrView(tr_variant* initme, std::string_view val) +{ + tr_variantInit(initme, TR_VARIANT_TYPE_STR); + initme->val.s.set_shallow(val); +} + void tr_variantInitRaw(tr_variant* initme, void const* value, size_t value_len) { tr_variantInit(initme, TR_VARIANT_TYPE_STR); - tr_variant_string_set_string(&initme->val.s, { static_cast(value), value_len }); + initme->val.s.set({ static_cast(value), value_len }); } void tr_variantInitQuark(tr_variant* initme, tr_quark value) { tr_variantInit(initme, TR_VARIANT_TYPE_STR); - tr_variant_string_set_quark(&initme->val.s, value); + initme->val.s.set_shallow(tr_quark_get_string_view(value)); } void tr_variantInitStr(tr_variant* initme, std::string_view value) { tr_variantInit(initme, TR_VARIANT_TYPE_STR); - tr_variant_string_set_string(&initme->val.s, value); + initme->val.s.set(value); } void tr_variantInitList(tr_variant* initme, size_t reserve_count) @@ -877,7 +797,7 @@ void freeDummyFunc(tr_variant const* /*v*/, void* /*buf*/) void freeStringFunc(tr_variant const* v, void* /*user_data*/) { - tr_variant_string_clear(&const_cast(v)->val.s); + const_cast(v)->val.s.clear(); } void freeContainerEndFunc(tr_variant const* v, void* /*user_data*/) diff --git a/libtransmission/variant.h b/libtransmission/variant.h index f376ad24f..b2a2280d5 100644 --- a/libtransmission/variant.h +++ b/libtransmission/variant.h @@ -5,6 +5,7 @@ #pragma once +#include #include // size_t #include // int64_t #include @@ -27,28 +28,6 @@ struct tr_error; * @{ */ -enum tr_string_type -{ - TR_STRING_TYPE_QUARK, - TR_STRING_TYPE_HEAP, - TR_STRING_TYPE_BUF, - TR_STRING_TYPE_VIEW -}; - -/* these are PRIVATE IMPLEMENTATION details that should not be touched. - * I'll probably change them just to break your code! HA HA HA! - * it's included in the header for inlining and composition */ -struct tr_variant_string -{ - tr_string_type type; - size_t len; - union - { - char buf[16]; - char const* str; - } str; -}; - /* these are PRIVATE IMPLEMENTATION details that should not be touched. * I'll probably change them just to break your code! HA HA HA! * it's included in the header for inlining and composition */ @@ -67,6 +46,74 @@ enum * it's included in the header for inlining and composition */ struct tr_variant { +private: + struct String + { + void set_shallow(std::string_view newval) + { + clear(); + + type_ = Type::View; + str_.str = std::data(newval); + len_ = std::size(newval); + } + + void set(std::string_view newval) + { + clear(); + + len_ = std::size(newval); + + if (len_ < sizeof(str_.buf)) + { + type_ = Type::Buf; + std::copy_n(std::data(newval), len_, str_.buf); + str_.buf[len_] = '\0'; + } + else + { + char* const newstr = new char[len_ + 1]; + std::copy_n(std::data(newval), len_, newstr); + newstr[len_] = '\0'; + + type_ = Type::Heap; + str_.str = newstr; + } + } + + [[nodiscard]] constexpr std::string_view get() const noexcept + { + return { type_ == Type::Buf ? str_.buf : str_.str, len_ }; + } + + void clear() + { + if (type_ == Type::Heap) + { + delete[] str_.str; + } + + *this = {}; + } + + private: + enum class Type + { + Heap, + Buf, + View + }; + + Type type_ = Type::View; + size_t len_ = 0U; + union + { + char buf[16]; + char const* str; + } str_ = {}; + }; + +public: char type = '\0'; tr_quark key = TR_KEY_NONE; @@ -79,7 +126,7 @@ struct tr_variant int64_t i; - struct tr_variant_string s; + String s; struct { @@ -171,6 +218,7 @@ bool tr_variantGetStrView(tr_variant const* variant, std::string_view* setme); void tr_variantInitStr(tr_variant* initme, std::string_view value); void tr_variantInitQuark(tr_variant* initme, tr_quark value); void tr_variantInitRaw(tr_variant* initme, void const* value, size_t value_len); +void tr_variantInitStrView(tr_variant* initme, std::string_view val); constexpr void tr_variantInit(tr_variant* initme, char type) { @@ -178,14 +226,6 @@ constexpr void tr_variantInit(tr_variant* initme, char type) initme->type = type; } -constexpr void tr_variantInitStrView(tr_variant* initme, std::string_view in) -{ - tr_variantInit(initme, TR_VARIANT_TYPE_STR); - initme->val.s.type = TR_STRING_TYPE_VIEW; - initme->val.s.len = std::size(in); - initme->val.s.str.str = std::data(in); -} - bool tr_variantGetRaw(tr_variant const* variant, std::byte const** setme_raw, size_t* setme_len); bool tr_variantGetRaw(tr_variant const* variant, uint8_t const** setme_raw, size_t* setme_len);