refactor: use std::variant in tr_variant, pt 1: make tr_variant_string private (#5832)

This commit is contained in:
Charles Kerr 2023-07-28 16:14:31 -05:00 committed by GitHub
parent 8b801a276f
commit c6e47c232e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 93 additions and 133 deletions

View File

@ -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<char*>(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<std::byte const*>(getStr(v));
*setme_len = v->val.s.len;
*setme_raw = reinterpret_cast<std::byte const*>(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<uint8_t const*>(getStr(v));
*setme_len = v->val.s.len;
*setme_raw = reinterpret_cast<uint8_t const*>(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<char const*>(value), value_len });
initme->val.s.set({ static_cast<char const*>(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<tr_variant*>(v)->val.s);
const_cast<tr_variant*>(v)->val.s.clear();
}
void freeContainerEndFunc(tr_variant const* v, void* /*user_data*/)

View File

@ -5,6 +5,7 @@
#pragma once
#include <algorithm>
#include <cstddef> // size_t
#include <cstdint> // int64_t
#include <optional>
@ -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);