diff --git a/include/ircd/json/tuple/at.h b/include/ircd/json/tuple/at.h new file mode 100644 index 000000000..ece5302b6 --- /dev/null +++ b/include/ircd/json/tuple/at.h @@ -0,0 +1,132 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2018 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_JSON_TUPLE_AT_H + +namespace ircd { +namespace json { + +template +enable_if_tuple()> &> +at(const tuple &t) +{ + constexpr size_t idx + { + indexof() + }; + + const auto &ret + { + val(t) + }; + + using value_type = tuple_value_type; + if(!defined(json::value(ret))) + throw not_found + { + "%s", key(t) + }; + + return ret; +} + +template +enable_if_tuple()> &> +at(tuple &t) +{ + constexpr size_t idx + { + indexof() + }; + + auto &ret + { + val(t) + }; + + using value_type = tuple_value_type; + if(!defined(json::value(ret))) + throw not_found + { + "%s", key(t) + }; + + return ret; +} + +template +enable_if_tuple()> &> +at(const tuple &t) +{ + return at(t); +} + +template +enable_if_tuple()> &> +at(tuple &t) +{ + return at(t); +} + +template +typename std::enable_if(), void>::type +at(tuple &t, + const string_view &name, + function&& f) +{ +} + +template +typename std::enable_if(), void>::type +at(tuple &t, + const string_view &name, + function&& f) +{ + if(indexof(name) == i) + f(val(t)); + else + at(t, name, std::forward(f)); +} + +template +typename std::enable_if(), void>::type +at(const tuple &t, + const string_view &name, + function&& f) +{ +} + +template +typename std::enable_if(), void>::type +at(const tuple &t, + const string_view &name, + function&& f) +{ + if(indexof(name) == i) + f(val(t)); + else + at(t, name, std::forward(f)); +} + +} // namespace json +} // namespace ircd diff --git a/include/ircd/json/tuple/for_each.h b/include/ircd/json/tuple/for_each.h new file mode 100644 index 000000000..03873e32a --- /dev/null +++ b/include/ircd/json/tuple/for_each.h @@ -0,0 +1,130 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2018 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_JSON_TUPLE_FOR_EACH_H + +namespace ircd { +namespace json { + +template +typename std::enable_if(), void>::type +for_each(const tuple &t, + function&& f) +{} + +template +typename std::enable_if(), void>::type +for_each(tuple &t, + function&& f) +{} + +template +typename std::enable_if(), void>::type +for_each(const tuple &t, + function&& f) +{ + f(key(t), val(t)); + for_each(t, std::forward(f)); +} + +template +typename std::enable_if(), void>::type +for_each(tuple &t, + function&& f) +{ + f(key(t), val(t)); + for_each(t, std::forward(f)); +} + +template +void +for_each(const tuple &t, + const vector_view &mask, + function&& f) +{ + std::for_each(std::begin(mask), std::end(mask), [&t, &f] + (const auto &key) + { + at(t, key, [&f, &key] + (auto&& val) + { + f(key, val); + }); + }); +} + +template +void +for_each(tuple &t, + const vector_view &mask, + function&& f) +{ + std::for_each(std::begin(mask), std::end(mask), [&t, &f] + (const auto &key) + { + at(t, key, [&f, &key] + (auto&& val) + { + f(key, val); + }); + }); +} + +template +typename std::enable_if<(i < 0), void>::type +rfor_each(const tuple &t, + function&& f) +{} + +template +typename std::enable_if<(i < 0), void>::type +rfor_each(tuple &t, + function&& f) +{} + +template() - 1> +typename std::enable_if(), void>::type +rfor_each(const tuple &t, + function&& f) +{ + f(key(t), val(t)); + rfor_each(t, std::forward(f)); +} + +template() - 1> +typename std::enable_if(), void>::type +rfor_each(tuple &t, + function&& f) +{ + f(key(t), val(t)); + rfor_each(t, std::forward(f)); +} + +} // namespace json +} // namespace ircd diff --git a/include/ircd/json/tuple/get.h b/include/ircd/json/tuple/get.h new file mode 100644 index 000000000..e49f880cb --- /dev/null +++ b/include/ircd/json/tuple/get.h @@ -0,0 +1,123 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2018 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_JSON_TUPLE_GET_H + +namespace ircd { +namespace json { + +template +enable_if_tuple()> &> +get(const tuple &t) +{ + constexpr size_t idx + { + indexof() + }; + + const auto &ret + { + val(t) + }; + + return ret; +} + +template +enable_if_tuple()>> +get(const tuple &t, + const tuple_value_type()> &def) +{ + constexpr size_t idx + { + indexof() + }; + + const auto &ret + { + val(t) + }; + + using value_type = tuple_value_type; + return defined(json::value(ret))? ret : def; +} + +template +enable_if_tuple()> &> +get(tuple &t) +{ + constexpr size_t idx + { + indexof() + }; + + auto &ret + { + val(t) + }; + + return ret; +} + +template +enable_if_tuple()> &> +get(tuple &t, + tuple_value_type()> &def) +{ + auto &ret + { + get(t) + }; + + using value_type = decltype(ret); + return defined(json::value(ret))? ret : def; +} + +template +enable_if_tuple()> &> +get(const tuple &t) +{ + return get(t); +} + +template +enable_if_tuple()>> +get(const tuple &t, + const tuple_value_type()> &def) +{ + return get(t, def); +} + +template +enable_if_tuple()>> +get(tuple &t) +{ + return get(t); +} + +template +enable_if_tuple()>> +get(tuple &t, + tuple_value_type()> &def) +{ + return get(t, def); +} + +} // namespace json +} // namespace ircd diff --git a/include/ircd/json/tuple/indexof.h b/include/ircd/json/tuple/indexof.h new file mode 100644 index 000000000..e43cf0c70 --- /dev/null +++ b/include/ircd/json/tuple/indexof.h @@ -0,0 +1,101 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2018 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_JSON_TUPLE_INDEXOF_H + +namespace ircd { +namespace json { + +template +constexpr typename std::enable_if(), size_t>::type +indexof() +{ + return size(); +} + +template +constexpr typename std::enable_if(), size_t>::type +indexof() +{ + constexpr auto equal + { + ircd::hash(key()) == hash + }; + + return equal? i : indexof(); +} + +template +constexpr typename std::enable_if(), size_t>::type +indexof() +{ + return size(); +} + +template +constexpr typename std::enable_if(), size_t>::type +indexof() +{ + return indexof(); +} + +template +constexpr typename std::enable_if(), size_t>::type +indexof(const char *const &name) +{ + return size(); +} + +template +constexpr typename std::enable_if(), size_t>::type +indexof(const char *const &name) +{ + constexpr auto equal + { + _constexpr_equal(key(), name) + }; + + return equal? i : indexof(name); +} + +template +constexpr typename std::enable_if(), size_t>::type +indexof(const string_view &name) +{ + return size(); +} + +template +constexpr typename std::enable_if(), size_t>::type +indexof(const string_view &name) +{ + const auto equal + { + name == key() + }; + + return equal? i : indexof(name); +} + +} // namespace json +} // namespace ircd diff --git a/include/ircd/json/tuple/keys.h b/include/ircd/json/tuple/keys.h new file mode 100644 index 000000000..14d087bb5 --- /dev/null +++ b/include/ircd/json/tuple/keys.h @@ -0,0 +1,96 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2018 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_JSON_TUPLE_KEYS_H + +namespace ircd { +namespace json { + +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); + } +}; + +} // namespace json +} // namespace ircd diff --git a/include/ircd/json/tuple/set.h b/include/ircd/json/tuple/set.h new file mode 100644 index 000000000..5b2b2c69b --- /dev/null +++ b/include/ircd/json/tuple/set.h @@ -0,0 +1,180 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2018 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_JSON_TUPLE_SET_H + +namespace ircd { +namespace json { + +template +typename std::enable_if +< + std::is_base_of() && + std::is_convertible(), +void>::type +_assign(dst &d, + src&& s) +{ + d = unquote(string_view{std::forward(s)}); +} + +template +typename std::enable_if +< + !std::is_base_of() && + std::is_convertible() && + !ircd::json::is_tuple() && + !std::is_same(), +void>::type +_assign(dst &d, + src&& s) +{ + d = std::forward(s); +} + +template +typename std::enable_if +< + !std::is_base_of() && + std::is_convertible() && + !ircd::json::is_tuple() && + std::is_same(), +void>::type +_assign(dst &d, + src&& s) +{ + static const is_zero test{}; + d = !test(std::forward(s)); +} + +template +typename std::enable_if +< + std::is_arithmetic() && + std::is_base_of::type>() && + !std::is_base_of, typename std::remove_reference::type>(), +void>::type +_assign(dst &d, + src&& s) +try +{ + d = lex_cast(std::forward(s)); +} +catch(const bad_lex_cast &e) +{ + throw parse_error("cannot convert '%s' to '%s'", + demangle(), + demangle()); +} + +template +typename std::enable_if +< + std::is_arithmetic() && + std::is_base_of, typename std::remove_reference::type>(), +void>::type +_assign(dst &d, + src&& s) +{ + assert(!s.empty()); + d = byte_view(std::forward(s)); +} + +template +typename std::enable_if +< + std::is_base_of() && + std::is_pod::type>(), +void>::type +_assign(dst &d, + src&& s) +{ + d = byte_view(std::forward(s)); +} + +template +typename std::enable_if +< + ircd::json::is_tuple(), +void>::type +_assign(dst &d, + src&& s) +{ + d = dst{std::forward(s)}; +} + +template +tuple & +set(tuple &t, + const string_view &key, + V&& val) +try +{ + at(t, key, [&key, &val] + (auto &target) + { + _assign(target, std::forward(val)); + }); + + return t; +} +catch(const std::exception &e) +{ + throw parse_error("failed to set member '%s' (from %s): %s", + key, + demangle(), + e.what()); +} + +template +tuple & +set(tuple &t, + const string_view &key, + const json::value &value) +{ + switch(type(value)) + { + case type::STRING: + case type::LITERAL: + set(t, key, string_view{value}); + break; + + case type::NUMBER: + if(value.floats) + set(t, key, value.floating); + else + set(t, key, value.integer); + break; + + case type::OBJECT: + case type::ARRAY: + if(unlikely(!value.serial)) + throw print_error("Type %s must be JSON to be used by tuple member '%s'", + reflect(type(value)), + key); + + set(t, key, string_view{value}); + break; + } + + return t; +} + +} // namespace json +} // namespace ircd diff --git a/include/ircd/json/tuple/tuple.h b/include/ircd/json/tuple/tuple.h index fa6c5c3b2..af7fbb693 100644 --- a/include/ircd/json/tuple/tuple.h +++ b/include/ircd/json/tuple/tuple.h @@ -134,95 +134,13 @@ key(const tuple &t) return std::get(t).key; } -template -constexpr typename std::enable_if(), size_t>::type -indexof() -{ - return size(); -} +} // namespace json +} // namespace ircd -template -constexpr typename std::enable_if(), size_t>::type -indexof() -{ - constexpr auto equal - { - ircd::hash(key()) == hash - }; +#include "indexof.h" - return equal? i : indexof(); -} - -template -constexpr typename std::enable_if(), size_t>::type -indexof() -{ - return size(); -} - -template -constexpr typename std::enable_if(), size_t>::type -indexof() -{ - return indexof(); -} - -template -constexpr typename std::enable_if(), size_t>::type -indexof(const char *const &name) -{ - return size(); -} - -template -constexpr typename std::enable_if(), size_t>::type -indexof(const char *const &name) -{ - constexpr auto equal - { - _constexpr_equal(key(), name) - }; - - return equal? i : indexof(name); -} - -template -constexpr typename std::enable_if(), size_t>::type -indexof(const string_view &name) -{ - return size(); -} - -template -constexpr typename std::enable_if(), size_t>::type -indexof(const string_view &name) -{ - const auto equal - { - name == key() - }; - - return equal? i : indexof(name); -} - -template -constexpr bool -key_exists(const string_view &key) -{ - return indexof(key) < size(); -} +namespace ircd { +namespace json { template @@ -240,610 +158,24 @@ val(const tuple &t) return static_cast &>(std::get(t)); } -template -typename std::enable_if -< - std::is_base_of() && - std::is_convertible(), -void>::type -_assign(dst &d, - src&& s) +template +constexpr bool +key_exists(const string_view &key) { - d = unquote(string_view{std::forward(s)}); + return indexof(key) < size(); } -template -typename std::enable_if -< - !std::is_base_of() && - std::is_convertible() && - !ircd::json::is_tuple() && - !std::is_same(), -void>::type -_assign(dst &d, - src&& s) -{ - d = std::forward(s); -} +} // namespace json +} // namespace ircd -template -typename std::enable_if -< - !std::is_base_of() && - std::is_convertible() && - !ircd::json::is_tuple() && - std::is_same(), -void>::type -_assign(dst &d, - src&& s) -{ - static const is_zero test{}; - d = !test(std::forward(s)); -} +#include "get.h" +#include "at.h" +#include "for_each.h" +#include "until.h" +#include "set.h" -template -typename std::enable_if -< - std::is_arithmetic() && - std::is_base_of::type>() && - !std::is_base_of, typename std::remove_reference::type>(), -void>::type -_assign(dst &d, - src&& s) -try -{ - d = lex_cast(std::forward(s)); -} -catch(const bad_lex_cast &e) -{ - throw parse_error("cannot convert '%s' to '%s'", - demangle(), - demangle()); -} - -template -typename std::enable_if -< - std::is_arithmetic() && - std::is_base_of, typename std::remove_reference::type>(), -void>::type -_assign(dst &d, - src&& s) -{ - assert(!s.empty()); - d = byte_view(std::forward(s)); -} - -template -typename std::enable_if -< - std::is_base_of() && - std::is_pod::type>(), -void>::type -_assign(dst &d, - src&& s) -{ - d = byte_view(std::forward(s)); -} - -template -typename std::enable_if -< - ircd::json::is_tuple(), -void>::type -_assign(dst &d, - src&& s) -{ - d = dst{std::forward(s)}; -} - -template -enable_if_tuple()> &> -get(const tuple &t) -{ - constexpr size_t idx - { - indexof() - }; - - const auto &ret - { - val(t) - }; - - return ret; -} - -template -enable_if_tuple()>> -get(const tuple &t, - const tuple_value_type()> &def) -{ - constexpr size_t idx - { - indexof() - }; - - const auto &ret - { - val(t) - }; - - using value_type = tuple_value_type; - return defined(json::value(ret))? ret : def; -} - -template -enable_if_tuple()> &> -get(tuple &t) -{ - constexpr size_t idx - { - indexof() - }; - - auto &ret - { - val(t) - }; - - return ret; -} - -template -enable_if_tuple()> &> -get(tuple &t, - tuple_value_type()> &def) -{ - auto &ret - { - get(t) - }; - - using value_type = decltype(ret); - return defined(json::value(ret))? ret : def; -} - -template -enable_if_tuple()> &> -get(const tuple &t) -{ - return get(t); -} - -template -enable_if_tuple()>> -get(const tuple &t, - const tuple_value_type()> &def) -{ - return get(t, def); -} - -template -enable_if_tuple()>> -get(tuple &t) -{ - return get(t); -} - -template -enable_if_tuple()>> -get(tuple &t, - tuple_value_type()> &def) -{ - return get(t, def); -} - -template -enable_if_tuple()> &> -at(const tuple &t) -{ - constexpr size_t idx - { - indexof() - }; - - const auto &ret - { - val(t) - }; - - using value_type = tuple_value_type; - if(!defined(json::value(ret))) - throw not_found - { - "%s", key(t) - }; - - return ret; -} - -template -enable_if_tuple()> &> -at(tuple &t) -{ - constexpr size_t idx - { - indexof() - }; - - auto &ret - { - val(t) - }; - - using value_type = tuple_value_type; - if(!defined(json::value(ret))) - throw not_found - { - "%s", key(t) - }; - - return ret; -} - -template -enable_if_tuple()> &> -at(const tuple &t) -{ - return at(t); -} - -template -enable_if_tuple()> &> -at(tuple &t) -{ - return at(t); -} - -template -typename std::enable_if(), void>::type -at(tuple &t, - const string_view &name, - function&& f) -{ -} - -template -typename std::enable_if(), void>::type -at(tuple &t, - const string_view &name, - function&& f) -{ - if(indexof(name) == i) - f(val(t)); - else - at(t, name, std::forward(f)); -} - -template -typename std::enable_if(), void>::type -at(const tuple &t, - const string_view &name, - function&& f) -{ -} - -template -typename std::enable_if(), void>::type -at(const tuple &t, - const string_view &name, - function&& f) -{ - if(indexof(name) == i) - f(val(t)); - else - at(t, name, std::forward(f)); -} - -template -typename std::enable_if(), void>::type -for_each(const tuple &t, - function&& f) -{} - -template -typename std::enable_if(), void>::type -for_each(tuple &t, - function&& f) -{} - -template -typename std::enable_if(), void>::type -for_each(const tuple &t, - function&& f) -{ - f(key(t), val(t)); - for_each(t, std::forward(f)); -} - -template -typename std::enable_if(), void>::type -for_each(tuple &t, - function&& f) -{ - f(key(t), val(t)); - for_each(t, std::forward(f)); -} - -template -void -for_each(const tuple &t, - const vector_view &mask, - function&& f) -{ - std::for_each(std::begin(mask), std::end(mask), [&t, &f] - (const auto &key) - { - at(t, key, [&f, &key] - (auto&& val) - { - f(key, val); - }); - }); -} - -template -void -for_each(tuple &t, - const vector_view &mask, - function&& f) -{ - std::for_each(std::begin(mask), std::end(mask), [&t, &f] - (const auto &key) - { - at(t, key, [&f, &key] - (auto&& val) - { - f(key, val); - }); - }); -} - -template -typename std::enable_if<(i < 0), void>::type -rfor_each(const tuple &t, - function&& f) -{} - -template -typename std::enable_if<(i < 0), void>::type -rfor_each(tuple &t, - function&& f) -{} - -template() - 1> -typename std::enable_if(), void>::type -rfor_each(const tuple &t, - function&& f) -{ - f(key(t), val(t)); - rfor_each(t, std::forward(f)); -} - -template() - 1> -typename std::enable_if(), void>::type -rfor_each(tuple &t, - function&& f) -{ - f(key(t), val(t)); - rfor_each(t, std::forward(f)); -} - -template -typename std::enable_if(), bool>::type -until(const tuple &t, - function&& f) -{ - return true; -} - -template -typename std::enable_if(), bool>::type -until(tuple &t, - function&& f) -{ - return true; -} - -template -typename std::enable_if(), bool>::type -until(const tuple &t, - function&& f) -{ - return f(key(t), val(t))? - until(t, std::forward(f)): - false; -} - -template -typename std::enable_if(), bool>::type -until(tuple &t, - function&& f) -{ - return f(key(t), val(t))? - until(t, std::forward(f)): - false; -} - -template -typename std::enable_if(), bool>::type -until(const tuple &a, - const tuple &b, - function&& f) -{ - return true; -} - -template -typename std::enable_if(), bool>::type -until(const tuple &a, - const tuple &b, - function&& f) -{ - return f(key(a), val(a), val(b))? - until(a, b, std::forward(f)): - false; -} - -template -typename std::enable_if<(i < 0), bool>::type -runtil(const tuple &t, - function&& f) -{ - return true; -} - -template -typename std::enable_if<(i < 0), bool>::type -runtil(tuple &t, - function&& f) -{ - return true; -} - -template() - 1> -typename std::enable_if(), bool>::type -runtil(const tuple &t, - function&& f) -{ - return f(key(t), val(t))? - runtil(t, std::forward(f)): - false; -} - -template() - 1> -typename std::enable_if(), bool>::type -runtil(tuple &t, - function&& f) -{ - return f(key(t), val(t))? - runtil(t, std::forward(f)): - false; -} - -template -tuple & -set(tuple &t, - const string_view &key, - V&& val) -try -{ - at(t, key, [&key, &val] - (auto &target) - { - _assign(target, std::forward(val)); - }); - - return t; -} -catch(const std::exception &e) -{ - throw parse_error("failed to set member '%s' (from %s): %s", - key, - demangle(), - e.what()); -} - -template -tuple & -set(tuple &t, - const string_view &key, - const json::value &value) -{ - switch(type(value)) - { - case type::STRING: - case type::LITERAL: - set(t, key, string_view{value}); - break; - - case type::NUMBER: - if(value.floats) - set(t, key, value.floating); - else - set(t, key, value.integer); - break; - - case type::OBJECT: - case type::ARRAY: - if(unlikely(!value.serial)) - throw print_error("Type %s must be JSON to be used by tuple member '%s'", - reflect(type(value)), - key); - - set(t, key, string_view{value}); - break; - } - - return t; -} +namespace ircd { +namespace json { template tuple::tuple(const json::object &object) @@ -948,83 +280,13 @@ _key_transform(const tuple &tuple, return it; } -template -struct tuple::keys -:std::array::size()> -{ - struct selection; - struct include; - struct exclude; +} // namespace json +} // namespace ircd - constexpr keys() - { - _key_transform>(this->begin(), this->end()); - } -}; +#include "keys.h" -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); - } -}; +namespace ircd { +namespace json { template +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_JSON_TUPLE_UNTIL_H + +namespace ircd { +namespace json { + +template +typename std::enable_if(), bool>::type +until(const tuple &t, + function&& f) +{ + return true; +} + +template +typename std::enable_if(), bool>::type +until(tuple &t, + function&& f) +{ + return true; +} + +template +typename std::enable_if(), bool>::type +until(const tuple &t, + function&& f) +{ + return f(key(t), val(t))? + until(t, std::forward(f)): + false; +} + +template +typename std::enable_if(), bool>::type +until(tuple &t, + function&& f) +{ + return f(key(t), val(t))? + until(t, std::forward(f)): + false; +} + +template +typename std::enable_if(), bool>::type +until(const tuple &a, + const tuple &b, + function&& f) +{ + return true; +} + +template +typename std::enable_if(), bool>::type +until(const tuple &a, + const tuple &b, + function&& f) +{ + return f(key(a), val(a), val(b))? + until(a, b, std::forward(f)): + false; +} + +template +typename std::enable_if<(i < 0), bool>::type +runtil(const tuple &t, + function&& f) +{ + return true; +} + +template +typename std::enable_if<(i < 0), bool>::type +runtil(tuple &t, + function&& f) +{ + return true; +} + +template() - 1> +typename std::enable_if(), bool>::type +runtil(const tuple &t, + function&& f) +{ + return f(key(t), val(t))? + runtil(t, std::forward(f)): + false; +} + +template() - 1> +typename std::enable_if(), bool>::type +runtil(tuple &t, + function&& f) +{ + return f(key(t), val(t))? + runtil(t, std::forward(f)): + false; +} + +} // namespace json +} // namespace ircd