diff --git a/include/ircd/json/iov.h b/include/ircd/json/iov.h index ab1559a0f..cc662256a 100644 --- a/include/ircd/json/iov.h +++ b/include/ircd/json/iov.h @@ -54,6 +54,8 @@ struct ircd::json::iov struct add_if; struct set; struct set_if; + struct defaults; + struct defaults_if; public: bool has(const string_view &key) const; @@ -103,3 +105,19 @@ struct ircd::json::iov::set_if 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 &, 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; +}; diff --git a/ircd/json.cc b/ircd/json.cc index 57b7b3e5c..c938d7560 100644 --- a/ircd/json.cc +++ b/ircd/json.cc @@ -434,6 +434,38 @@ ircd::json::iov::set_if::set_if(iov &iov, iov.pop_front(); } +ircd::json::iov::defaults::defaults(iov &iov, + member member) +:node +{ + iov, 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) +:node +{ + iov, std::move(member) +} +{ + if(!b) + iov.pop_front(); +} + /////////////////////////////////////////////////////////////////////////////// // // json/member.h