1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2025-02-22 14:10:34 +00:00

refactor: variant fixups (#1811)

* cleanups to the previous variant commit
This commit is contained in:
Charles Kerr 2021-09-15 17:11:00 -05:00 committed by GitHub
parent de4634f0a5
commit c80fb5f6e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -17,6 +17,7 @@
#include <algorithm> // std::sort
#include <errno.h>
#include <stack>
#include <stdlib.h> /* strtod() */
#include <string.h>
#include <vector>
@ -741,14 +742,38 @@ bool tr_variantDictRemove(tr_variant* dict, tr_quark const key)
class WalkNode
{
public:
WalkNode(tr_variant const* v_in, bool sort_dicts)
: v{ *v_in }
{
if (sort_dicts && tr_variantIsDict(v_in))
{
sortByKey();
}
}
tr_variant const* nextChild()
{
if (!tr_variantIsContainer(&v) || (child_index >= v.val.l.count))
{
return nullptr;
}
auto idx = child_index++;
if (!sorted.empty())
{
idx = sorted[idx];
}
return v.val.l.vals + idx;
}
bool is_visited = false;
// Shallow bitwise copy of the variant passed to the constructor
tr_variant const v = {};
private:
// When walking `v`'s children, this is the index of the next child
size_t child_index = 0;
// When `v` is a dict, this is its children's indices sorted by key.
// Bencoded dicts must be sorted, so this is useful when writing benc.
std::vector<size_t> sorted;
void sortByKey()
{
auto const n = v.val.l.count;
@ -766,11 +791,7 @@ private:
tmp[i] = { tr_quark_get_string(children[i].key, nullptr), i };
}
auto const compare = [](ByKey const& a, ByKey const& b)
{
return strcmp(a.key, b.key) < 0;
};
std::sort(std::begin(tmp), std::end(tmp), compare);
std::sort(std::begin(tmp), std::end(tmp), [](ByKey const& a, ByKey const& b) { return strcmp(a.key, b.key) < 0; });
// keep the sorted indices
@ -781,36 +802,12 @@ private:
}
}
public:
bool is_visited = false;
// When walking `v`'s children, this is the index of the next child
size_t child_index = 0;
// Shallow bitwise copy of the variant passed to the constructor
tr_variant const v = {};
WalkNode(tr_variant const* v_in, bool sort_dicts)
: v{ *v_in }
{
if (sort_dicts && tr_variantIsDict(v_in))
{
sortByKey();
}
}
tr_variant const* nextChild()
{
if (child_index >= v.val.l.count)
{
return nullptr;
}
auto idx = child_index++;
if (!sorted.empty())
{
idx = sorted[idx];
}
return v.val.l.vals + idx;
}
// When `v` is a dict, this is its children's indices sorted by key.
// Bencoded dicts must be sorted, so this is useful when writing benc.
std::vector<size_t> sorted;
};
/**
@ -820,12 +817,12 @@ public:
*/
void tr_variantWalk(tr_variant const* v_in, struct VariantWalkFuncs const* walkFuncs, void* user_data, bool sort_dicts)
{
auto stack = std::vector<WalkNode>{};
stack.emplace_back(v_in, sort_dicts);
auto stack = std::stack<WalkNode>{};
stack.emplace(v_in, sort_dicts);
while (!stack.empty())
{
auto& node = stack.back();
auto& node = stack.top();
tr_variant const* v;
if (!node.is_visited)
@ -833,7 +830,7 @@ void tr_variantWalk(tr_variant const* v_in, struct VariantWalkFuncs const* walkF
v = &node.v;
node.is_visited = true;
}
else if (tr_variantIsContainer(&node.v) && ((v = node.nextChild())))
else if ((v = node.nextChild()) != nullptr)
{
if (tr_variantIsDict(&node.v))
{
@ -849,7 +846,7 @@ void tr_variantWalk(tr_variant const* v_in, struct VariantWalkFuncs const* walkF
walkFuncs->containerEndFunc(&node.v, user_data);
}
stack.pop_back();
stack.pop();
continue;
}
@ -880,7 +877,7 @@ void tr_variantWalk(tr_variant const* v_in, struct VariantWalkFuncs const* walkF
}
else
{
stack.emplace_back(v, sort_dicts);
stack.emplace(v, sort_dicts);
}
break;
@ -891,7 +888,7 @@ void tr_variantWalk(tr_variant const* v_in, struct VariantWalkFuncs const* walkF
}
else
{
stack.emplace_back(v, sort_dicts);
stack.emplace(v, sort_dicts);
}
break;