0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-02 18:18:56 +02:00

ircd::json: Reduce iov interface; make conditional nodes evaluate conditionally.

This commit is contained in:
Jason Volk 2018-06-05 11:16:52 -07:00
parent f1443752c5
commit 5146ddf67e
2 changed files with 114 additions and 75 deletions

View file

@ -45,6 +45,7 @@ struct ircd::json::iov
struct set_if;
struct defaults;
struct defaults_if;
using conditional_member = std::pair<string_view, std::function<json::value ()>>;
IRCD_EXCEPTION(json::error, error);
IRCD_EXCEPTION(error, exists);
@ -71,10 +72,8 @@ struct ircd::json::iov::push
operator const member &() const;
operator member &();
push(iov &iov, member m)
:node(iov, std::move(m))
{}
push(iov &, const bool &, const conditional_member &);
push(iov &iov, member m);
push() = default;
};
@ -82,51 +81,29 @@ struct ircd::json::iov::push
struct ircd::json::iov::add
:protected ircd::json::iov::node
{
add(iov &, const bool &, const conditional_member &);
add(iov &, member);
add() = default;
};
/// iov::add only if the bool argument is true for your condition
struct ircd::json::iov::add_if
:protected ircd::json::iov::node
{
add_if(iov &, const bool &, const string_view &, const std::function<json::value ()> &);
add_if(iov &, const bool &, member);
add_if() = default;
};
/// Add or overwrite a member in the object vector.
struct ircd::json::iov::set
:protected ircd::json::iov::node
{
set(iov &, const bool &, const conditional_member &);
set(iov &, member);
set() = default;
};
/// iov::set only if the bool argument is true for your condition
struct ircd::json::iov::set_if
:protected ircd::json::iov::node
{
set_if(iov &, const bool &, member);
set_if() = default;
};
/// Add member to the object vector if doesn't exist; otherwise ignored
struct ircd::json::iov::defaults
:protected ircd::json::iov::node
{
defaults(iov &, bool, const conditional_member &);
defaults(iov &, member);
defaults() = default;
};
/// iov::defaults only if the bool argument is true for your condition
struct ircd::json::iov::defaults_if
:protected ircd::json::iov::node
{
defaults_if(iov &, const bool &, member);
defaults_if() = default;
};
inline ircd::json::iov::push::operator
ircd::json::member &()
{

View file

@ -1041,6 +1041,31 @@ const
});
}
ircd::json::iov::push::push(iov &iov,
member member)
:node
{
iov, std::move(member)
}
{
}
ircd::json::iov::push::push(iov &iov,
const bool &b,
const conditional_member &cp)
:node
{
b?
&iov:
nullptr,
b?
member{cp.first, cp.second()}:
member{}
}
{
}
ircd::json::iov::add::add(iov &iov,
member member)
:node
@ -1048,8 +1073,11 @@ ircd::json::iov::add::add(iov &iov,
iov, [&iov, &member]
{
if(iov.has(member.first))
throw exists("failed to add member '%s': already exists",
string_view{member.first});
throw exists
{
"failed to add member '%s': already exists",
string_view{member.first}
};
return std::move(member);
}()
@ -1057,32 +1085,38 @@ ircd::json::iov::add::add(iov &iov,
{
}
ircd::json::iov::add_if::add_if(iov &iov,
const bool &b,
member member)
ircd::json::iov::add::add(iov &iov,
const bool &b,
const conditional_member &cp)
:node
{
iov, std::move(member)
b?
&iov:
nullptr,
[&iov, &b, &cp]
{
if(!b)
return member{};
if(iov.has(cp.first))
throw exists
{
"failed to add member '%s': already exists",
string_view{cp.first}
};
return member
{
cp.first, cp.second()
};
}()
}
{
if(!b)
iov.pop_front();
}
ircd::json::iov::add_if::add_if(iov &iov,
const bool &b,
const string_view &key,
const std::function<json::value ()> &val)
:node
{
iov, b? member{key, val()} : member{}
}
{
if(!b)
iov.pop_front();
}
ircd::json::iov::set::set(iov &iov, member member)
ircd::json::iov::set::set(iov &iov,
member member)
:node
{
iov, [&iov, &member]
@ -1098,48 +1132,76 @@ ircd::json::iov::set::set(iov &iov, member member)
{
}
ircd::json::iov::set_if::set_if(iov &iov,
const bool &b,
member member)
ircd::json::iov::set::set(iov &iov,
const bool &b,
const conditional_member &cp)
:node
{
iov, std::move(member)
b?
&iov:
nullptr,
[&iov, &b, &cp]
{
if(!b)
return member{};
iov.remove_if([&cp](const auto &existing)
{
return string_view{existing.first} == cp.first;
});
return member
{
cp.first, cp.second()
};
}()
}
{
if(!b)
iov.pop_front();
}
ircd::json::iov::defaults::defaults(iov &iov,
member member)
:node
{
iov, std::move(member)
!iov.has(member.first)?
&iov:
nullptr,
std::move(member)
}
{
const auto count
{
std::count_if(std::begin(iov), std::end(iov), [&member]
(const auto &existing)
{
return string_view{existing.first} == string_view{member.first};
})
};
if(count > 1)
iov.pop_front();
}
ircd::json::iov::defaults_if::defaults_if(iov &iov,
const bool &b,
member member)
ircd::json::iov::defaults::defaults(iov &iov,
bool b,
const conditional_member &cp)
:node
{
iov, std::move(member)
[&iov, &b, &cp]() -> json::iov *
{
if(!b)
return nullptr;
if(!iov.has(cp.first))
return &iov;
b = false;
return nullptr;
}(),
[&iov, &b, &cp]
{
if(!b)
return member{};
return member
{
cp.first, cp.second()
};
}()
}
{
if(!b)
iov.pop_front();
}
///////////////////////////////////////////////////////////////////////////////