diff options
Diffstat (limited to 'Source/cmJSONHelpers.h')
| -rw-r--r-- | Source/cmJSONHelpers.h | 494 |
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)...); + }; + } +}; |
