0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-07-03 01:09:05 +02:00

ircd::json: Preliminary rough splitup of tuple headers.

This commit is contained in:
Jason Volk 2018-05-06 21:31:32 -07:00
parent 456f8e7ac1
commit 671622d778
8 changed files with 915 additions and 761 deletions

View file

@ -0,0 +1,132 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
//
// 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<size_t hash,
class tuple>
enable_if_tuple<tuple, const tuple_value_type<tuple, indexof<tuple, hash>()> &>
at(const tuple &t)
{
constexpr size_t idx
{
indexof<tuple, hash>()
};
const auto &ret
{
val<idx>(t)
};
using value_type = tuple_value_type<tuple, idx>;
if(!defined(json::value(ret)))
throw not_found
{
"%s", key<idx>(t)
};
return ret;
}
template<size_t hash,
class tuple>
enable_if_tuple<tuple, tuple_value_type<tuple, indexof<tuple, hash>()> &>
at(tuple &t)
{
constexpr size_t idx
{
indexof<tuple, hash>()
};
auto &ret
{
val<idx>(t)
};
using value_type = tuple_value_type<tuple, idx>;
if(!defined(json::value(ret)))
throw not_found
{
"%s", key<idx>(t)
};
return ret;
}
template<const char *const &name,
class tuple>
enable_if_tuple<tuple, const tuple_value_type<tuple, indexof<tuple, name>()> &>
at(const tuple &t)
{
return at<name_hash(name), tuple>(t);
}
template<const char *const &name,
class tuple>
enable_if_tuple<tuple, tuple_value_type<tuple, indexof<tuple, name>()> &>
at(tuple &t)
{
return at<name_hash(name), tuple>(t);
}
template<class tuple,
class function,
size_t i>
typename std::enable_if<i == size<tuple>(), void>::type
at(tuple &t,
const string_view &name,
function&& f)
{
}
template<class tuple,
class function,
size_t i = 0>
typename std::enable_if<i < size<tuple>(), void>::type
at(tuple &t,
const string_view &name,
function&& f)
{
if(indexof<tuple>(name) == i)
f(val<i>(t));
else
at<tuple, function, i + 1>(t, name, std::forward<function>(f));
}
template<class tuple,
class function,
size_t i>
typename std::enable_if<i == size<tuple>(), void>::type
at(const tuple &t,
const string_view &name,
function&& f)
{
}
template<class tuple,
class function,
size_t i = 0>
typename std::enable_if<i < size<tuple>(), void>::type
at(const tuple &t,
const string_view &name,
function&& f)
{
if(indexof<tuple>(name) == i)
f(val<i>(t));
else
at<tuple, function, i + 1>(t, name, std::forward<function>(f));
}
} // namespace json
} // namespace ircd

View file

@ -0,0 +1,130 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
//
// 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<size_t i,
class tuple,
class function>
typename std::enable_if<i == size<tuple>(), void>::type
for_each(const tuple &t,
function&& f)
{}
template<size_t i,
class tuple,
class function>
typename std::enable_if<i == size<tuple>(), void>::type
for_each(tuple &t,
function&& f)
{}
template<size_t i = 0,
class tuple,
class function>
typename std::enable_if<i < size<tuple>(), void>::type
for_each(const tuple &t,
function&& f)
{
f(key<i>(t), val<i>(t));
for_each<i + 1>(t, std::forward<function>(f));
}
template<size_t i = 0,
class tuple,
class function>
typename std::enable_if<i < size<tuple>(), void>::type
for_each(tuple &t,
function&& f)
{
f(key<i>(t), val<i>(t));
for_each<i + 1>(t, std::forward<function>(f));
}
template<class tuple,
class function>
void
for_each(const tuple &t,
const vector_view<const string_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<class tuple,
class function>
void
for_each(tuple &t,
const vector_view<const string_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<class tuple,
class function,
ssize_t i>
typename std::enable_if<(i < 0), void>::type
rfor_each(const tuple &t,
function&& f)
{}
template<class tuple,
class function,
ssize_t i>
typename std::enable_if<(i < 0), void>::type
rfor_each(tuple &t,
function&& f)
{}
template<class tuple,
class function,
ssize_t i = size<tuple>() - 1>
typename std::enable_if<i < tuple_size<tuple>(), void>::type
rfor_each(const tuple &t,
function&& f)
{
f(key<i>(t), val<i>(t));
rfor_each<tuple, function, i - 1>(t, std::forward<function>(f));
}
template<class tuple,
class function,
ssize_t i = size<tuple>() - 1>
typename std::enable_if<i < tuple_size<tuple>(), void>::type
rfor_each(tuple &t,
function&& f)
{
f(key<i>(t), val<i>(t));
rfor_each<tuple, function, i - 1>(t, std::forward<function>(f));
}
} // namespace json
} // namespace ircd

View file

@ -0,0 +1,123 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
//
// 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<size_t hash,
class tuple>
enable_if_tuple<tuple, const tuple_value_type<tuple, indexof<tuple, hash>()> &>
get(const tuple &t)
{
constexpr size_t idx
{
indexof<tuple, hash>()
};
const auto &ret
{
val<idx>(t)
};
return ret;
}
template<size_t hash,
class tuple>
enable_if_tuple<tuple, tuple_value_type<tuple, indexof<tuple, hash>()>>
get(const tuple &t,
const tuple_value_type<tuple, indexof<tuple, hash>()> &def)
{
constexpr size_t idx
{
indexof<tuple, hash>()
};
const auto &ret
{
val<idx>(t)
};
using value_type = tuple_value_type<tuple, idx>;
return defined(json::value(ret))? ret : def;
}
template<size_t hash,
class tuple>
enable_if_tuple<tuple, tuple_value_type<tuple, indexof<tuple, hash>()> &>
get(tuple &t)
{
constexpr size_t idx
{
indexof<tuple, hash>()
};
auto &ret
{
val<idx>(t)
};
return ret;
}
template<size_t hash,
class tuple>
enable_if_tuple<tuple, tuple_value_type<tuple, indexof<tuple, hash>()> &>
get(tuple &t,
tuple_value_type<tuple, indexof<tuple, hash>()> &def)
{
auto &ret
{
get<hash, tuple>(t)
};
using value_type = decltype(ret);
return defined(json::value(ret))? ret : def;
}
template<const char *const &name,
class tuple>
enable_if_tuple<tuple, const tuple_value_type<tuple, indexof<tuple, name>()> &>
get(const tuple &t)
{
return get<name_hash(name), tuple>(t);
}
template<const char *const &name,
class tuple>
enable_if_tuple<tuple, tuple_value_type<tuple, indexof<tuple, name>()>>
get(const tuple &t,
const tuple_value_type<tuple, indexof<tuple, name>()> &def)
{
return get<name_hash(name), tuple>(t, def);
}
template<const char *const &name,
class tuple>
enable_if_tuple<tuple, tuple_value_type<tuple, indexof<tuple, name>()>>
get(tuple &t)
{
return get<name_hash(name), tuple>(t);
}
template<const char *const &name,
class tuple>
enable_if_tuple<tuple, tuple_value_type<tuple, indexof<tuple, name>()>>
get(tuple &t,
tuple_value_type<tuple, indexof<tuple, hash>()> &def)
{
return get<name_hash(name), tuple>(t, def);
}
} // namespace json
} // namespace ircd

View file

@ -0,0 +1,101 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
//
// 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<class tuple,
size_t hash,
size_t i>
constexpr typename std::enable_if<i == size<tuple>(), size_t>::type
indexof()
{
return size<tuple>();
}
template<class tuple,
size_t hash,
size_t i = 0>
constexpr typename std::enable_if<i < size<tuple>(), size_t>::type
indexof()
{
constexpr auto equal
{
ircd::hash(key<tuple, i>()) == hash
};
return equal? i : indexof<tuple, hash, i + 1>();
}
template<class tuple,
const char *const &name,
size_t i>
constexpr typename std::enable_if<i == size<tuple>(), size_t>::type
indexof()
{
return size<tuple>();
}
template<class tuple,
const char *const &name,
size_t i = 0>
constexpr typename std::enable_if<i < size<tuple>(), size_t>::type
indexof()
{
return indexof<tuple, name_hash(name)>();
}
template<class tuple,
size_t i>
constexpr typename std::enable_if<i == size<tuple>(), size_t>::type
indexof(const char *const &name)
{
return size<tuple>();
}
template<class tuple,
size_t i = 0>
constexpr typename std::enable_if<i < size<tuple>(), size_t>::type
indexof(const char *const &name)
{
constexpr auto equal
{
_constexpr_equal(key<tuple, i>(), name)
};
return equal? i : indexof<tuple, i + 1>(name);
}
template<class tuple,
size_t i>
constexpr typename std::enable_if<i == size<tuple>(), size_t>::type
indexof(const string_view &name)
{
return size<tuple>();
}
template<class tuple,
size_t i = 0>
constexpr typename std::enable_if<i < size<tuple>(), size_t>::type
indexof(const string_view &name)
{
const auto equal
{
name == key<tuple, i>()
};
return equal? i : indexof<tuple, i + 1>(name);
}
} // namespace json
} // namespace ircd

View file

@ -0,0 +1,96 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
//
// 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<class... T>
struct tuple<T...>::keys
:std::array<string_view, tuple<T...>::size()>
{
struct selection;
struct include;
struct exclude;
constexpr keys()
{
_key_transform<tuple<T...>>(this->begin(), this->end());
}
};
template<class... T>
struct tuple<T...>::keys::selection
:std::bitset<tuple<T...>::size()>
{
template<class closure>
constexpr 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>
constexpr void for_each(closure &&function) const
{
this->until([&function](auto&& key)
{
function(key);
return true;
});
}
template<class it_a,
class it_b>
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<class... T>
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>
struct tuple<T...>::keys::exclude
:selection
{
constexpr exclude(const std::initializer_list<string_view> &list)
{
this->set();
for(const auto &key : list)
this->set(indexof<tuple<T...>>(key), false);
}
};
} // namespace json
} // namespace ircd

View file

@ -0,0 +1,180 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
//
// 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<class dst,
class src>
typename std::enable_if
<
std::is_base_of<json::string, dst>() &&
std::is_convertible<src, ircd::string_view>(),
void>::type
_assign(dst &d,
src&& s)
{
d = unquote(string_view{std::forward<src>(s)});
}
template<class dst,
class src>
typename std::enable_if
<
!std::is_base_of<json::string, dst>() &&
std::is_convertible<src, dst>() &&
!ircd::json::is_tuple<dst>() &&
!std::is_same<bool, dst>(),
void>::type
_assign(dst &d,
src&& s)
{
d = std::forward<src>(s);
}
template<class dst,
class src>
typename std::enable_if
<
!std::is_base_of<json::string, dst>() &&
std::is_convertible<src, dst>() &&
!ircd::json::is_tuple<dst>() &&
std::is_same<bool, dst>(),
void>::type
_assign(dst &d,
src&& s)
{
static const is_zero test{};
d = !test(std::forward<src>(s));
}
template<class dst,
class src>
typename std::enable_if
<
std::is_arithmetic<dst>() &&
std::is_base_of<std::string_view, typename std::remove_reference<src>::type>() &&
!std::is_base_of<ircd::byte_view<ircd::string_view>, typename std::remove_reference<src>::type>(),
void>::type
_assign(dst &d,
src&& s)
try
{
d = lex_cast<dst>(std::forward<src>(s));
}
catch(const bad_lex_cast &e)
{
throw parse_error("cannot convert '%s' to '%s'",
demangle<src>(),
demangle<dst>());
}
template<class dst,
class src>
typename std::enable_if
<
std::is_arithmetic<dst>() &&
std::is_base_of<ircd::byte_view<ircd::string_view>, typename std::remove_reference<src>::type>(),
void>::type
_assign(dst &d,
src&& s)
{
assert(!s.empty());
d = byte_view<dst>(std::forward<src>(s));
}
template<class dst,
class src>
typename std::enable_if
<
std::is_base_of<std::string_view, dst>() &&
std::is_pod<typename std::remove_reference<src>::type>(),
void>::type
_assign(dst &d,
src&& s)
{
d = byte_view<string_view>(std::forward<src>(s));
}
template<class dst,
class src>
typename std::enable_if
<
ircd::json::is_tuple<dst>(),
void>::type
_assign(dst &d,
src&& s)
{
d = dst{std::forward<src>(s)};
}
template<class V,
class... T>
tuple<T...> &
set(tuple<T...> &t,
const string_view &key,
V&& val)
try
{
at(t, key, [&key, &val]
(auto &target)
{
_assign(target, std::forward<V>(val));
});
return t;
}
catch(const std::exception &e)
{
throw parse_error("failed to set member '%s' (from %s): %s",
key,
demangle<V>(),
e.what());
}
template<class... T>
tuple<T...> &
set(tuple<T...> &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

View file

@ -134,95 +134,13 @@ key(const tuple &t)
return std::get<i>(t).key;
}
template<class tuple,
size_t hash,
size_t i>
constexpr typename std::enable_if<i == size<tuple>(), size_t>::type
indexof()
{
return size<tuple>();
}
} // namespace json
} // namespace ircd
template<class tuple,
size_t hash,
size_t i = 0>
constexpr typename std::enable_if<i < size<tuple>(), size_t>::type
indexof()
{
constexpr auto equal
{
ircd::hash(key<tuple, i>()) == hash
};
#include "indexof.h"
return equal? i : indexof<tuple, hash, i + 1>();
}
template<class tuple,
const char *const &name,
size_t i>
constexpr typename std::enable_if<i == size<tuple>(), size_t>::type
indexof()
{
return size<tuple>();
}
template<class tuple,
const char *const &name,
size_t i = 0>
constexpr typename std::enable_if<i < size<tuple>(), size_t>::type
indexof()
{
return indexof<tuple, name_hash(name)>();
}
template<class tuple,
size_t i>
constexpr typename std::enable_if<i == size<tuple>(), size_t>::type
indexof(const char *const &name)
{
return size<tuple>();
}
template<class tuple,
size_t i = 0>
constexpr typename std::enable_if<i < size<tuple>(), size_t>::type
indexof(const char *const &name)
{
constexpr auto equal
{
_constexpr_equal(key<tuple, i>(), name)
};
return equal? i : indexof<tuple, i + 1>(name);
}
template<class tuple,
size_t i>
constexpr typename std::enable_if<i == size<tuple>(), size_t>::type
indexof(const string_view &name)
{
return size<tuple>();
}
template<class tuple,
size_t i = 0>
constexpr typename std::enable_if<i < size<tuple>(), size_t>::type
indexof(const string_view &name)
{
const auto equal
{
name == key<tuple, i>()
};
return equal? i : indexof<tuple, i + 1>(name);
}
template<class tuple>
constexpr bool
key_exists(const string_view &key)
{
return indexof<tuple>(key) < size<tuple>();
}
namespace ircd {
namespace json {
template<size_t i,
class tuple>
@ -240,610 +158,24 @@ val(const tuple &t)
return static_cast<const tuple_value_type<tuple, i> &>(std::get<i>(t));
}
template<class dst,
class src>
typename std::enable_if
<
std::is_base_of<json::string, dst>() &&
std::is_convertible<src, ircd::string_view>(),
void>::type
_assign(dst &d,
src&& s)
template<class tuple>
constexpr bool
key_exists(const string_view &key)
{
d = unquote(string_view{std::forward<src>(s)});
return indexof<tuple>(key) < size<tuple>();
}
template<class dst,
class src>
typename std::enable_if
<
!std::is_base_of<json::string, dst>() &&
std::is_convertible<src, dst>() &&
!ircd::json::is_tuple<dst>() &&
!std::is_same<bool, dst>(),
void>::type
_assign(dst &d,
src&& s)
{
d = std::forward<src>(s);
}
} // namespace json
} // namespace ircd
template<class dst,
class src>
typename std::enable_if
<
!std::is_base_of<json::string, dst>() &&
std::is_convertible<src, dst>() &&
!ircd::json::is_tuple<dst>() &&
std::is_same<bool, dst>(),
void>::type
_assign(dst &d,
src&& s)
{
static const is_zero test{};
d = !test(std::forward<src>(s));
}
#include "get.h"
#include "at.h"
#include "for_each.h"
#include "until.h"
#include "set.h"
template<class dst,
class src>
typename std::enable_if
<
std::is_arithmetic<dst>() &&
std::is_base_of<std::string_view, typename std::remove_reference<src>::type>() &&
!std::is_base_of<ircd::byte_view<ircd::string_view>, typename std::remove_reference<src>::type>(),
void>::type
_assign(dst &d,
src&& s)
try
{
d = lex_cast<dst>(std::forward<src>(s));
}
catch(const bad_lex_cast &e)
{
throw parse_error("cannot convert '%s' to '%s'",
demangle<src>(),
demangle<dst>());
}
template<class dst,
class src>
typename std::enable_if
<
std::is_arithmetic<dst>() &&
std::is_base_of<ircd::byte_view<ircd::string_view>, typename std::remove_reference<src>::type>(),
void>::type
_assign(dst &d,
src&& s)
{
assert(!s.empty());
d = byte_view<dst>(std::forward<src>(s));
}
template<class dst,
class src>
typename std::enable_if
<
std::is_base_of<std::string_view, dst>() &&
std::is_pod<typename std::remove_reference<src>::type>(),
void>::type
_assign(dst &d,
src&& s)
{
d = byte_view<string_view>(std::forward<src>(s));
}
template<class dst,
class src>
typename std::enable_if
<
ircd::json::is_tuple<dst>(),
void>::type
_assign(dst &d,
src&& s)
{
d = dst{std::forward<src>(s)};
}
template<size_t hash,
class tuple>
enable_if_tuple<tuple, const tuple_value_type<tuple, indexof<tuple, hash>()> &>
get(const tuple &t)
{
constexpr size_t idx
{
indexof<tuple, hash>()
};
const auto &ret
{
val<idx>(t)
};
return ret;
}
template<size_t hash,
class tuple>
enable_if_tuple<tuple, tuple_value_type<tuple, indexof<tuple, hash>()>>
get(const tuple &t,
const tuple_value_type<tuple, indexof<tuple, hash>()> &def)
{
constexpr size_t idx
{
indexof<tuple, hash>()
};
const auto &ret
{
val<idx>(t)
};
using value_type = tuple_value_type<tuple, idx>;
return defined(json::value(ret))? ret : def;
}
template<size_t hash,
class tuple>
enable_if_tuple<tuple, tuple_value_type<tuple, indexof<tuple, hash>()> &>
get(tuple &t)
{
constexpr size_t idx
{
indexof<tuple, hash>()
};
auto &ret
{
val<idx>(t)
};
return ret;
}
template<size_t hash,
class tuple>
enable_if_tuple<tuple, tuple_value_type<tuple, indexof<tuple, hash>()> &>
get(tuple &t,
tuple_value_type<tuple, indexof<tuple, hash>()> &def)
{
auto &ret
{
get<hash, tuple>(t)
};
using value_type = decltype(ret);
return defined(json::value(ret))? ret : def;
}
template<const char *const &name,
class tuple>
enable_if_tuple<tuple, const tuple_value_type<tuple, indexof<tuple, name>()> &>
get(const tuple &t)
{
return get<name_hash(name), tuple>(t);
}
template<const char *const &name,
class tuple>
enable_if_tuple<tuple, tuple_value_type<tuple, indexof<tuple, name>()>>
get(const tuple &t,
const tuple_value_type<tuple, indexof<tuple, name>()> &def)
{
return get<name_hash(name), tuple>(t, def);
}
template<const char *const &name,
class tuple>
enable_if_tuple<tuple, tuple_value_type<tuple, indexof<tuple, name>()>>
get(tuple &t)
{
return get<name_hash(name), tuple>(t);
}
template<const char *const &name,
class tuple>
enable_if_tuple<tuple, tuple_value_type<tuple, indexof<tuple, name>()>>
get(tuple &t,
tuple_value_type<tuple, indexof<tuple, hash>()> &def)
{
return get<name_hash(name), tuple>(t, def);
}
template<size_t hash,
class tuple>
enable_if_tuple<tuple, const tuple_value_type<tuple, indexof<tuple, hash>()> &>
at(const tuple &t)
{
constexpr size_t idx
{
indexof<tuple, hash>()
};
const auto &ret
{
val<idx>(t)
};
using value_type = tuple_value_type<tuple, idx>;
if(!defined(json::value(ret)))
throw not_found
{
"%s", key<idx>(t)
};
return ret;
}
template<size_t hash,
class tuple>
enable_if_tuple<tuple, tuple_value_type<tuple, indexof<tuple, hash>()> &>
at(tuple &t)
{
constexpr size_t idx
{
indexof<tuple, hash>()
};
auto &ret
{
val<idx>(t)
};
using value_type = tuple_value_type<tuple, idx>;
if(!defined(json::value(ret)))
throw not_found
{
"%s", key<idx>(t)
};
return ret;
}
template<const char *const &name,
class tuple>
enable_if_tuple<tuple, const tuple_value_type<tuple, indexof<tuple, name>()> &>
at(const tuple &t)
{
return at<name_hash(name), tuple>(t);
}
template<const char *const &name,
class tuple>
enable_if_tuple<tuple, tuple_value_type<tuple, indexof<tuple, name>()> &>
at(tuple &t)
{
return at<name_hash(name), tuple>(t);
}
template<class tuple,
class function,
size_t i>
typename std::enable_if<i == size<tuple>(), void>::type
at(tuple &t,
const string_view &name,
function&& f)
{
}
template<class tuple,
class function,
size_t i = 0>
typename std::enable_if<i < size<tuple>(), void>::type
at(tuple &t,
const string_view &name,
function&& f)
{
if(indexof<tuple>(name) == i)
f(val<i>(t));
else
at<tuple, function, i + 1>(t, name, std::forward<function>(f));
}
template<class tuple,
class function,
size_t i>
typename std::enable_if<i == size<tuple>(), void>::type
at(const tuple &t,
const string_view &name,
function&& f)
{
}
template<class tuple,
class function,
size_t i = 0>
typename std::enable_if<i < size<tuple>(), void>::type
at(const tuple &t,
const string_view &name,
function&& f)
{
if(indexof<tuple>(name) == i)
f(val<i>(t));
else
at<tuple, function, i + 1>(t, name, std::forward<function>(f));
}
template<size_t i,
class tuple,
class function>
typename std::enable_if<i == size<tuple>(), void>::type
for_each(const tuple &t,
function&& f)
{}
template<size_t i,
class tuple,
class function>
typename std::enable_if<i == size<tuple>(), void>::type
for_each(tuple &t,
function&& f)
{}
template<size_t i = 0,
class tuple,
class function>
typename std::enable_if<i < size<tuple>(), void>::type
for_each(const tuple &t,
function&& f)
{
f(key<i>(t), val<i>(t));
for_each<i + 1>(t, std::forward<function>(f));
}
template<size_t i = 0,
class tuple,
class function>
typename std::enable_if<i < size<tuple>(), void>::type
for_each(tuple &t,
function&& f)
{
f(key<i>(t), val<i>(t));
for_each<i + 1>(t, std::forward<function>(f));
}
template<class tuple,
class function>
void
for_each(const tuple &t,
const vector_view<const string_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<class tuple,
class function>
void
for_each(tuple &t,
const vector_view<const string_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<class tuple,
class function,
ssize_t i>
typename std::enable_if<(i < 0), void>::type
rfor_each(const tuple &t,
function&& f)
{}
template<class tuple,
class function,
ssize_t i>
typename std::enable_if<(i < 0), void>::type
rfor_each(tuple &t,
function&& f)
{}
template<class tuple,
class function,
ssize_t i = size<tuple>() - 1>
typename std::enable_if<i < tuple_size<tuple>(), void>::type
rfor_each(const tuple &t,
function&& f)
{
f(key<i>(t), val<i>(t));
rfor_each<tuple, function, i - 1>(t, std::forward<function>(f));
}
template<class tuple,
class function,
ssize_t i = size<tuple>() - 1>
typename std::enable_if<i < tuple_size<tuple>(), void>::type
rfor_each(tuple &t,
function&& f)
{
f(key<i>(t), val<i>(t));
rfor_each<tuple, function, i - 1>(t, std::forward<function>(f));
}
template<size_t i,
class tuple,
class function>
typename std::enable_if<i == size<tuple>(), bool>::type
until(const tuple &t,
function&& f)
{
return true;
}
template<size_t i,
class tuple,
class function>
typename std::enable_if<i == size<tuple>(), bool>::type
until(tuple &t,
function&& f)
{
return true;
}
template<size_t i = 0,
class tuple,
class function>
typename std::enable_if<i < size<tuple>(), bool>::type
until(const tuple &t,
function&& f)
{
return f(key<i>(t), val<i>(t))?
until<i + 1>(t, std::forward<function>(f)):
false;
}
template<size_t i = 0,
class tuple,
class function>
typename std::enable_if<i < size<tuple>(), bool>::type
until(tuple &t,
function&& f)
{
return f(key<i>(t), val<i>(t))?
until<i + 1>(t, std::forward<function>(f)):
false;
}
template<size_t i,
class tuple,
class function>
typename std::enable_if<i == size<tuple>(), bool>::type
until(const tuple &a,
const tuple &b,
function&& f)
{
return true;
}
template<size_t i = 0,
class tuple,
class function>
typename std::enable_if<i < size<tuple>(), bool>::type
until(const tuple &a,
const tuple &b,
function&& f)
{
return f(key<i>(a), val<i>(a), val<i>(b))?
until<i + 1>(a, b, std::forward<function>(f)):
false;
}
template<class tuple,
class function,
ssize_t i>
typename std::enable_if<(i < 0), bool>::type
runtil(const tuple &t,
function&& f)
{
return true;
}
template<class tuple,
class function,
ssize_t i>
typename std::enable_if<(i < 0), bool>::type
runtil(tuple &t,
function&& f)
{
return true;
}
template<class tuple,
class function,
ssize_t i = size<tuple>() - 1>
typename std::enable_if<i < size<tuple>(), bool>::type
runtil(const tuple &t,
function&& f)
{
return f(key<i>(t), val<i>(t))?
runtil<tuple, function, i - 1>(t, std::forward<function>(f)):
false;
}
template<class tuple,
class function,
ssize_t i = size<tuple>() - 1>
typename std::enable_if<i < size<tuple>(), bool>::type
runtil(tuple &t,
function&& f)
{
return f(key<i>(t), val<i>(t))?
runtil<tuple, function, i - 1>(t, std::forward<function>(f)):
false;
}
template<class V,
class... T>
tuple<T...> &
set(tuple<T...> &t,
const string_view &key,
V&& val)
try
{
at(t, key, [&key, &val]
(auto &target)
{
_assign(target, std::forward<V>(val));
});
return t;
}
catch(const std::exception &e)
{
throw parse_error("failed to set member '%s' (from %s): %s",
key,
demangle<V>(),
e.what());
}
template<class... T>
tuple<T...> &
set(tuple<T...> &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<class... T>
tuple<T...>::tuple(const json::object &object)
@ -948,83 +280,13 @@ _key_transform(const tuple<T...> &tuple,
return it;
}
template<class... T>
struct tuple<T...>::keys
:std::array<string_view, tuple<T...>::size()>
{
struct selection;
struct include;
struct exclude;
} // namespace json
} // namespace ircd
constexpr keys()
{
_key_transform<tuple<T...>>(this->begin(), this->end());
}
};
#include "keys.h"
template<class... T>
struct tuple<T...>::keys::selection
:std::bitset<tuple<T...>::size()>
{
template<class closure>
constexpr 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>
constexpr void for_each(closure &&function) const
{
this->until([&function](auto&& key)
{
function(key);
return true;
});
}
template<class it_a,
class it_b>
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<class... T>
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>
struct tuple<T...>::keys::exclude
:selection
{
constexpr exclude(const std::initializer_list<string_view> &list)
{
this->set();
for(const auto &key : list)
this->set(indexof<tuple<T...>>(key), false);
}
};
namespace ircd {
namespace json {
template<class it_a,
class it_b,

View file

@ -0,0 +1,130 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
//
// 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<size_t i,
class tuple,
class function>
typename std::enable_if<i == size<tuple>(), bool>::type
until(const tuple &t,
function&& f)
{
return true;
}
template<size_t i,
class tuple,
class function>
typename std::enable_if<i == size<tuple>(), bool>::type
until(tuple &t,
function&& f)
{
return true;
}
template<size_t i = 0,
class tuple,
class function>
typename std::enable_if<i < size<tuple>(), bool>::type
until(const tuple &t,
function&& f)
{
return f(key<i>(t), val<i>(t))?
until<i + 1>(t, std::forward<function>(f)):
false;
}
template<size_t i = 0,
class tuple,
class function>
typename std::enable_if<i < size<tuple>(), bool>::type
until(tuple &t,
function&& f)
{
return f(key<i>(t), val<i>(t))?
until<i + 1>(t, std::forward<function>(f)):
false;
}
template<size_t i,
class tuple,
class function>
typename std::enable_if<i == size<tuple>(), bool>::type
until(const tuple &a,
const tuple &b,
function&& f)
{
return true;
}
template<size_t i = 0,
class tuple,
class function>
typename std::enable_if<i < size<tuple>(), bool>::type
until(const tuple &a,
const tuple &b,
function&& f)
{
return f(key<i>(a), val<i>(a), val<i>(b))?
until<i + 1>(a, b, std::forward<function>(f)):
false;
}
template<class tuple,
class function,
ssize_t i>
typename std::enable_if<(i < 0), bool>::type
runtil(const tuple &t,
function&& f)
{
return true;
}
template<class tuple,
class function,
ssize_t i>
typename std::enable_if<(i < 0), bool>::type
runtil(tuple &t,
function&& f)
{
return true;
}
template<class tuple,
class function,
ssize_t i = size<tuple>() - 1>
typename std::enable_if<i < size<tuple>(), bool>::type
runtil(const tuple &t,
function&& f)
{
return f(key<i>(t), val<i>(t))?
runtil<tuple, function, i - 1>(t, std::forward<function>(f)):
false;
}
template<class tuple,
class function,
ssize_t i = size<tuple>() - 1>
typename std::enable_if<i < size<tuple>(), bool>::type
runtil(tuple &t,
function&& f)
{
return f(key<i>(t), val<i>(t))?
runtil<tuple, function, i - 1>(t, std::forward<function>(f)):
false;
}
} // namespace json
} // namespace ircd