mirror of
https://github.com/matrix-construct/construct
synced 2024-11-19 16:30:52 +01:00
ircd::json: Elaborate on keys interface; cleanup; add comments.
This commit is contained in:
parent
4b554f4605
commit
9d2a796f17
2 changed files with 124 additions and 50 deletions
|
@ -14,48 +14,88 @@
|
||||||
namespace ircd {
|
namespace ircd {
|
||||||
namespace json {
|
namespace json {
|
||||||
|
|
||||||
template<class... T>
|
template<class tuple> struct keys;
|
||||||
struct tuple<T...>::keys
|
|
||||||
:std::array<string_view, tuple<T...>::size()>
|
} // namespace json
|
||||||
|
} // namespace ircd
|
||||||
|
|
||||||
|
/// Array of string literals (in string_views) representing just the keys of a
|
||||||
|
/// tuple. By default construction all keys are included in the array. A
|
||||||
|
/// selection construction will only include keys that are selected. Note that
|
||||||
|
/// the selection construction packs all the chosen keys at the front of the
|
||||||
|
/// array so you cannot rely on this for a key's index into the tuple.
|
||||||
|
template<class tuple>
|
||||||
|
struct ircd::json::keys
|
||||||
|
:std::array<ircd::string_view, tuple::size()>
|
||||||
{
|
{
|
||||||
struct selection;
|
struct selection;
|
||||||
struct include;
|
struct include;
|
||||||
struct exclude;
|
struct exclude;
|
||||||
|
|
||||||
constexpr keys()
|
size_t count() const;
|
||||||
{
|
|
||||||
_key_transform<tuple<T...>>(this->begin(), this->end());
|
keys(const selection &);
|
||||||
}
|
keys();
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class... T>
|
/// Selection of keys in a tuple represented by a bitset. Users generally
|
||||||
struct tuple<T...>::keys::selection
|
/// do not construct this class directly. Instead, construct one of the
|
||||||
:std::bitset<tuple<T...>::size()>
|
/// `include` or `exclude` classes which will set these bits appropriately.
|
||||||
|
template<class tuple>
|
||||||
|
struct ircd::json::keys<tuple>::selection
|
||||||
|
:std::bitset<tuple::size()>
|
||||||
{
|
{
|
||||||
template<class closure>
|
template<class closure>
|
||||||
constexpr bool until(closure &&function) const
|
bool until(closure &&function) const;
|
||||||
{
|
|
||||||
for(size_t i(0); i < this->size(); ++i)
|
|
||||||
if(this->test(i))
|
|
||||||
if(!function(key<tuple<T...>, i>()))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class closure>
|
template<class closure>
|
||||||
constexpr void for_each(closure &&function) const
|
void for_each(closure &&function) const;
|
||||||
{
|
|
||||||
this->until([&function](auto&& key)
|
|
||||||
{
|
|
||||||
function(key);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class it_a,
|
template<class it_a,
|
||||||
class it_b>
|
class it_b>
|
||||||
constexpr auto transform(it_a it, const it_b end) const
|
it_a transform(it_a it, const it_b end) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Construct this class with a list of keys you want to select for a given
|
||||||
|
/// tuple. This constructs a bitset representing the keys of the tuple and
|
||||||
|
/// lights the bits for your selections.
|
||||||
|
template<class tuple>
|
||||||
|
struct ircd::json::keys<tuple>::include
|
||||||
|
:selection
|
||||||
|
{
|
||||||
|
include(const std::initializer_list<string_view> &list)
|
||||||
|
{
|
||||||
|
for(const auto &key : list)
|
||||||
|
this->set(indexof<tuple>(key), true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Construct this class with a list of keys you want to deselect for a given
|
||||||
|
/// tuple. This constructs a bitset representing the keys of the tuple and
|
||||||
|
/// lights the bits which are not in the list.
|
||||||
|
template<class tuple>
|
||||||
|
struct ircd::json::keys<tuple>::exclude
|
||||||
|
:selection
|
||||||
|
{
|
||||||
|
exclude(const std::initializer_list<string_view> &list)
|
||||||
|
{
|
||||||
|
this->set();
|
||||||
|
for(const auto &key : list)
|
||||||
|
this->set(indexof<tuple>(key), false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// selection
|
||||||
|
//
|
||||||
|
|
||||||
|
template<class tuple>
|
||||||
|
template<class it_a,
|
||||||
|
class it_b>
|
||||||
|
it_a
|
||||||
|
ircd::json::keys<tuple>::selection::transform(it_a it,
|
||||||
|
const it_b end)
|
||||||
|
const
|
||||||
{
|
{
|
||||||
this->until([&it, &end](auto&& key)
|
this->until([&it, &end](auto&& key)
|
||||||
{
|
{
|
||||||
|
@ -66,31 +106,62 @@ struct tuple<T...>::keys::selection
|
||||||
++it;
|
++it;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class... T>
|
return it;
|
||||||
struct tuple<T...>::keys::include
|
|
||||||
:selection
|
|
||||||
{
|
|
||||||
constexpr include(const std::initializer_list<string_view> &list)
|
|
||||||
{
|
|
||||||
for(const auto &key : list)
|
|
||||||
this->set(indexof<tuple<T...>>(key), true);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
template<class... T>
|
template<class tuple>
|
||||||
struct tuple<T...>::keys::exclude
|
template<class closure>
|
||||||
:selection
|
void
|
||||||
|
ircd::json::keys<tuple>::selection::for_each(closure &&function)
|
||||||
|
const
|
||||||
{
|
{
|
||||||
constexpr exclude(const std::initializer_list<string_view> &list)
|
this->until([&function](auto&& key)
|
||||||
{
|
{
|
||||||
this->set();
|
function(key);
|
||||||
for(const auto &key : list)
|
return true;
|
||||||
this->set(indexof<tuple<T...>>(key), false);
|
});
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace json
|
template<class tuple>
|
||||||
} // namespace ircd
|
template<class closure>
|
||||||
|
bool
|
||||||
|
ircd::json::keys<tuple>::selection::until(closure &&function)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
for(size_t i(0); i < tuple::size(); ++i)
|
||||||
|
if(this->test(i))
|
||||||
|
if(!function(key<tuple>(i)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// keys
|
||||||
|
//
|
||||||
|
|
||||||
|
template<class tuple>
|
||||||
|
ircd::json::keys<tuple>::keys()
|
||||||
|
{
|
||||||
|
_key_transform<tuple>(this->begin(), this->end());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class tuple>
|
||||||
|
ircd::json::keys<tuple>::keys(const selection &selection)
|
||||||
|
{
|
||||||
|
selection.transform(this->begin(), this->end());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class tuple>
|
||||||
|
size_t
|
||||||
|
ircd::json::keys<tuple>::count()
|
||||||
|
const
|
||||||
|
{
|
||||||
|
size_t i(0);
|
||||||
|
for(; i < this->size(); ++i)
|
||||||
|
if(!(*this)[i])
|
||||||
|
break;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
namespace ircd {
|
namespace ircd {
|
||||||
namespace json {
|
namespace json {
|
||||||
|
|
||||||
|
//TODO: sort
|
||||||
|
template<class tuple> struct keys;
|
||||||
|
|
||||||
/// All tuple templates inherit from this non-template type for tagging.
|
/// All tuple templates inherit from this non-template type for tagging.
|
||||||
struct tuple_base
|
struct tuple_base
|
||||||
{
|
{
|
||||||
|
@ -51,9 +54,9 @@ struct tuple
|
||||||
:std::tuple<T...>
|
:std::tuple<T...>
|
||||||
,tuple_base
|
,tuple_base
|
||||||
{
|
{
|
||||||
struct keys;
|
|
||||||
using tuple_type = std::tuple<T...>;
|
using tuple_type = std::tuple<T...>;
|
||||||
using super_type = tuple<T...>;
|
using super_type = tuple<T...>;
|
||||||
|
using keys = json::keys<super_type>;
|
||||||
|
|
||||||
static constexpr size_t size();
|
static constexpr size_t size();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue