refactor: tr_variant API update (#5998)

This commit is contained in:
Charles Kerr 2023-09-13 08:49:17 -05:00 committed by GitHub
parent 8234fe39d2
commit 9a82372e95
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 218 additions and 67 deletions

View File

@ -117,10 +117,11 @@ void tr_variant::Merge::operator()(tr_variant::Map const& src)
{
tgt_.val_.emplace<tr_variant::Map>();
}
auto* const tgt = tgt_.get_if<tr_variant::MapIndex>();
auto& tgt = *tgt_.get_if<tr_variant::MapIndex>();
tgt.reserve(std::size(tgt) + std::size(src));
for (auto const& [key, val] : src)
{
std::visit(Merge{ (*tgt)[key] }, val.val_);
std::visit(Merge{ tgt[key] }, val.val_);
}
}
@ -380,31 +381,38 @@ void tr_variantInitStr(tr_variant* initme, std::string_view value)
*initme = value;
}
void tr_variantInitList(tr_variant* initme, size_t reserve_count)
void tr_variantInitList(tr_variant* initme, size_t n_reserve)
{
auto vec = tr_variant::Vector{};
vec.reserve(reserve_count);
vec.reserve(n_reserve);
*initme = std::move(vec);
}
void tr_variantListReserve(tr_variant* const var, size_t count)
void tr_variantListReserve(tr_variant* const var, size_t n_reserve)
{
TR_ASSERT(var != nullptr);
TR_ASSERT(var->holds_alternative<tr_variant::Vector>());
if (auto* const vec = var != nullptr ? var->get_if<tr_variant::VectorIndex>() : nullptr; vec != nullptr)
{
vec->reserve(std::size(*vec) + count);
vec->reserve(std::size(*vec) + n_reserve);
}
}
void tr_variantInitDict(tr_variant* initme, size_t /*reserve_count*/)
void tr_variantInitDict(tr_variant* initme, size_t n_reserve)
{
*initme = tr_variant::Map{};
*initme = tr_variant::Map{ n_reserve };
}
void tr_variantDictReserve(tr_variant* const /*var*/, size_t /*reserve_count*/)
void tr_variantDictReserve(tr_variant* const var, size_t n_reserve)
{
TR_ASSERT(var != nullptr);
TR_ASSERT(var->holds_alternative<tr_variant::Map>());
if (auto* const map = var != nullptr ? var->get_if<tr_variant::MapIndex>() : nullptr; map != nullptr)
{
map->reserve(std::size(*map) + n_reserve);
}
}
tr_variant* tr_variantListAdd(tr_variant* const var)
@ -460,26 +468,26 @@ tr_variant* tr_variantListAddQuark(tr_variant* const var, tr_quark value)
return tr_variantListAddStrView(var, tr_quark_get_string_view(value));
}
tr_variant* tr_variantListAddRaw(tr_variant* const var, void const* value, size_t value_len)
tr_variant* tr_variantListAddRaw(tr_variant* const var, void const* value, size_t n_bytes)
{
auto* const child = tr_variantListAdd(var);
*child = std::string_view{ static_cast<char const*>(value), value_len };
*child = tr_variant::make_raw(value, n_bytes);
return child;
}
tr_variant* tr_variantListAddList(tr_variant* const var, size_t reserve_count)
tr_variant* tr_variantListAddList(tr_variant* const var, size_t n_reserve)
{
auto* const child = tr_variantListAdd(var);
auto vec = tr_variant::Vector{};
vec.reserve(reserve_count);
vec.reserve(n_reserve);
*child = std::move(vec);
return child;
}
tr_variant* tr_variantListAddDict(tr_variant* const var, size_t reserve_count)
tr_variant* tr_variantListAddDict(tr_variant* const var, size_t n_reserve)
{
auto* const child = tr_variantListAdd(var);
tr_variantInitDict(child, reserve_count);
tr_variantInitDict(child, n_reserve);
return child;
}
@ -544,25 +552,25 @@ tr_variant* tr_variantDictAddStrView(tr_variant* const var, tr_quark key, std::s
return child;
}
tr_variant* tr_variantDictAddRaw(tr_variant* const var, tr_quark key, void const* value, size_t len)
tr_variant* tr_variantDictAddRaw(tr_variant* const var, tr_quark key, void const* value, size_t n_bytes)
{
tr_variantDictRemove(var, key);
auto* const child = tr_variantDictAdd(var, key);
tr_variantInitRaw(child, value, len);
*child = tr_variant::make_raw(value, n_bytes);
return child;
}
tr_variant* tr_variantDictAddList(tr_variant* const var, tr_quark key, size_t reserve_count)
tr_variant* tr_variantDictAddList(tr_variant* const var, tr_quark key, size_t n_reserve)
{
auto* const child = tr_variantDictAdd(var, key);
tr_variantInitList(child, reserve_count);
tr_variantInitList(child, n_reserve);
return child;
}
tr_variant* tr_variantDictAddDict(tr_variant* const var, tr_quark key, size_t reserve_count)
tr_variant* tr_variantDictAddDict(tr_variant* const var, tr_quark key, size_t n_reserve)
{
auto* const child = tr_variantDictAdd(var, key);
tr_variantInitDict(child, reserve_count);
tr_variantInitDict(child, n_reserve);
return child;
}

View File

@ -8,16 +8,16 @@
#include <algorithm> // std::move()
#include <cstddef> // size_t
#include <cstdint> // int64_t
#include <map>
#include <optional>
#include <string>
#include <string_view>
#include <type_traits> // std::is_same_v
#include <utility> // std::as_const, std::pair
#include <utility> // std::pair
#include <variant>
#include <vector>
#include "libtransmission/quark.h"
#include "libtransmission/tr-macros.h" // TR_CONSTEXPR20
struct tr_error;
@ -43,7 +43,126 @@ public:
};
using Vector = std::vector<tr_variant>;
using Map = std::map<tr_quark, tr_variant>;
class Map
{
public:
Map(size_t const n_reserve = 0U)
{
vec_.reserve(n_reserve);
}
[[nodiscard]] TR_CONSTEXPR20 auto begin() noexcept
{
return std::begin(vec_);
}
[[nodiscard]] TR_CONSTEXPR20 auto begin() const noexcept
{
return std::cbegin(vec_);
}
[[nodiscard]] TR_CONSTEXPR20 auto cbegin() const noexcept
{
return std::cbegin(vec_);
}
[[nodiscard]] TR_CONSTEXPR20 auto end() noexcept
{
return std::end(vec_);
}
[[nodiscard]] TR_CONSTEXPR20 auto end() const noexcept
{
return std::cend(vec_);
}
[[nodiscard]] TR_CONSTEXPR20 auto cend() const noexcept
{
return std::cend(vec_);
}
[[nodiscard]] TR_CONSTEXPR20 auto find(tr_quark const key) noexcept
{
return std::find_if(begin(), end(), [key](auto const& item) { return item.first == key; });
}
[[nodiscard]] TR_CONSTEXPR20 auto find(tr_quark const key) const noexcept
{
return std::find_if(begin(), end(), [key](auto const& item) { return item.first == key; });
}
[[nodiscard]] TR_CONSTEXPR20 auto size() const noexcept
{
return std::size(vec_);
}
[[nodiscard]] TR_CONSTEXPR20 auto empty() const noexcept
{
return std::empty(vec_);
}
void reserve(size_t new_cap)
{
vec_.reserve(new_cap);
}
auto erase(tr_quark const key)
{
if (auto iter = find(key); iter != end())
{
vec_.erase(iter);
return 1U;
}
return 0U;
}
[[nodiscard]] tr_variant& operator[](tr_quark const& key)
{
if (auto const iter = find(key); iter != end())
{
return iter->second;
}
return vec_.emplace_back(key, tr_variant{}).second;
}
template<typename Val>
std::pair<tr_variant&, bool> try_emplace(tr_quark const key, Val&& val)
{
if (auto iter = find(key); iter != end())
{
return { iter->second, false };
}
return { vec_.emplace_back(key, tr_variant{ std::move(val) }).second, true };
}
// --- custom functions
template<typename Type>
[[nodiscard]] TR_CONSTEXPR20 auto TR_CONSTEXPR20 find_if(tr_quark const key) const noexcept
{
auto const iter = find(key);
return iter != end() ? iter->second.get_if<Type>() : nullptr;
}
template<typename Type>
[[nodiscard]] TR_CONSTEXPR20 std::optional<Type> value_if(tr_quark const key) const noexcept
{
if (auto const* const value = find_if<Type>(key); value != nullptr)
{
return std::optional<Type>{ *value };
}
return {};
}
private:
using Vector = std::vector<std::pair<tr_quark, tr_variant>>;
Vector vec_;
};
constexpr tr_variant() noexcept = default;
tr_variant(tr_variant const&) = delete;
@ -51,23 +170,66 @@ public:
tr_variant& operator=(tr_variant const&) = delete;
tr_variant& operator=(tr_variant&& that) noexcept = default;
[[nodiscard]] static auto make_map() noexcept
{
auto ret = tr_variant{};
ret.val_.emplace<Map>();
return ret;
}
template<typename Val>
tr_variant(Val value)
{
*this = std::move(value);
}
[[nodiscard]] static auto make_map(size_t const n_reserve = 0U) noexcept
{
auto ret = tr_variant{};
ret.val_.emplace<Map>(n_reserve);
return ret;
}
[[nodiscard]] static auto make_vector(size_t const n_reserve = 0U)
{
auto ret = tr_variant{};
ret.val_.emplace<Vector>().reserve(n_reserve);
return ret;
}
[[nodiscard]] static auto make_raw(void const* value, size_t n_bytes)
{
return tr_variant{ std::string{ static_cast<char const*>(value), n_bytes } };
}
template<typename CharSpan>
[[nodiscard]] static auto make_raw(CharSpan const& value)
{
static_assert(sizeof(CharSpan::value_type) == 1U);
return make_raw(std::data(value), std::size(value));
}
[[nodiscard]] static tr_variant unmanaged_string(std::string_view val)
{
auto ret = tr_variant{};
ret.val_.emplace<StringHolder>().set_unmanaged(val);
return ret;
}
template<typename Val>
tr_variant& operator=(Val value)
{
val_ = std::move(value);
if constexpr (std::is_same_v<Val, std::string_view>)
{
val_.emplace<StringHolder>(std::string{ value });
}
// note: std::is_integral_v<bool> is true, so this check
// must come first to prevent bools from being stored as ints
else if constexpr (std::is_same_v<Val, bool>)
{
val_.emplace<bool>(value);
}
else if constexpr (std::is_integral_v<Val> || std::is_enum_v<Val>)
{
val_ = static_cast<int64_t>(value);
}
else
{
val_ = std::move(value);
}
return *this;
}
@ -79,25 +241,13 @@ public:
tr_variant& operator=(std::string const& value)
{
val_.emplace<StringHolder>(std::string(value));
*this = std::string{ value };
return *this;
}
tr_variant& operator=(std::string_view value)
tr_variant& operator=(char const* const value)
{
val_.emplace<StringHolder>(std::string(value));
return *this;
}
tr_variant& operator=(int value)
{
*this = static_cast<int64_t>(value);
return *this;
}
tr_variant& operator=(uint64_t value)
{
*this = static_cast<int64_t>(value); // hmmm
*this = std::string{ value != nullptr ? value : "" };
return *this;
}
@ -132,7 +282,7 @@ public:
}
template<size_t Index>
[[nodiscard]] auto* get_if() noexcept
[[nodiscard]] constexpr auto* get_if() noexcept
{
if constexpr (Index == StringIndex)
{
@ -151,13 +301,6 @@ public:
return const_cast<tr_variant*>(this)->get_if<Index>();
}
[[nodiscard]] static tr_variant unmanaged_string(std::string_view val)
{
auto ret = tr_variant{};
ret.val_.emplace<StringHolder>().set_unmanaged(val);
return ret;
}
template<typename Val>
[[nodiscard]] constexpr bool holds_alternative() const noexcept
{
@ -250,8 +393,8 @@ void tr_variantInitInt(tr_variant* initme, int64_t value);
// --- Lists
void tr_variantInitList(tr_variant* initme, size_t reserve_count);
void tr_variantListReserve(tr_variant* var, size_t reserve_count);
void tr_variantInitList(tr_variant* initme, size_t n_reserve);
void tr_variantListReserve(tr_variant* var, size_t n_reserve);
tr_variant* tr_variantListAdd(tr_variant* var);
tr_variant* tr_variantListAddBool(tr_variant* var, bool value);
@ -260,9 +403,9 @@ tr_variant* tr_variantListAddReal(tr_variant* var, double value);
tr_variant* tr_variantListAddStr(tr_variant* var, std::string_view value);
tr_variant* tr_variantListAddStrView(tr_variant* var, std::string_view value);
tr_variant* tr_variantListAddQuark(tr_variant* var, tr_quark value);
tr_variant* tr_variantListAddRaw(tr_variant* var, void const* value, size_t value_len);
tr_variant* tr_variantListAddList(tr_variant* var, size_t reserve_count);
tr_variant* tr_variantListAddDict(tr_variant* var, size_t reserve_count);
tr_variant* tr_variantListAddRaw(tr_variant* var, void const* value, size_t n_bytes);
tr_variant* tr_variantListAddList(tr_variant* var, size_t n_reserve);
tr_variant* tr_variantListAddDict(tr_variant* var, size_t n_reserve);
tr_variant* tr_variantListChild(tr_variant* var, size_t pos);
bool tr_variantListRemove(tr_variant* var, size_t pos);
@ -282,8 +425,8 @@ bool tr_variantListRemove(tr_variant* var, size_t pos);
// --- Dictionaries
void tr_variantInitDict(tr_variant* initme, size_t reserve_count);
void tr_variantDictReserve(tr_variant* var, size_t reserve_count);
void tr_variantInitDict(tr_variant* initme, size_t n_reserve);
void tr_variantDictReserve(tr_variant* var, size_t n_reserve);
bool tr_variantDictRemove(tr_variant* var, tr_quark key);
tr_variant* tr_variantDictAdd(tr_variant* var, tr_quark key);
@ -293,9 +436,9 @@ tr_variant* tr_variantDictAddBool(tr_variant* var, tr_quark key, bool value);
tr_variant* tr_variantDictAddStr(tr_variant* var, tr_quark key, std::string_view value);
tr_variant* tr_variantDictAddStrView(tr_variant* var, tr_quark key, std::string_view value);
tr_variant* tr_variantDictAddQuark(tr_variant* var, tr_quark key, tr_quark val);
tr_variant* tr_variantDictAddList(tr_variant* var, tr_quark key, size_t reserve_count);
tr_variant* tr_variantDictAddDict(tr_variant* var, tr_quark key, size_t reserve_count);
tr_variant* tr_variantDictAddRaw(tr_variant* var, tr_quark key, void const* value, size_t len);
tr_variant* tr_variantDictAddList(tr_variant* var, tr_quark key, size_t n_reserve);
tr_variant* tr_variantDictAddDict(tr_variant* var, tr_quark key, size_t n_reserve);
tr_variant* tr_variantDictAddRaw(tr_variant* var, tr_quark key, void const* value, size_t n_bytes);
bool tr_variantDictChild(tr_variant* var, size_t pos, tr_quark* setme_key, tr_variant** setme_value);
tr_variant* tr_variantDictFind(tr_variant* var, tr_quark key);
@ -321,12 +464,12 @@ class tr_variant_serde
public:
~tr_variant_serde();
static tr_variant_serde benc() noexcept
[[nodiscard]] static tr_variant_serde benc() noexcept
{
return tr_variant_serde{ Type::Benc };
}
static tr_variant_serde json() noexcept
[[nodiscard]] static tr_variant_serde json() noexcept
{
return tr_variant_serde{ Type::Json };
}