mirror of
https://github.com/matrix-construct/construct
synced 2024-11-17 15:30:52 +01:00
ircd:Ⓜ️:state: Add branch accounting to b-tree node.
This commit is contained in:
parent
bc7efd8bff
commit
4643a78c47
2 changed files with 209 additions and 15 deletions
|
@ -60,6 +60,9 @@ namespace ircd::m::state
|
||||||
bool dfs(const id &root, const json::array &key, const search_closure &);
|
bool dfs(const id &root, const json::array &key, const search_closure &);
|
||||||
bool dfs(const id &root, const search_closure &);
|
bool dfs(const id &root, const search_closure &);
|
||||||
|
|
||||||
|
size_t count(const id &root, const string_view &type);
|
||||||
|
size_t count(const id &root);
|
||||||
|
|
||||||
bool test(const id &root, const iter_bool_closure &);
|
bool test(const id &root, const iter_bool_closure &);
|
||||||
bool test(const id &root, const string_view &type, const iter_bool_closure &);
|
bool test(const id &root, const string_view &type, const iter_bool_closure &);
|
||||||
bool test(const id &root, const string_view &type, const string_view &state_key_lb, const iter_bool_closure &);
|
bool test(const id &root, const string_view &type, const string_view &state_key_lb, const iter_bool_closure &);
|
||||||
|
@ -67,8 +70,7 @@ namespace ircd::m::state
|
||||||
void for_each(const id &root, const iter_closure &);
|
void for_each(const id &root, const iter_closure &);
|
||||||
void for_each(const id &root, const string_view &type, const iter_closure &);
|
void for_each(const id &root, const string_view &type, const iter_closure &);
|
||||||
|
|
||||||
size_t count(const id &root, const iter_bool_closure &);
|
size_t accumulate(const id &root, const iter_bool_closure &);
|
||||||
size_t count(const id &root);
|
|
||||||
|
|
||||||
bool get(std::nothrow_t, const id &root, const json::array &key, const val_closure &);
|
bool get(std::nothrow_t, const id &root, const json::array &key, const val_closure &);
|
||||||
void get(const id &root, const json::array &key, const val_closure &);
|
void get(const id &root, const json::array &key, const val_closure &);
|
||||||
|
@ -83,6 +85,7 @@ namespace ircd::m::state::name
|
||||||
constexpr const char *const k {"k"};
|
constexpr const char *const k {"k"};
|
||||||
constexpr const char *const v {"v"};
|
constexpr const char *const v {"v"};
|
||||||
constexpr const char *const c {"c"};
|
constexpr const char *const c {"c"};
|
||||||
|
constexpr const char *const n {"n"};
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
|
@ -110,6 +113,12 @@ namespace ircd::m::state::name
|
||||||
/// "PcxAAACvkvyUMz19AZcCfrC3S84s", ; Center child
|
/// "PcxAAACvkvyUMz19AZcCfrC3S84s", ; Center child
|
||||||
/// "2jVYKIMKErJ6w6BLMhfVjsXearhB", ; Right child
|
/// "2jVYKIMKErJ6w6BLMhfVjsXearhB", ; Right child
|
||||||
/// ] ;
|
/// ] ;
|
||||||
|
/// "n": ; Counting array
|
||||||
|
/// [ ;
|
||||||
|
/// 15, ; Left child value count
|
||||||
|
/// 12, ; Center child value count
|
||||||
|
/// 19, ; Right child value count
|
||||||
|
/// ] ;
|
||||||
/// } ;
|
/// } ;
|
||||||
///
|
///
|
||||||
/// Elements are ordered based on type+state_key lexical sort. The type and
|
/// Elements are ordered based on type+state_key lexical sort. The type and
|
||||||
|
@ -130,7 +139,8 @@ struct ircd::m::state::node
|
||||||
<
|
<
|
||||||
json::property<name::k, json::array>,
|
json::property<name::k, json::array>,
|
||||||
json::property<name::v, json::array>,
|
json::property<name::v, json::array>,
|
||||||
json::property<name::c, json::array>
|
json::property<name::c, json::array>,
|
||||||
|
json::property<name::n, json::array>
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
struct rep;
|
struct rep;
|
||||||
|
@ -138,14 +148,18 @@ struct ircd::m::state::node
|
||||||
size_t keys() const;
|
size_t keys() const;
|
||||||
size_t vals() const;
|
size_t vals() const;
|
||||||
size_t childs() const;
|
size_t childs() const;
|
||||||
|
size_t counts() const;
|
||||||
|
size_t totals() const;
|
||||||
|
|
||||||
json::array key(const size_t &) const;
|
json::array key(const size_t &) const;
|
||||||
string_view val(const size_t &) const;
|
string_view val(const size_t &) const;
|
||||||
state::id child(const size_t &) const;
|
state::id child(const size_t &) const;
|
||||||
|
size_t count(const size_t &) const;
|
||||||
|
|
||||||
size_t keys(json::array *const &out, const size_t &max) const;
|
size_t keys(json::array *const &out, const size_t &max) const;
|
||||||
size_t vals(string_view *const &out, const size_t &max) const;
|
size_t vals(string_view *const &out, const size_t &max) const;
|
||||||
size_t childs(state::id *const &out, const size_t &max) const;
|
size_t childs(state::id *const &out, const size_t &max) const;
|
||||||
|
size_t counts(size_t *const &out, const size_t &max) const;
|
||||||
|
|
||||||
size_t find(const json::array &key) const;
|
size_t find(const json::array &key) const;
|
||||||
bool has_key(const json::array &key) const;
|
bool has_key(const json::array &key) const;
|
||||||
|
@ -168,16 +182,21 @@ struct ircd::m::state::node::rep
|
||||||
std::array<json::array, NODE_MAX_KEY + 1> keys;
|
std::array<json::array, NODE_MAX_KEY + 1> keys;
|
||||||
std::array<string_view, NODE_MAX_VAL + 1> vals;
|
std::array<string_view, NODE_MAX_VAL + 1> vals;
|
||||||
std::array<state::id, NODE_MAX_DEG + 1> chld;
|
std::array<state::id, NODE_MAX_DEG + 1> chld;
|
||||||
|
std::array<size_t, NODE_MAX_DEG + 1> cnts;
|
||||||
size_t kn {0};
|
size_t kn {0};
|
||||||
size_t vn {0};
|
size_t vn {0};
|
||||||
size_t cn {0};
|
size_t cn {0};
|
||||||
|
size_t nn {0};
|
||||||
|
|
||||||
bool full() const;
|
bool full() const;
|
||||||
bool overfull() const;
|
bool overfull() const;
|
||||||
bool duplicates() const;
|
bool duplicates() const;
|
||||||
size_t childs() const;
|
size_t childs() const;
|
||||||
|
size_t counts() const;
|
||||||
|
size_t totals() const;
|
||||||
size_t find(const json::array &key) const;
|
size_t find(const json::array &key) const;
|
||||||
|
|
||||||
|
void shl(const size_t &pos);
|
||||||
void shr(const size_t &pos);
|
void shr(const size_t &pos);
|
||||||
|
|
||||||
json::object write(const mutable_buffer &out);
|
json::object write(const mutable_buffer &out);
|
||||||
|
|
197
ircd/m/state.cc
197
ircd/m/state.cc
|
@ -93,17 +93,7 @@ ircd::m::state::get(std::nothrow_t,
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
ircd::m::state::count(const string_view &root)
|
ircd::m::state::accumulate(const string_view &root,
|
||||||
{
|
|
||||||
return count(root, []
|
|
||||||
(const json::array &key, const string_view &val)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
|
||||||
ircd::m::state::count(const string_view &root,
|
|
||||||
const iter_bool_closure &closure)
|
const iter_bool_closure &closure)
|
||||||
{
|
{
|
||||||
size_t ret{0};
|
size_t ret{0};
|
||||||
|
@ -189,6 +179,83 @@ ircd::m::state::test(const string_view &root,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ircd::m::state
|
||||||
|
{
|
||||||
|
size_t _count_recurse(const node &, const json::array &key, const json::array &dom);
|
||||||
|
size_t _count(const string_view &root, const json::array &key);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
ircd::m::state::count(const string_view &root)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
ircd::m::state::count(const string_view &root,
|
||||||
|
const string_view &type)
|
||||||
|
{
|
||||||
|
char buf[KEY_MAX_SZ];
|
||||||
|
const json::array key
|
||||||
|
{
|
||||||
|
make_key(buf, type)
|
||||||
|
};
|
||||||
|
|
||||||
|
return _count(root, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
ircd::m::state::_count(const string_view &root,
|
||||||
|
const json::array &key)
|
||||||
|
{
|
||||||
|
size_t ret{0};
|
||||||
|
get_node(root, [&key, &ret]
|
||||||
|
(const auto &node)
|
||||||
|
{
|
||||||
|
ret += _count_recurse(node, key, json::array{});
|
||||||
|
});
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
ircd::m::state::_count_recurse(const node &node,
|
||||||
|
const json::array &key,
|
||||||
|
const json::array &dom)
|
||||||
|
{
|
||||||
|
const node::rep rep{node};
|
||||||
|
|
||||||
|
bool under{!empty(dom)};
|
||||||
|
for(uint pos(0); under && pos < rep.kn; ++pos)
|
||||||
|
if(!prefix_eq(dom, rep.keys[pos]))
|
||||||
|
under = false;
|
||||||
|
|
||||||
|
if(under)
|
||||||
|
return rep.totals();
|
||||||
|
|
||||||
|
size_t ret{0};
|
||||||
|
const auto kpos{rep.find(key)};
|
||||||
|
for(uint pos(kpos); pos < rep.kn || pos < rep.cn; ++pos)
|
||||||
|
{
|
||||||
|
if(!empty(rep.chld[pos]))
|
||||||
|
get_node(rep.chld[pos], [&key, &ret, &rep, &pos]
|
||||||
|
(const auto &node)
|
||||||
|
{
|
||||||
|
ret += _count_recurse(node, key, rep.keys[pos]);
|
||||||
|
});
|
||||||
|
|
||||||
|
if(pos < rep.kn)
|
||||||
|
{
|
||||||
|
if(prefix_eq(key, rep.keys[pos]))
|
||||||
|
++ret;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
namespace ircd::m::state
|
namespace ircd::m::state
|
||||||
{
|
{
|
||||||
bool _dfs_recurse(const search_closure &, const node &, const json::array &key, int &);
|
bool _dfs_recurse(const search_closure &, const node &, const json::array &key, int &);
|
||||||
|
@ -319,6 +386,8 @@ ircd::m::state::_create(db::txn &txn,
|
||||||
rep.vn = 1;
|
rep.vn = 1;
|
||||||
rep.chld[0] = string_view{};
|
rep.chld[0] = string_view{};
|
||||||
rep.cn = 1;
|
rep.cn = 1;
|
||||||
|
rep.cnts[0] = 0;
|
||||||
|
rep.nn = 1;
|
||||||
|
|
||||||
return set_node(txn, root, rep.write(node));
|
return set_node(txn, root, rep.write(node));
|
||||||
}
|
}
|
||||||
|
@ -414,6 +483,7 @@ ircd::m::state::_insert(int8_t &height,
|
||||||
|
|
||||||
// Indicates no push, and the child value is just an ID of a node.
|
// Indicates no push, and the child value is just an ID of a node.
|
||||||
rep.chld[pos] = child;
|
rep.chld[pos] = child;
|
||||||
|
rep.cnts[pos]++;
|
||||||
return rep.write(txn, idbuf);
|
return rep.write(txn, idbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,6 +507,10 @@ ircd::m::state::_insert_branch_full(const int8_t &height,
|
||||||
rep.chld[pos + 1] = pushed.chld[1];
|
rep.chld[pos + 1] = pushed.chld[1];
|
||||||
++rep.cn;
|
++rep.cn;
|
||||||
|
|
||||||
|
rep.cnts[pos] = pushed.cnts[0];
|
||||||
|
rep.cnts[pos + 1] = pushed.cnts[1];
|
||||||
|
++rep.nn;
|
||||||
|
|
||||||
size_t i(0);
|
size_t i(0);
|
||||||
node::rep left;
|
node::rep left;
|
||||||
for(; i < rep.kn / 2; ++i)
|
for(; i < rep.kn / 2; ++i)
|
||||||
|
@ -444,8 +518,10 @@ ircd::m::state::_insert_branch_full(const int8_t &height,
|
||||||
left.keys[left.kn++] = rep.keys[i];
|
left.keys[left.kn++] = rep.keys[i];
|
||||||
left.vals[left.vn++] = rep.vals[i];
|
left.vals[left.vn++] = rep.vals[i];
|
||||||
left.chld[left.cn++] = rep.chld[i];
|
left.chld[left.cn++] = rep.chld[i];
|
||||||
|
left.cnts[left.nn++] = rep.cnts[i];
|
||||||
}
|
}
|
||||||
left.chld[left.cn++] = rep.chld[i];
|
left.chld[left.cn++] = rep.chld[i];
|
||||||
|
left.cnts[left.nn++] = rep.cnts[i];
|
||||||
|
|
||||||
push.keys[push.kn++] = rep.keys[i];
|
push.keys[push.kn++] = rep.keys[i];
|
||||||
push.vals[push.vn++] = rep.vals[i];
|
push.vals[push.vn++] = rep.vals[i];
|
||||||
|
@ -456,12 +532,16 @@ ircd::m::state::_insert_branch_full(const int8_t &height,
|
||||||
right.keys[right.kn++] = rep.keys[i];
|
right.keys[right.kn++] = rep.keys[i];
|
||||||
right.vals[right.vn++] = rep.vals[i];
|
right.vals[right.vn++] = rep.vals[i];
|
||||||
right.chld[right.cn++] = rep.chld[i];
|
right.chld[right.cn++] = rep.chld[i];
|
||||||
|
right.cnts[right.nn++] = rep.cnts[i];
|
||||||
}
|
}
|
||||||
right.chld[right.cn++] = rep.chld[i];
|
right.chld[right.cn++] = rep.chld[i];
|
||||||
|
right.cnts[right.nn++] = rep.cnts[i];
|
||||||
|
|
||||||
thread_local char lc[ID_MAX_SZ], rc[ID_MAX_SZ];
|
thread_local char lc[ID_MAX_SZ], rc[ID_MAX_SZ];
|
||||||
push.chld[push.cn++] = left.write(txn, lc);
|
push.chld[push.cn++] = left.write(txn, lc);
|
||||||
push.chld[push.cn++] = right.write(txn, rc);
|
push.chld[push.cn++] = right.write(txn, rc);
|
||||||
|
push.cnts[push.nn++] = left.totals();
|
||||||
|
push.cnts[push.nn++] = right.totals();
|
||||||
|
|
||||||
const auto ret
|
const auto ret
|
||||||
{
|
{
|
||||||
|
@ -497,6 +577,7 @@ ircd::m::state::_insert_leaf_full(const int8_t &height,
|
||||||
left.keys[left.kn++] = rep.keys[i];
|
left.keys[left.kn++] = rep.keys[i];
|
||||||
left.vals[left.vn++] = rep.vals[i];
|
left.vals[left.vn++] = rep.vals[i];
|
||||||
left.chld[left.cn++] = string_view{};
|
left.chld[left.cn++] = string_view{};
|
||||||
|
left.cnts[left.nn++] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
push.keys[push.kn++] = rep.keys[i];
|
push.keys[push.kn++] = rep.keys[i];
|
||||||
|
@ -508,11 +589,14 @@ ircd::m::state::_insert_leaf_full(const int8_t &height,
|
||||||
right.keys[right.kn++] = rep.keys[i];
|
right.keys[right.kn++] = rep.keys[i];
|
||||||
right.vals[right.vn++] = rep.vals[i];
|
right.vals[right.vn++] = rep.vals[i];
|
||||||
right.chld[right.cn++] = string_view{};
|
right.chld[right.cn++] = string_view{};
|
||||||
|
right.cnts[right.nn++] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_local char lc[ID_MAX_SZ], rc[ID_MAX_SZ];
|
thread_local char lc[ID_MAX_SZ], rc[ID_MAX_SZ];
|
||||||
push.chld[push.cn++] = left.write(txn, lc);
|
push.chld[push.cn++] = left.write(txn, lc);
|
||||||
push.chld[push.cn++] = right.write(txn, rc);
|
push.chld[push.cn++] = right.write(txn, rc);
|
||||||
|
push.cnts[push.nn++] = left.totals();
|
||||||
|
push.cnts[push.nn++] = right.totals();
|
||||||
|
|
||||||
const auto ret
|
const auto ret
|
||||||
{
|
{
|
||||||
|
@ -543,6 +627,10 @@ ircd::m::state::_insert_branch_nonfull(db::txn &txn,
|
||||||
rep.chld[pos + 1] = pushed.chld[1];
|
rep.chld[pos + 1] = pushed.chld[1];
|
||||||
++rep.cn;
|
++rep.cn;
|
||||||
|
|
||||||
|
rep.cnts[pos] = pushed.cnts[0];
|
||||||
|
rep.cnts[pos + 1] = pushed.cnts[1];
|
||||||
|
++rep.nn;
|
||||||
|
|
||||||
return rep.write(txn, idbuf);
|
return rep.write(txn, idbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,6 +653,9 @@ ircd::m::state::_insert_leaf_nonfull(db::txn &txn,
|
||||||
rep.chld[pos] = string_view{};
|
rep.chld[pos] = string_view{};
|
||||||
++rep.cn;
|
++rep.cn;
|
||||||
|
|
||||||
|
rep.cnts[pos] = 0;
|
||||||
|
++rep.nn;
|
||||||
|
|
||||||
return rep.write(txn, idbuf);
|
return rep.write(txn, idbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -733,7 +824,9 @@ ircd::m::state::node::rep::rep(const node &node)
|
||||||
:kn{node.keys(keys.data(), keys.size())}
|
:kn{node.keys(keys.data(), keys.size())}
|
||||||
,vn{node.vals(vals.data(), vals.size())}
|
,vn{node.vals(vals.data(), vals.size())}
|
||||||
,cn{node.childs(chld.data(), chld.size())}
|
,cn{node.childs(chld.data(), chld.size())}
|
||||||
|
,nn{node.counts(cnts.data(), cnts.size())}
|
||||||
{
|
{
|
||||||
|
assert(cn == nn);
|
||||||
}
|
}
|
||||||
|
|
||||||
ircd::m::state::id
|
ircd::m::state::id
|
||||||
|
@ -748,6 +841,7 @@ ircd::json::object
|
||||||
ircd::m::state::node::rep::write(const mutable_buffer &out)
|
ircd::m::state::node::rep::write(const mutable_buffer &out)
|
||||||
{
|
{
|
||||||
assert(kn == vn);
|
assert(kn == vn);
|
||||||
|
assert(cn == nn);
|
||||||
assert(cn <= kn + 1);
|
assert(cn <= kn + 1);
|
||||||
assert(!childs() || childs() > kn);
|
assert(!childs() || childs() > kn);
|
||||||
assert(!duplicates());
|
assert(!duplicates());
|
||||||
|
@ -775,12 +869,19 @@ ircd::m::state::node::rep::write(const mutable_buffer &out)
|
||||||
chld[i] = this->chld[i];
|
chld[i] = this->chld[i];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
json::value cnts[nn];
|
||||||
|
{
|
||||||
|
for(size_t i(0); i < nn; ++i)
|
||||||
|
cnts[i] = json::value{long(this->cnts[i])};
|
||||||
|
};
|
||||||
|
|
||||||
json::iov iov;
|
json::iov iov;
|
||||||
const json::iov::push push[]
|
const json::iov::push push[]
|
||||||
{
|
{
|
||||||
{ iov, { "k"_sv, { keys, kn } } },
|
{ iov, { "k"_sv, { keys, kn } } },
|
||||||
{ iov, { "v"_sv, { vals, vn } } },
|
{ iov, { "v"_sv, { vals, vn } } },
|
||||||
{ iov, { "c"_sv, { chld, cn } } },
|
{ iov, { "c"_sv, { chld, cn } } },
|
||||||
|
{ iov, { "n"_sv, { cnts, nn } } },
|
||||||
};
|
};
|
||||||
|
|
||||||
return { data(out), json::print(out, iov) };
|
return { data(out), json::print(out, iov) };
|
||||||
|
@ -793,6 +894,17 @@ ircd::m::state::node::rep::shr(const size_t &pos)
|
||||||
std::copy_backward(begin(keys) + pos, begin(keys) + kn, begin(keys) + kn + 1);
|
std::copy_backward(begin(keys) + pos, begin(keys) + kn, begin(keys) + kn + 1);
|
||||||
std::copy_backward(begin(vals) + pos, begin(vals) + vn, begin(vals) + vn + 1);
|
std::copy_backward(begin(vals) + pos, begin(vals) + vn, begin(vals) + vn + 1);
|
||||||
std::copy_backward(begin(chld) + pos, begin(chld) + cn, begin(chld) + cn + 1);
|
std::copy_backward(begin(chld) + pos, begin(chld) + cn, begin(chld) + cn + 1);
|
||||||
|
std::copy_backward(begin(cnts) + pos, begin(cnts) + nn, begin(cnts) + nn + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shift left.
|
||||||
|
void
|
||||||
|
ircd::m::state::node::rep::shl(const size_t &pos)
|
||||||
|
{
|
||||||
|
std::copy(begin(keys) + pos + 1, begin(keys) + kn, begin(keys) + std::max(ssize_t(kn) - 1, 0L));
|
||||||
|
std::copy(begin(vals) + pos + 1, begin(vals) + vn, begin(vals) + std::max(ssize_t(vn) - 1, 0L));
|
||||||
|
std::copy(begin(chld) + pos + 1, begin(chld) + cn, begin(chld) + std::max(ssize_t(cn) - 1, 0L));
|
||||||
|
std::copy(begin(cnts) + pos + 1, begin(cnts) + nn, begin(cnts) + std::max(ssize_t(nn) - 1, 0L));
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
|
@ -807,6 +919,24 @@ const
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
ircd::m::state::node::rep::totals()
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return kn + counts();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
ircd::m::state::node::rep::counts()
|
||||||
|
const
|
||||||
|
{
|
||||||
|
size_t ret(0);
|
||||||
|
for(size_t i(0); i < nn; ++i)
|
||||||
|
ret += cnts[i];
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
ircd::m::state::node::rep::childs()
|
ircd::m::state::node::rep::childs()
|
||||||
const
|
const
|
||||||
|
@ -900,6 +1030,19 @@ const
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
ircd::m::state::node::counts(size_t *const &out,
|
||||||
|
const size_t &max)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
size_t i(0);
|
||||||
|
for(const string_view &c : json::get<"n"_>(*this))
|
||||||
|
if(likely(i < max))
|
||||||
|
out[i++] = lex_cast<size_t>(c);
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
ircd::m::state::node::childs(state::id *const &out,
|
ircd::m::state::node::childs(state::id *const &out,
|
||||||
const size_t &max)
|
const size_t &max)
|
||||||
|
@ -939,6 +1082,18 @@ const
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
ircd::m::state::node::count(const size_t &pos)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
const json::array &counts
|
||||||
|
{
|
||||||
|
json::get<"n"_>(*this, json::empty_array)
|
||||||
|
};
|
||||||
|
|
||||||
|
return counts.at<size_t>(pos);
|
||||||
|
}
|
||||||
|
|
||||||
ircd::m::state::id
|
ircd::m::state::id
|
||||||
ircd::m::state::node::child(const size_t &pos)
|
ircd::m::state::node::child(const size_t &pos)
|
||||||
const
|
const
|
||||||
|
@ -977,6 +1132,26 @@ const
|
||||||
return keys[pos];
|
return keys[pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Count counts in node
|
||||||
|
size_t
|
||||||
|
ircd::m::state::node::totals()
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return keys() + counts();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count counts in node
|
||||||
|
size_t
|
||||||
|
ircd::m::state::node::counts()
|
||||||
|
const
|
||||||
|
{
|
||||||
|
size_t ret(0);
|
||||||
|
for(const auto &c : json::get<"n"_>(*this))
|
||||||
|
ret += lex_cast<size_t>(c);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
// Count children in node
|
// Count children in node
|
||||||
size_t
|
size_t
|
||||||
ircd::m::state::node::childs()
|
ircd::m::state::node::childs()
|
||||||
|
|
Loading…
Reference in a new issue