summaryrefslogtreecommitdiffstats
path: root/Source/cmJSONHelpers.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmJSONHelpers.h')
-rw-r--r--Source/cmJSONHelpers.h494
1 files changed, 241 insertions, 253 deletions
diff --git a/Source/cmJSONHelpers.h b/Source/cmJSONHelpers.h
index 6690aef..48decbc 100644
--- a/Source/cmJSONHelpers.h
+++ b/Source/cmJSONHelpers.h
@@ -14,146 +14,126 @@
#include <cm3p/json/value.h>
-template <typename T, typename E>
-using cmJSONHelper = std::function<E(T& out, const Json::Value* value)>;
+template <typename T, typename E, typename... CallState>
+using cmJSONHelper =
+ std::function<E(T& out, const Json::Value* value, CallState&&... state)>;
-template <typename T, typename E>
-class cmJSONObjectHelper
+template <typename E, typename... CallState>
+struct cmJSONHelperBuilder
{
-public:
- cmJSONObjectHelper(E&& success, E&& fail, bool allowExtra = true);
-
- template <typename U, typename M, typename F>
- cmJSONObjectHelper& Bind(const cm::string_view& name, M U::*member, F func,
- bool required = true);
- template <typename M, typename F>
- cmJSONObjectHelper& Bind(const cm::string_view& name, std::nullptr_t, F func,
- bool required = true);
- template <typename F>
- cmJSONObjectHelper& Bind(const cm::string_view& name, F func,
- bool required = true);
-
- E operator()(T& out, const Json::Value* value) const;
-
-private:
- // Not a true cmJSONHelper, it just happens to match the signature
- using MemberFunction = std::function<E(T& out, const Json::Value* value)>;
- struct Member
+ template <typename T>
+ class Object
{
- cm::string_view Name;
- MemberFunction Function;
- bool Required;
- };
- std::vector<Member> Members;
- bool AnyRequired = false;
- E Success;
- E Fail;
- bool AllowExtra;
-
- cmJSONObjectHelper& BindPrivate(const cm::string_view& name,
- MemberFunction&& func, bool required);
-};
-
-template <typename T, typename E>
-cmJSONObjectHelper<T, E>::cmJSONObjectHelper(E&& success, E&& fail,
- bool allowExtra)
- : Success(std::move(success))
- , Fail(std::move(fail))
- , AllowExtra(allowExtra)
-{
-}
+ public:
+ Object(E&& success, E&& fail, bool allowExtra = true)
+ : Success(std::move(success))
+ , Fail(std::move(fail))
+ , AllowExtra(allowExtra)
+ {
+ }
-template <typename T, typename E>
-template <typename U, typename M, typename F>
-cmJSONObjectHelper<T, E>& cmJSONObjectHelper<T, E>::Bind(
- const cm::string_view& name, M U::*member, F func, bool required)
-{
- return this->BindPrivate(
- name,
- [func, member](T& out, const Json::Value* value) -> E {
- return func(out.*member, value);
- },
- required);
-}
+ template <typename U, typename M, typename F>
+ Object& Bind(const cm::string_view& name, M U::*member, F func,
+ bool required = true)
+ {
+ return this->BindPrivate(name,
+ [func, member](T& out, const Json::Value* value,
+ CallState&&... state) -> E {
+ return func(out.*member, value,
+ std::forward(state)...);
+ },
+ required);
+ }
+ template <typename M, typename F>
+ Object& Bind(const cm::string_view& name, std::nullptr_t, F func,
+ bool required = true)
+ {
+ return this->BindPrivate(name,
+ [func](T& /*out*/, const Json::Value* value,
+ CallState&&... state) -> E {
+ M dummy;
+ return func(dummy, value,
+ std::forward(state)...);
+ },
+ required);
+ }
+ template <typename F>
+ Object& Bind(const cm::string_view& name, F func, bool required = true)
+ {
+ return this->BindPrivate(name, MemberFunction(func), required);
+ }
-template <typename T, typename E>
-template <typename M, typename F>
-cmJSONObjectHelper<T, E>& cmJSONObjectHelper<T, E>::Bind(
- const cm::string_view& name, std::nullptr_t, F func, bool required)
-{
- return this->BindPrivate(name,
- [func](T& /*out*/, const Json::Value* value) -> E {
- M dummy;
- return func(dummy, value);
- },
- required);
-}
+ E operator()(T& out, const Json::Value* value, CallState&&... state) const
+ {
+ if (!value && this->AnyRequired) {
+ return this->Fail;
+ }
+ if (value && !value->isObject()) {
+ return this->Fail;
+ }
+ Json::Value::Members extraFields;
+ if (value) {
+ extraFields = value->getMemberNames();
+ }
-template <typename T, typename E>
-template <typename F>
-cmJSONObjectHelper<T, E>& cmJSONObjectHelper<T, E>::Bind(
- const cm::string_view& name, F func, bool required)
-{
- return this->BindPrivate(name, MemberFunction(func), required);
-}
+ for (auto const& m : this->Members) {
+ std::string name(m.Name.data(), m.Name.size());
+ if (value && value->isMember(name)) {
+ E result = m.Function(out, &(*value)[name], std::forward(state)...);
+ if (result != this->Success) {
+ return result;
+ }
+ extraFields.erase(
+ std::find(extraFields.begin(), extraFields.end(), name));
+ } else if (!m.Required) {
+ E result = m.Function(out, nullptr, std::forward(state)...);
+ if (result != this->Success) {
+ return result;
+ }
+ } else {
+ return this->Fail;
+ }
+ }
-template <typename T, typename E>
-cmJSONObjectHelper<T, E>& cmJSONObjectHelper<T, E>::BindPrivate(
- const cm::string_view& name, MemberFunction&& func, bool required)
-{
- Member m;
- m.Name = name;
- m.Function = std::move(func);
- m.Required = required;
- this->Members.push_back(std::move(m));
- if (required) {
- this->AnyRequired = true;
- }
- return *this;
-}
+ return this->AllowExtra || extraFields.empty() ? this->Success
+ : this->Fail;
+ }
-template <typename T, typename E>
-E cmJSONObjectHelper<T, E>::operator()(T& out, const Json::Value* value) const
-{
- if (!value && this->AnyRequired) {
- return this->Fail;
- }
- if (value && !value->isObject()) {
- return this->Fail;
- }
- Json::Value::Members extraFields;
- if (value) {
- extraFields = value->getMemberNames();
- }
+ private:
+ // Not a true cmJSONHelper, it just happens to match the signature
+ using MemberFunction =
+ std::function<E(T& out, const Json::Value* value, CallState&&... state)>;
+ struct Member
+ {
+ cm::string_view Name;
+ MemberFunction Function;
+ bool Required;
+ };
+ std::vector<Member> Members;
+ bool AnyRequired = false;
+ E Success;
+ E Fail;
+ bool AllowExtra;
- for (auto const& m : this->Members) {
- std::string name(m.Name.data(), m.Name.size());
- if (value && value->isMember(name)) {
- E result = m.Function(out, &(*value)[name]);
- if (result != this->Success) {
- return result;
- }
- extraFields.erase(
- std::find(extraFields.begin(), extraFields.end(), name));
- } else if (!m.Required) {
- E result = m.Function(out, nullptr);
- if (result != this->Success) {
- return result;
+ Object& BindPrivate(const cm::string_view& name, MemberFunction&& func,
+ bool required)
+ {
+ Member m;
+ m.Name = name;
+ m.Function = std::move(func);
+ m.Required = required;
+ this->Members.push_back(std::move(m));
+ if (required) {
+ this->AnyRequired = true;
}
- } else {
- return this->Fail;
+ return *this;
}
- }
-
- return this->AllowExtra || extraFields.empty() ? this->Success : this->Fail;
-}
-
-template <typename E>
-cmJSONHelper<std::string, E> cmJSONStringHelper(E success, E fail,
- const std::string& defval = "")
-{
- return
- [success, fail, defval](std::string& out, const Json::Value* value) -> E {
+ };
+ static cmJSONHelper<std::string, E, CallState...> String(
+ E success, E fail, const std::string& defval = "")
+ {
+ return [success, fail, defval](std::string& out, const Json::Value* value,
+ CallState&&... /*state*/) -> E {
if (!value) {
out = defval;
return success;
@@ -164,30 +144,30 @@ cmJSONHelper<std::string, E> cmJSONStringHelper(E success, E fail,
out = value->asString();
return success;
};
-}
+ }
-template <typename E>
-cmJSONHelper<int, E> cmJSONIntHelper(E success, E fail, int defval = 0)
-{
- return [success, fail, defval](int& out, const Json::Value* value) -> E {
- if (!value) {
- out = defval;
+ static cmJSONHelper<int, E, CallState...> Int(E success, E fail,
+ int defval = 0)
+ {
+ return [success, fail, defval](int& out, const Json::Value* value,
+ CallState&&... /*state*/) -> E {
+ if (!value) {
+ out = defval;
+ return success;
+ }
+ if (!value->isInt()) {
+ return fail;
+ }
+ out = value->asInt();
return success;
- }
- if (!value->isInt()) {
- return fail;
- }
- out = value->asInt();
- return success;
- };
-}
+ };
+ }
-template <typename E>
-cmJSONHelper<unsigned int, E> cmJSONUIntHelper(E success, E fail,
- unsigned int defval = 0)
-{
- return
- [success, fail, defval](unsigned int& out, const Json::Value* value) -> E {
+ static cmJSONHelper<unsigned int, E, CallState...> UInt(
+ E success, E fail, unsigned int defval = 0)
+ {
+ return [success, fail, defval](unsigned int& out, const Json::Value* value,
+ CallState&&... /*state*/) -> E {
if (!value) {
out = defval;
return success;
@@ -198,118 +178,126 @@ cmJSONHelper<unsigned int, E> cmJSONUIntHelper(E success, E fail,
out = value->asUInt();
return success;
};
-}
+ }
-template <typename E>
-cmJSONHelper<bool, E> cmJSONBoolHelper(E success, E fail, bool defval = false)
-{
- return [success, fail, defval](bool& out, const Json::Value* value) -> E {
- if (!value) {
- out = defval;
+ static cmJSONHelper<bool, E, CallState...> Bool(E success, E fail,
+ bool defval = false)
+ {
+ return [success, fail, defval](bool& out, const Json::Value* value,
+ CallState&&... /*state*/) -> E {
+ if (!value) {
+ out = defval;
+ return success;
+ }
+ if (!value->isBool()) {
+ return fail;
+ }
+ out = value->asBool();
return success;
- }
- if (!value->isBool()) {
- return fail;
- }
- out = value->asBool();
- return success;
- };
-}
+ };
+ }
-template <typename T, typename E, typename F, typename Filter>
-cmJSONHelper<std::vector<T>, E> cmJSONVectorFilterHelper(E success, E fail,
- F func, Filter filter)
-{
- return [success, fail, func, filter](std::vector<T>& out,
- const Json::Value* value) -> E {
- if (!value) {
- out.clear();
- return success;
- }
- if (!value->isArray()) {
- return fail;
- }
- out.clear();
- for (auto const& item : *value) {
- T t;
- E result = func(t, &item);
- if (result != success) {
- return result;
+ template <typename T, typename F, typename Filter>
+ static cmJSONHelper<std::vector<T>, E, CallState...> VectorFilter(
+ E success, E fail, F func, Filter filter)
+ {
+ return [success, fail, func, filter](std::vector<T>& out,
+ const Json::Value* value,
+ CallState&&... state) -> E {
+ if (!value) {
+ out.clear();
+ return success;
}
- if (!filter(t)) {
- continue;
+ if (!value->isArray()) {
+ return fail;
}
- out.push_back(std::move(t));
- }
- return success;
- };
-}
-
-template <typename T, typename E, typename F>
-cmJSONHelper<std::vector<T>, E> cmJSONVectorHelper(E success, E fail, F func)
-{
- return cmJSONVectorFilterHelper<T, E, F>(success, fail, func,
- [](const T&) { return true; });
-}
-
-template <typename T, typename E, typename F, typename Filter>
-cmJSONHelper<std::map<std::string, T>, E> cmJSONMapFilterHelper(E success,
- E fail, F func,
- Filter filter)
-{
- return [success, fail, func, filter](std::map<std::string, T>& out,
- const Json::Value* value) -> E {
- if (!value) {
out.clear();
+ for (auto const& item : *value) {
+ T t;
+ E result = func(t, &item, std::forward(state)...);
+ if (result != success) {
+ return result;
+ }
+ if (!filter(t)) {
+ continue;
+ }
+ out.push_back(std::move(t));
+ }
return success;
- }
- if (!value->isObject()) {
- return fail;
- }
- out.clear();
- for (auto const& key : value->getMemberNames()) {
- if (!filter(key)) {
- continue;
+ };
+ }
+
+ template <typename T, typename F>
+ static cmJSONHelper<std::vector<T>, E, CallState...> Vector(E success,
+ E fail, F func)
+ {
+ return VectorFilter<T, F>(success, fail, func,
+ [](const T&) { return true; });
+ }
+
+ template <typename T, typename F, typename Filter>
+ static cmJSONHelper<std::map<std::string, T>, E, CallState...> MapFilter(
+ E success, E fail, F func, Filter filter)
+ {
+ return [success, fail, func, filter](std::map<std::string, T>& out,
+ const Json::Value* value,
+ CallState&&... state) -> E {
+ if (!value) {
+ out.clear();
+ return success;
}
- T t;
- E result = func(t, &(*value)[key]);
- if (result != success) {
- return result;
+ if (!value->isObject()) {
+ return fail;
}
- out[key] = std::move(t);
- }
- return success;
- };
-}
+ out.clear();
+ for (auto const& key : value->getMemberNames()) {
+ if (!filter(key)) {
+ continue;
+ }
+ T t;
+ E result = func(t, &(*value)[key], std::forward(state)...);
+ if (result != success) {
+ return result;
+ }
+ out[key] = std::move(t);
+ }
+ return success;
+ };
+ }
-template <typename T, typename E, typename F>
-cmJSONHelper<std::map<std::string, T>, E> cmJSONMapHelper(E success, E fail,
- F func)
-{
- return cmJSONMapFilterHelper<T, E, F>(
- success, fail, func, [](const std::string&) { return true; });
-}
+ template <typename T, typename F>
+ static cmJSONHelper<std::map<std::string, T>, E, CallState...> Map(E success,
+ E fail,
+ F func)
+ {
+ return MapFilter<T, F>(success, fail, func,
+ [](const std::string&) { return true; });
+ }
-template <typename T, typename E, typename F>
-cmJSONHelper<cm::optional<T>, E> cmJSONOptionalHelper(E success, F func)
-{
- return [success, func](cm::optional<T>& out, const Json::Value* value) -> E {
- if (!value) {
- out.reset();
- return success;
- }
- out.emplace();
- return func(*out, value);
- };
-}
+ template <typename T, typename F>
+ static cmJSONHelper<cm::optional<T>, E, CallState...> Optional(E success,
+ F func)
+ {
+ return [success, func](cm::optional<T>& out, const Json::Value* value,
+ CallState&&... state) -> E {
+ if (!value) {
+ out.reset();
+ return success;
+ }
+ out.emplace();
+ return func(*out, value, std::forward(state)...);
+ };
+ }
-template <typename T, typename E, typename F>
-cmJSONHelper<T, E> cmJSONRequiredHelper(E fail, F func)
-{
- return [fail, func](T& out, const Json::Value* value) -> E {
- if (!value) {
- return fail;
- }
- return func(out, value);
- };
-}
+ template <typename T, typename F>
+ static cmJSONHelper<T, E, CallState...> Required(E fail, F func)
+ {
+ return [fail, func](T& out, const Json::Value* value,
+ CallState&&... state) -> E {
+ if (!value) {
+ return fail;
+ }
+ return func(out, value, std::forward(state)...);
+ };
+ }
+};