Mercurial > irccd
changeset 649:4a13a016ea4f
Irccd: use new json_util::parser class
line wrap: on
line diff
--- a/irccdctl/cli.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/irccdctl/cli.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -36,7 +36,7 @@ if (code) throw boost::system::system_error(code); - const auto c = json_util::get_string(message, "/command"_json_pointer); + const auto c = json_util::parser(message).get<std::string>("command"); if (!c) { recv_response(ctl, std::move(req), std::move(handler));
--- a/irccdctl/main.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/irccdctl/main.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -514,9 +514,10 @@ throw boost::system::system_error(code); if (verbose) { - const auto major = json_util::get_int(info, "/major"_json_pointer); - const auto minor = json_util::get_int(info, "/minor"_json_pointer); - const auto patch = json_util::get_int(info, "/patch"_json_pointer); + const json_util::parser parser(info); + const auto major = parser.get<int>("/major"); + const auto minor = parser.get<int>("/minor"); + const auto patch = parser.get<int>("/patch"); if (!major || !minor || !patch) std::cout << "connected to irccd (unknown version)" << std::endl;
--- a/irccdctl/plugin_info_cli.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/irccdctl/plugin_info_cli.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -35,15 +35,17 @@ throw std::invalid_argument("plugin-info requires 1 argument"); request(ctl, {{ "plugin", args[0] }}, [] (auto result) { + const json_util::parser parser(result); + std::cout << std::boolalpha; std::cout << "Author : " << - json_util::get_string(result, "/author"_json_pointer).value_or("(unknown)") << std::endl; + parser.get<std::string>("author").value_or("(unknown)") << std::endl; std::cout << "License : " << - json_util::get_string(result, "/license"_json_pointer).value_or("(unknown)") << std::endl; + parser.get<std::string>("license").value_or("(unknown)") << std::endl; std::cout << "Summary : " << - json_util::get_string(result, "/summary"_json_pointer).value_or("(unknown)") << std::endl; + parser.get<std::string>("summary").value_or("(unknown)") << std::endl; std::cout << "Version : " << - json_util::get_string(result, "/version"_json_pointer).value_or("(unknown)") << std::endl; + parser.get<std::string>("version").value_or("(unknown)") << std::endl; }); }
--- a/irccdctl/watch_cli.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/irccdctl/watch_cli.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -181,7 +181,7 @@ if (code) throw boost::system::system_error(code); - const auto event = json_util::get_string(message, "/event"_json_pointer); + const auto event = json_util::parser(message).get<std::string>("event"); const auto it = events.find(event ? *event : ""); if (it != events.end()) {
--- a/libcommon/irccd/json_util.hpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libcommon/irccd/json_util.hpp Mon Mar 26 20:30:15 2018 +0200 @@ -16,8 +16,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifndef IRCCD_COMMON_JSON_UTIL_HPP -#define IRCCD_COMMON_JSON_UTIL_HPP +#ifndef IRCCD_JSON_UTIL_HPP +#define IRCCD_JSON_UTIL_HPP /** * \file json_util.hpp @@ -25,7 +25,9 @@ */ #include <cstdint> +#include <limits> #include <string> +#include <type_traits> #include <boost/optional.hpp> @@ -39,214 +41,282 @@ namespace json_util { /** - * Get a JSON value from the given object or array. - * - * \param json the JSON object/array - * \param key the pointer to the object - * \return the value or boost::none if not found + * \cond JSON_UTIL_HIDDEN_SYMBOLS */ -inline boost::optional<nlohmann::json> get(const nlohmann::json& json, - const nlohmann::json::json_pointer& key) noexcept -{ - // Unfortunately, there is no find using pointer yet. - try { - return json.at(key); - } catch (...) { - return boost::none; + +namespace detail { + +template <typename Int> +class parser_type_traits_uint : public std::true_type { +public: + static boost::optional<Int> get(const nlohmann::json& value) noexcept + { + if (!value.is_number_unsigned()) + return boost::none; + + const auto ret = value.get<std::uint64_t>(); + + if (ret > std::numeric_limits<Int>::max()) + return boost::none; + + return static_cast<Int>(ret); } -} +}; + +template <typename Int> +class parser_type_traits_int : public std::true_type { +public: + static boost::optional<Int> get(const nlohmann::json& value) noexcept + { + if (!value.is_number_integer()) + return boost::none; + + const auto ret = value.get<std::int64_t>(); + + if (ret < std::numeric_limits<Int>::min() || ret > std::numeric_limits<Int>::max()) + return boost::none; + + return static_cast<Int>(ret); + } +}; + +} // !detail /** - * Convenient overload with simple key. - * - * \param json the JSON object/array - * \param key the pointer to the object - * \return the value or boost::none if not found + * \endcond */ -inline boost::optional<nlohmann::json> get(const nlohmann::json& json, - const std::string& key) noexcept -{ - const auto it = json.find(key); - - if (it == json.end()) - return boost::none; - - return *it; -} /** - * Get a bool or null if not found or invalid. + * \brief Describe how to convert a JSON value. + * + * This class must be specialized for every type you want to convert from JSON + * to its native type. + * + * You only need to implement the get function with the following signature: * - * \param json the JSON object/array - * \param key the pointer or property key - * \return the value or boost::none if not found or invalid + * ```cpp + * static boost::optional<T> get(const nlohmann::json& value); + * ``` + * + * The implementation should not throw an exception but return a null optional + * instead. + * + * This class is already specialized for the given types: + * + * - bool + * - double + * - std::uint(8, 16, 32, 64) + * - std::string */ -template <typename Key> -inline boost::optional<bool> get_bool(const nlohmann::json& json, const Key& key) noexcept -{ - const auto v = get(json, key); - - if (!v || !v->is_boolean()) - return boost::none; - - return v->template get<bool>(); -} +template <typename T> +class parser_type_traits : public std::false_type { +}; /** - * Get a 64 bit signed integer or null if not found or invalid. - * - * \param json the JSON object/array - * \param key the pointer or property key - * \return the value or boost::none if not found or invalid + * \brief Specialization for `bool`. */ -template <typename Key> -inline boost::optional<std::int64_t> get_int(const nlohmann::json& json, const Key& key) noexcept -{ - const auto v = get(json, key); +template <> +class parser_type_traits<bool> : public std::true_type { +public: + /** + * Convert the JSON value to bool. + * + * \return the bool or none if not a boolean type + */ + static boost::optional<bool> get(const nlohmann::json& value) noexcept + { + if (!value.is_boolean()) + return boost::none; - if (!v || !v->is_number_integer()) - return boost::none; - - return v->template get<std::int64_t>(); -} + return value.get<bool>(); + } +}; /** - * Get a 64 bit unsigned integer or null if not found or invalid. - * - * \param json the JSON object/array - * \param key the pointer or property key - * \return the value or boost::none if not found or invalid + * \brief Specialization for `double`. */ -template <typename Key> -inline boost::optional<std::uint64_t> get_uint(const nlohmann::json& json, const Key& key) noexcept -{ - const auto v = get(json, key); +template <> +class parser_type_traits<double> : public std::true_type { +public: + /** + * Convert the JSON value to bool. + * + * \return the double or none if not a double type + */ + static boost::optional<double> get(const nlohmann::json& value) noexcept + { + if (!value.is_number_float()) + return boost::none; + + return value.get<double>(); + } +}; - if (!v || !v->is_number_unsigned()) - return boost::none; +/** + * \brief Specialization for `std::string`. + */ +template <> +class parser_type_traits<std::string> : public std::true_type { +public: + /** + * Convert the JSON value to bool. + * + * \return the string or none if not a string type + */ + static boost::optional<std::string> get(const nlohmann::json& value) + { + if (!value.is_string()) + return boost::none; - return v->template get<std::uint64_t>(); -} + return value.get<std::string>(); + } +}; /** - * Get a string or null if not found or invalid. - * - * \param json the JSON object/array - * \param key the pointer or property key - * \return the value or boost::none if not found or invalid + * \brief Specialization for `std::int8_t`. + */ +template <> +class parser_type_traits<std::int8_t> : public detail::parser_type_traits_int<std::int8_t> { +}; + +/** + * \brief Specialization for `std::int16_t`. */ -template <typename Key> -inline boost::optional<std::string> get_string(const nlohmann::json& json, const Key& key) noexcept -{ - const auto v = get(json, key); +template <> +class parser_type_traits<std::int16_t> : public detail::parser_type_traits_int<std::int16_t> { +}; - if (!v || !v->is_string()) - return boost::none; - - return v->template get<std::string>(); -} +/** + * \brief Specialization for `std::int32_t`. + */ +template <> +class parser_type_traits<std::int32_t> : public detail::parser_type_traits_int<std::int32_t> { +}; /** - * Get an optional bool. - * - * If the property is not found, return default value. If the property is not - * a bool, return boost::none, otherwise return the value. - * - * \param json the JSON object/array - * \param key the pointer or property key - * \param def the default value - * \return the value, boost::none or def + * \brief Specialization for `std::int64_t`. */ -template <typename Key> -inline boost::optional<bool> optional_bool(const nlohmann::json& json, const Key& key, bool def = false) noexcept -{ - const auto v = get(json, key); +template <> +class parser_type_traits<std::int64_t> : public std::true_type { +public: + /** + * Convert the JSON value to std::int64_t. + * + * \return the int or none if not a int type + */ + static boost::optional<std::int64_t> get(const nlohmann::json& value) noexcept + { + if (!value.is_number_integer()) + return boost::none; + + return value.get<std::int64_t>(); + } +}; - if (!v) - return def; - if (!v->is_boolean()) - return boost::none; +/** + * \brief Specialization for `std::int8_t`. + */ +template <> +class parser_type_traits<std::uint8_t> : public detail::parser_type_traits_uint<std::uint8_t> { +}; - return v->template get<bool>(); -} +/** + * \brief Specialization for `std::int16_t`. + */ +template <> +class parser_type_traits<std::uint16_t> : public detail::parser_type_traits_uint<std::uint16_t> { +}; + +/** + * \brief Specialization for `std::int32_t`. + */ +template <> +class parser_type_traits<std::uint32_t> : public detail::parser_type_traits_uint<std::uint32_t> { +}; /** - * Get an optional integer. - * - * If the property is not found, return default value. If the property is not - * an integer, return boost::none, otherwise return the value. - * - * \param json the JSON object/array - * \param key the pointer or property key - * \param def the default value - * \return the value, boost::none or def + * \brief Specialization for `std::int64_t`. */ -template <typename Key> -inline boost::optional<std::int64_t> optional_int(const nlohmann::json& json, - const Key& key, - std::int64_t def = 0) noexcept -{ - const auto v = get(json, key); +template <> +class parser_type_traits<std::uint64_t> : public std::true_type { +public: + /** + * Convert the JSON value to std::uint64_t. + * + * \return the int or none if not a int type + */ + static boost::optional<std::uint64_t> get(const nlohmann::json& value) noexcept + { + if (!value.is_number_unsigned()) + return boost::none; - if (!v) - return def; - if (!v->is_number_integer()) - return boost::none; - - return v->template get<std::int64_t>(); -} + return value.get<std::uint64_t>(); + } +}; /** - * Get an optional unsigned integer. - * - * If the property is not found, return default value. If the property is not - * an unsigned integer, return boost::none, otherwise return the value. + * \brief Convenient JSON object parser * - * \param json the JSON object/array - * \param key the pointer or property key - * \param def the default value - * \return the value, boost::none or def + * This class helps destructuring insecure JSON input by returning optional + * values if they are not present or invalid. */ -template <typename Key> -inline boost::optional<std::uint64_t> optional_uint(const nlohmann::json& json, - const Key& key, - std::uint64_t def = 0) noexcept -{ - const auto v = get(json, key); +class parser { +private: + nlohmann::json json_; - if (!v) - return def; - if (!v->is_number_unsigned()) - return boost::none; +public: + /** + * Construct the parser. + * + * \param document the document + */ + inline parser(nlohmann::json document) noexcept + : json_(std::move(document)) + { + } - return v->template get<std::uint64_t>(); -} + /** + * Get a value from the document object. + * + * \param key the property key + * \return the value or boost::none if not found + */ + template <typename Type> + inline boost::optional<Type> get(const std::string& key) const noexcept + { + static_assert(parser_type_traits<Type>::value, "type not supported"); -/** - * Get an optional string. - * - * If the property is not found, return default value. If the property is not - * a string, return boost::none, otherwise return the value. - * - * \param json the JSON object/array - * \param key the pointer or property key - * \param def the default value - * \return the value, boost::none or def - */ -template <typename Key> -inline boost::optional<std::string> optional_string(const nlohmann::json& json, - const Key& key, - const std::string& def = "") noexcept -{ - const auto v = get(json, key); + const auto it = json_.find(key); + + if (it == json_.end()) + return boost::none; + + return parser_type_traits<Type>::get(*it); + } - if (!v) - return def; - if (!v->is_string()) - return boost::none; + /** + * Get an optional value from the document object. + * + * If the value is undefined, the default value is returned. Otherwise, if + * the value is not in the given type, boost::none is returned. + * + * \param key the property key + * \param def the default value if property is undefined + * \return the value, boost::none or def + */ + template <typename Type, typename DefaultValue> + inline boost::optional<Type> optional(const std::string& key, DefaultValue&& def) const noexcept + { + static_assert(parser_type_traits<Type>::value, "type not supported"); - return v->template get<std::string>(); -} + const auto it = json_.find(key); + + if (it == json_.end()) + return boost::optional<Type>(std::forward<DefaultValue>(def)); + + return parser_type_traits<Type>::get(*it); + } +}; /** * Print the value as human readable. @@ -292,8 +362,6 @@ return false; } - - } // !json_util } // !irccd
--- a/libirccd/irccd/daemon/command/plugin_config_command.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/command/plugin_config_command.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -81,7 +81,7 @@ void plugin_config_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args) { - const auto id = json_util::get_string(args, "plugin"); + const auto id = json_util::parser(args).get<std::string>("plugin"); if (!id || !string_util::is_identifier(*id)) throw plugin_error(plugin_error::invalid_identifier);
--- a/libirccd/irccd/daemon/command/plugin_info_command.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/command/plugin_info_command.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -35,7 +35,7 @@ void plugin_info_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args) { - const auto id = json_util::get_string(args, "plugin"); + const auto id = json_util::parser(args).get<std::string>("plugin"); if (!id || !string_util::is_identifier(*id)) throw plugin_error(plugin_error::invalid_identifier);
--- a/libirccd/irccd/daemon/command/plugin_load_command.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/command/plugin_load_command.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -35,7 +35,7 @@ void plugin_load_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args) { - const auto id = json_util::get_string(args, "plugin"); + const auto id = json_util::parser(args).get<std::string>("plugin"); if (!id || !string_util::is_identifier(*id)) throw plugin_error(plugin_error::invalid_identifier);
--- a/libirccd/irccd/daemon/command/plugin_reload_command.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/command/plugin_reload_command.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -35,7 +35,7 @@ void plugin_reload_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args) { - const auto id = json_util::get_string(args, "plugin"); + const auto id = json_util::parser(args).get<std::string>("plugin"); if (!id || !string_util::is_identifier(*id)) throw plugin_error(plugin_error::invalid_identifier);
--- a/libirccd/irccd/daemon/command/plugin_unload_command.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/command/plugin_unload_command.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -35,7 +35,7 @@ void plugin_unload_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args) { - const auto id = json_util::get_string(args, "plugin"); + const auto id = json_util::parser(args).get<std::string>("plugin"); if (!id || !string_util::is_identifier(*id)) throw plugin_error(plugin_error::invalid_identifier);
--- a/libirccd/irccd/daemon/command/rule_add_command.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/command/rule_add_command.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -35,11 +35,9 @@ void rule_add_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args) { - auto index = json_util::get_uint(args, "index"); + const auto index = json_util::parser(args).optional<unsigned>("index", irccd.rules().length()); - if (!index) - index = irccd.rules().length(); - if (index > irccd.rules().length()) + if (!index || *index > irccd.rules().length()) throw rule_error(rule_error::error::invalid_index); irccd.rules().insert(rule_util::from_json(args), *index);
--- a/libirccd/irccd/daemon/command/rule_edit_command.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/command/rule_edit_command.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -49,7 +49,7 @@ }; // Create a copy to avoid incomplete edition in case of errors. - const auto index = json_util::get_uint(args, "index"); + const auto index = json_util::parser(args).get<unsigned>("index"); if (!index) throw rule_error(rule_error::invalid_index);
--- a/libirccd/irccd/daemon/command/rule_info_command.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/command/rule_info_command.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -35,7 +35,7 @@ void rule_info_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args) { - const auto index = json_util::get_uint(args, "index"); + const auto index = json_util::parser(args).get<unsigned>("index"); if (!index) throw rule_error(rule_error::invalid_index);
--- a/libirccd/irccd/daemon/command/rule_move_command.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/command/rule_move_command.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -35,8 +35,9 @@ void rule_move_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args) { - const auto from = json_util::get_uint(args, "from"); - const auto to = json_util::get_uint(args, "to"); + const json_util::parser parser(args); + const auto from = parser.get<unsigned>("from"); + const auto to = parser.get<unsigned>("to"); if (!from || !to) throw rule_error(rule_error::invalid_index);
--- a/libirccd/irccd/daemon/command/rule_remove_command.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/command/rule_remove_command.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -34,7 +34,7 @@ void rule_remove_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args) { - const auto index = json_util::get_uint(args, "index"); + const auto index = json_util::parser(args).get<unsigned>("index"); if (!index || *index >= irccd.rules().length()) throw rule_error(rule_error::invalid_index);
--- a/libirccd/irccd/daemon/command/server_info_command.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/command/server_info_command.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -36,7 +36,7 @@ void server_info_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args) { - const auto id = json_util::get_string(args, "server"); + const auto id = json_util::parser(args).get<std::string>("server"); if (!id || !string_util::is_identifier(*id)) throw server_error(server_error::invalid_identifier);
--- a/libirccd/irccd/daemon/command/server_invite_command.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/command/server_invite_command.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -35,9 +35,10 @@ void server_invite_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args) { - const auto id = json_util::get_string(args, "server"); - const auto target = json_util::get_string(args, "target"); - const auto channel = json_util::get_string(args, "channel"); + const json_util::parser parser(args); + const auto id = parser.get<std::string>("server"); + const auto target = parser.get<std::string>("target"); + const auto channel = parser.get<std::string>("channel"); if (!id || !string_util::is_identifier(*id)) throw server_error(server_error::invalid_identifier);
--- a/libirccd/irccd/daemon/command/server_join_command.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/command/server_join_command.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -35,16 +35,19 @@ void server_join_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args) { - const auto id = json_util::get_string(args, "server"); - const auto channel = json_util::get_string(args, "channel"); - const auto password = json_util::get_string(args, "password"); + const json_util::parser parser(args); + const auto id = parser.get<std::string>("server"); + const auto channel = parser.get<std::string>("channel"); + const auto password = parser.optional<std::string>("password", ""); if (!id || !string_util::is_identifier(*id)) throw server_error(server_error::invalid_identifier); if (!channel || channel->empty()) throw server_error(server_error::invalid_channel); + if (!password) + throw server_error(server_error::invalid_password); - irccd.servers().require(*id)->join(*channel, password ? *password : ""); + irccd.servers().require(*id)->join(*channel, *password); client.success("server-join"); }
--- a/libirccd/irccd/daemon/command/server_kick_command.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/command/server_kick_command.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -35,10 +35,11 @@ void server_kick_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args) { - const auto id = json_util::get_string(args, "server"); - const auto target = json_util::get_string(args, "target"); - const auto channel = json_util::get_string(args, "channel"); - const auto reason = json_util::get_string(args, "reason"); + const json_util::parser parser(args); + const auto id = parser.get<std::string>("server"); + const auto target = parser.get<std::string>("target"); + const auto channel = parser.get<std::string>("channel"); + const auto reason = parser.optional<std::string>("reason", ""); if (!id || !string_util::is_identifier(*id)) throw server_error(server_error::invalid_identifier); @@ -46,8 +47,10 @@ throw server_error(server_error::invalid_nickname); if (!channel || channel->empty()) throw server_error(server_error::invalid_channel); + if (!reason) + throw server_error(server_error::invalid_message); - irccd.servers().require(*id)->kick(*target, *channel, reason ? *reason : ""); + irccd.servers().require(*id)->kick(*target, *channel, *reason); client.success("server-kick"); }
--- a/libirccd/irccd/daemon/command/server_me_command.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/command/server_me_command.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -35,9 +35,10 @@ void server_me_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args) { - const auto id = json_util::get_string(args, "server"); - const auto channel = json_util::get_string(args, "target"); - const auto message = json_util::optional_string(args, "message", ""); + const json_util::parser parser(args); + const auto id = parser.get<std::string>("server"); + const auto channel = parser.get<std::string>("target"); + const auto message = parser.optional<std::string>("message", ""); if (!id || !string_util::is_identifier(*id)) throw server_error(server_error::invalid_identifier);
--- a/libirccd/irccd/daemon/command/server_message_command.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/command/server_message_command.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -35,9 +35,10 @@ void server_message_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args) { - const auto id = json_util::get_string(args, "server"); - const auto channel = json_util::get_string(args, "target"); - const auto message = json_util::optional_string(args, "message", ""); + const json_util::parser parser(args); + const auto id = parser.get<std::string>("server"); + const auto channel = parser.get<std::string>("target"); + const auto message = parser.optional<std::string>("message", ""); if (!id || !string_util::is_identifier(*id)) throw server_error(server_error::invalid_identifier);
--- a/libirccd/irccd/daemon/command/server_mode_command.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/command/server_mode_command.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -35,12 +35,13 @@ void server_mode_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args) { - const auto id = json_util::get_string(args, "server"); - const auto channel = json_util::get_string(args, "channel"); - const auto mode = json_util::get_string(args, "mode"); - const auto limit = json_util::optional_string(args, "limit", ""); - const auto user = json_util::optional_string(args, "user", ""); - const auto mask = json_util::optional_string(args, "mask", ""); + const json_util::parser parser(args); + const auto id = parser.get<std::string>("server"); + const auto channel = parser.get<std::string>("channel"); + const auto mode = parser.get<std::string>("mode"); + const auto limit = parser.optional<std::string>("limit", ""); + const auto user = parser.optional<std::string>("user", ""); + const auto mask = parser.optional<std::string>("mask", ""); if (!id || !string_util::is_identifier(*id)) throw server_error(server_error::invalid_identifier);
--- a/libirccd/irccd/daemon/command/server_nick_command.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/command/server_nick_command.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -35,8 +35,9 @@ void server_nick_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args) { - const auto id = json_util::get_string(args, "server"); - const auto nick = json_util::get_string(args, "nickname"); + const json_util::parser parser(args); + const auto id = parser.get<std::string>("server"); + const auto nick = parser.get<std::string>("nickname"); if (!id || !string_util::is_identifier(*id)) throw server_error(server_error::invalid_identifier);
--- a/libirccd/irccd/daemon/command/server_notice_command.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/command/server_notice_command.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -35,9 +35,10 @@ void server_notice_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args) { - const auto id = json_util::get_string(args, "server"); - const auto channel = json_util::get_string(args, "target"); - const auto message = json_util::optional_string(args, "message", ""); + const json_util::parser parser(args); + const auto id = parser.get<std::string>("server"); + const auto channel = parser.get<std::string>("target"); + const auto message = parser.optional<std::string>("message", ""); if (!id || !string_util::is_identifier(*id)) throw server_error(server_error::invalid_identifier);
--- a/libirccd/irccd/daemon/command/server_part_command.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/command/server_part_command.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -35,9 +35,10 @@ void server_part_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args) { - const auto id = json_util::get_string(args, "server"); - const auto channel = json_util::get_string(args, "channel"); - const auto reason = json_util::optional_string(args, "reason", ""); + const json_util::parser parser(args); + const auto id = parser.get<std::string>("server"); + const auto channel = parser.get<std::string>("channel"); + const auto reason = parser.optional<std::string>("reason", ""); if (!id || !string_util::is_identifier(*id)) throw server_error(server_error::invalid_identifier);
--- a/libirccd/irccd/daemon/command/server_topic_command.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/command/server_topic_command.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -35,9 +35,10 @@ void server_topic_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args) { - const auto id = json_util::get_string(args, "server"); - const auto channel = json_util::get_string(args, "channel"); - const auto topic = json_util::optional_string(args, "topic", ""); + const json_util::parser parser(args); + const auto id = parser.get<std::string>("server"); + const auto channel = parser.get<std::string>("channel"); + const auto topic = parser.optional<std::string>("topic", ""); if (!id || !string_util::is_identifier(*id)) throw server_error(server_error::invalid_identifier);
--- a/libirccd/irccd/daemon/server_util.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/server_util.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -119,15 +119,15 @@ sv.set_command_char(command_char); } -void from_json_load_options(server& sv, const nlohmann::json& object) +void from_json_load_options(server& sv, const json_util::parser& parser) { - const auto port = json_util::optional_uint(object, "port", sv.get_port()); - const auto nickname = json_util::optional_string(object, "nickname", sv.get_nickname()); - const auto realname = json_util::optional_string(object, "realname", sv.get_realname()); - const auto username = json_util::optional_string(object, "username", sv.get_username()); - const auto ctcp_version = json_util::optional_string(object, "ctcpVersion", sv.get_ctcp_version()); - const auto command = json_util::optional_string(object, "commandChar", sv.get_command_char()); - const auto password = json_util::optional_string(object, "password", sv.get_password()); + const auto port = parser.optional<std::uint16_t>("port", sv.get_port()); + const auto nickname = parser.optional<std::string>("nickname", sv.get_nickname()); + const auto realname = parser.optional<std::string>("realname", sv.get_realname()); + const auto username = parser.optional<std::string>("username", sv.get_username()); + const auto ctcp_version = parser.optional<std::string>("ctcpVersion", sv.get_ctcp_version()); + const auto command = parser.optional<std::string>("commandChar", sv.get_command_char()); + const auto password = parser.optional<std::string>("password", sv.get_password()); if (!port || *port > std::numeric_limits<std::uint16_t>::max()) throw server_error(server_error::invalid_port); @@ -153,29 +153,29 @@ sv.set_password(*password); } -void from_json_load_flags(server& sv, nlohmann::json object) +void from_json_load_flags(server& sv, const json_util::parser& parser) { - const auto ipv6 = object["ipv6"]; - const auto ssl = object["ssl"]; - const auto ssl_verify = object["sslVerify"]; - const auto auto_rejoin = object["autoRejoin"]; - const auto join_invite = object["joinInvite"]; + const auto ipv6 = parser.get<bool>("ipv6"); + const auto auto_rejoin = parser.get<bool>("autoRejoin"); + const auto join_invite = parser.get<bool>("joinInvite"); + const auto ssl = parser.get<bool>("ssl"); + const auto ssl_verify = parser.get<bool>("sslVerify"); - if (ipv6.is_boolean() && ipv6.get<bool>()) + if (ipv6.value_or(false)) sv.set_flags(sv.get_flags() | server::ipv6); - if (ssl.is_boolean() && ssl.get<bool>()) - sv.set_flags(sv.get_flags() | server::ssl); - if (ssl_verify.is_boolean() && ssl_verify.get<bool>()) - sv.set_flags(sv.get_flags() | server::ssl_verify); - if (auto_rejoin.is_boolean() && auto_rejoin.get<bool>()) + if (auto_rejoin.value_or(false)) sv.set_flags(sv.get_flags() | server::auto_rejoin); - if (join_invite.is_boolean() && join_invite.get<bool>()) + if (join_invite.value_or(false)) sv.set_flags(sv.get_flags() | server::join_invite); + if (ssl.value_or(false)) #if !defined(HAVE_SSL) - if (sv.get_flags() & server::ssl) throw server_error(server_error::ssl_disabled); +#else + sv.set_flags(sv.get_flags() | server::ssl); #endif + if (ssl_verify.value_or(false)) + sv.set_flags(sv.get_flags() | server::ssl_verify); } } // !namespace @@ -183,8 +183,9 @@ std::shared_ptr<server> from_json(boost::asio::io_service& service, const nlohmann::json& object) { // Mandatory parameters. - const auto id = json_util::get_string(object, "name"); - const auto host = json_util::get_string(object, "host"); + const json_util::parser parser(object); + const auto id = parser.get<std::string>("name"); + const auto host = parser.get<std::string>("host"); if (!id || !string_util::is_identifier(*id)) throw server_error(server_error::invalid_identifier); @@ -193,8 +194,8 @@ const auto sv = std::make_shared<server>(service, *id, *host); - from_json_load_options(*sv, object); - from_json_load_flags(*sv, object); + from_json_load_options(*sv, parser); + from_json_load_flags(*sv, parser); return sv; }
--- a/libirccd/irccd/daemon/service/transport_service.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/service/transport_service.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -41,7 +41,7 @@ { assert(object.is_object()); - const auto name = json_util::get_string(object, "/command"_json_pointer); + const auto name = json_util::parser(object).get<std::string>("command"); if (!name) { tc->error(irccd_error::invalid_message);
--- a/libirccd/irccd/daemon/transport_server.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccd/irccd/daemon/transport_server.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -39,8 +39,9 @@ return; } - const auto command = json_util::get_string(message, "/command"_json_pointer); - const auto password = json_util::get_string(message, "/password"_json_pointer); + const json_util::parser parser(message); + const auto command = parser.get<std::string>("command"); + const auto password = parser.get<std::string>("password"); if (!command || *command != "auth") { client->error(irccd_error::auth_required);
--- a/libirccdctl/irccd/ctl/controller.cpp Mon Mar 26 19:22:01 2018 +0200 +++ b/libirccdctl/irccd/ctl/controller.cpp Mon Mar 26 20:30:15 2018 +0200 @@ -60,8 +60,9 @@ return; } - const auto program = json_util::get_string(message, "/program"_json_pointer); - const auto major = json_util::get_int(message, "/major"_json_pointer); + const json_util::parser parser(message); + const auto program = parser.get<std::string>("program"); + const auto major = parser.get<int>("major"); if (!program && *program != "irccd") handler(irccd_error::not_irccd, std::move(message)); @@ -99,8 +100,9 @@ return; } - const auto e = json_util::get_int(msg, "/error"_json_pointer); - const auto c = json_util::get_string(msg, "/errorCategory"_json_pointer); + const json_util::parser parser(msg); + const auto e = parser.get<int>("error"); + const auto c = parser.get<std::string>("errorCategory"); if (e && c) { if (*c == "irccd")