diff --git a/include/ircd/json/tuple.h b/include/ircd/json/tuple.h index cc7e87e71..d82cb3b64 100644 --- a/include/ircd/json/tuple.h +++ b/include/ircd/json/tuple.h @@ -60,6 +60,7 @@ struct tuple :std::tuple ,tuple_base { + struct keys; using tuple_type = std::tuple; using super_type = tuple; @@ -960,6 +961,84 @@ _key_transform(const tuple &tuple, return it; } +template +struct tuple::keys +:std::array::size()> +{ + struct selection; + struct include; + struct exclude; + + constexpr keys() + { + _key_transform>(this->begin(), this->end()); + } +}; + +template +struct tuple::keys::selection +:std::bitset::size()> +{ + template + constexpr bool until(closure &&function) const + { + for(size_t i(0); i < this->size(); ++i) + if(this->test(i)) + if(!function(key, i>())) + return false; + + return true; + } + + template + constexpr void for_each(closure &&function) const + { + this->until([&function](auto&& key) + { + function(key); + return true; + }); + } + + template + constexpr auto transform(it_a it, const it_b end) const + { + this->until([&it, &end](auto&& key) + { + if(it == end) + return false; + + *it = key; + ++it; + return true; + }); + } +}; + +template +struct tuple::keys::include +:selection +{ + constexpr include(const std::initializer_list &list) + { + for(const auto &key : list) + this->set(indexof>(key), true); + } +}; + +template +struct tuple::keys::exclude +:selection +{ + constexpr exclude(const std::initializer_list &list) + { + this->set(); + for(const auto &key : list) + this->set(indexof>(key), false); + } +}; + template