refactor: use std::variant in tr_variant, pt 1: make tr_variant_string private (#5832)
This commit is contained in:
parent
8b801a276f
commit
c6e47c232e
|
@ -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*/)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue