From a5d95afb96eb9a3b65d82f5f84bf8e4a4fb4c8ac Mon Sep 17 00:00:00 2001 From: Rutger Broekhoff Date: Fri, 28 Aug 2026 21:12:55 +0200 Subject: clang-format C++ sources --- server/src/config.cpp | 337 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 204 insertions(+), 133 deletions(-) (limited to 'server/src/config.cpp') diff --git a/server/src/config.cpp b/server/src/config.cpp index 3b17691..84c436a 100644 --- a/server/src/config.cpp +++ b/server/src/config.cpp @@ -14,154 +14,225 @@ namespace json = boost::json; namespace routemon::config { - class location { - std::optional>> next_; - - auto append_to(std::string& s) const -> void { - if (next_) { - s += next_->first; - s += "."; - next_->second->append_to(s); - } - } - - public: - location() = default; - - explicit location(location const& next, std::string_view entry) - : next_{std::make_pair(entry, util::not_null{&next})} - {} - - [[nodiscard]] auto to_string() const -> std::string { - if (!next_) - return ""; - auto s = std::string{next_->first}; +class location +{ + std::optional>> + next_; + + auto append_to(std::string& s) const -> void + { + if (next_) + { + s += next_->first; + s += "."; next_->second->append_to(s); - return s; - } - - auto sub(std::string_view entry) const& -> location { - return location{*this, entry}; - } - }; - - class object_reader { - location loc_; - json::object const& obj_; - std::unordered_set visited_; - - public: - object_reader(json::value const& jv, location loc) - try : loc_{std::move(loc)}, obj_{jv.as_object()} - {} catch (boost::system::system_error const&) { - throw std::runtime_error{std::format("expected an object at {}", loc.to_string())}; - } - - auto check_unused() const -> void { - for (auto const& kv : obj_) { - if (!visited_.contains(std::string{kv.key()})) { - throw std::runtime_error{std::format("unexpected key {}", loc_.sub(kv.key()).to_string())}; - } - } - } - - template - auto expect_at(std::string_view key) -> T { - visited_.emplace(key); - auto const loc = loc_.sub(key); - if (auto const jv = obj_.try_at(key)) { - try { - return json::value_to(*jv, loc); - } catch (boost::system::system_error const& e) { - throw std::runtime_error{std::format("failed to read {}: {}", loc.to_string(), e.code().message())}; - } - } else { - throw std::runtime_error{std::format("did not find expected key {}", loc.to_string())}; - } } - }; - - auto as_checked_object(json::value const& jv, location const& loc, std::invocable auto const& f) -> decltype(f(std::declval())) { - auto r = object_reader{jv, loc}; - auto&& v = f(r); - r.check_unused(); - return std::forward(v); } - auto tag_invoke(json::value_to_tag const&, json::value const& jv, location const& loc) -> rwgps { - return as_checked_object(jv, loc, [](object_reader& r) -> rwgps { - return { - .api_key = r.expect_at("api_key"), - .auth_token = r.expect_at("auth_token"), - }; - }); - } +public: + location() = default; - auto tag_invoke(json::value_to_tag const&, json::value const& jv, location const& loc) -> situations { - return as_checked_object(jv, loc, [](object_reader& r) -> situations { - return { - .datex2_filename = r.expect_at("datex2_filename"), - }; - }); + explicit location(location const& next, std::string_view entry) + : next_{std::make_pair(entry, util::not_null{&next})} + { } - auto tag_invoke(json::value_to_tag const&, json::value const& jv, location const& loc) -> database { - return as_checked_object(jv, loc, [](object_reader& r) -> database { - return { - .sqlite3_filename = r.expect_at("sqlite3_filename"), - }; - }); + [[nodiscard]] auto to_string() const -> std::string + { + if (!next_) + return ""; + auto s = std::string{next_->first}; + next_->second->append_to(s); + return s; } - auto tag_invoke(json::value_to_tag const&, json::value const& jv, location const& loc) -> http_server { - return as_checked_object(jv, loc, [](object_reader& r) -> http_server { - return { - .lax_cors = r.expect_at("lax_cors"), - }; - }); + auto sub(std::string_view entry) const& -> location + { + return location{*this, entry}; } - - auto tag_invoke(json::value_to_tag const&, json::value const& jv, location const& loc) -> logger { - return as_checked_object(jv, loc, [obj_loc = loc](object_reader& r) -> logger { - auto const level_str = r.expect_at("level"); - auto level = log::level{}; - if (level_str == "debug") - level = log::level::debug; - else if (level_str == "info") - level = log::level::info; - else if (level_str == "warn") - level = log::level::warn; - else if (level_str == "error") - level = log::level::error; - else - throw std::runtime_error{std::format("unable to parse log level {:?} at {}: expected one of {{debug, info, warn, error}}", level_str, obj_loc.sub("level").to_string())}; - return logger{level}; - }); +}; + +class object_reader +{ + location loc_; + json::object const& obj_; + std::unordered_set visited_; + +public: + object_reader(json::value const& jv, location loc) + try : loc_{std::move(loc)}, obj_{jv.as_object()} {} + catch (boost::system::system_error const&) + { + throw std::runtime_error{std::format( + "expected an object at {}", loc.to_string())}; } - auto json_value_to_app(json::value const& jv) -> app { - return as_checked_object(jv, location{}, [](object_reader& r) -> app { - return { - .rwgps = r.expect_at("rwgps"), - .situations = r.expect_at("situations"), - .database = r.expect_at("database"), - .http_server = r.expect_at("http_server"), - .logger = r.expect_at("logger"), - }; - }); + auto check_unused() const -> void + { + for (auto const& kv : obj_) + { + if (!visited_.contains(std::string{kv.key()})) + { + throw std::runtime_error{std::format( + "unexpected key {}", loc_.sub(kv.key()).to_string())}; + } + } } - auto load_file(std::string const& filename) -> app { - auto f = std::ifstream{filename}; // TODO: ensure that we are opening in binary mode? - if (!f.is_open()) - throw std::runtime_error{std::format("failed to open {}", filename)}; - auto jv = json::value{}; - try { - jv = json::parse(f); - } catch (boost::system::system_error const& e) { - throw std::runtime_error{std::format("failed to parse: {}", e.code().message())}; + template + auto expect_at(std::string_view key) -> T + { + visited_.emplace(key); + auto const loc = loc_.sub(key); + if (auto const jv = obj_.try_at(key)) + { + try + { + return json::value_to(*jv, loc); + } + catch (boost::system::system_error const& e) + { + throw std::runtime_error{std::format( + "failed to read {}: {}", loc.to_string(), e.code().message())}; + } } - return json_value_to_app(jv); + else + { + throw std::runtime_error{std::format( + "did not find expected key {}", loc.to_string())}; + } + } +}; + +auto as_checked_object( + json::value const& jv, location const& loc, + std::invocable auto const& f) + -> decltype(f(std::declval())) +{ + auto r = object_reader{jv, loc}; + auto&& v = f(r); + r.check_unused(); + return std::forward(v); +} + +auto tag_invoke( + json::value_to_tag const&, json::value const& jv, + location const& loc) -> rwgps +{ + return as_checked_object( + jv, loc, + [](object_reader& r) -> rwgps + { + return { + .api_key = r.expect_at("api_key"), + .auth_token = r.expect_at("auth_token"), + }; + }); +} + +auto tag_invoke( + json::value_to_tag const&, json::value const& jv, + location const& loc) -> situations +{ + return as_checked_object( + jv, loc, + [](object_reader& r) -> situations + { + return { + .datex2_filename = r.expect_at("datex2_filename"), + }; + }); +} + +auto tag_invoke( + json::value_to_tag const&, json::value const& jv, + location const& loc) -> database +{ + return as_checked_object( + jv, loc, + [](object_reader& r) -> database + { + return { + .sqlite3_filename = r.expect_at("sqlite3_filename"), + }; + }); +} + +auto tag_invoke( + json::value_to_tag const&, json::value const& jv, + location const& loc) -> http_server +{ + return as_checked_object( + jv, loc, + [](object_reader& r) -> http_server + { + return { + .lax_cors = r.expect_at("lax_cors"), + }; + }); +} + +auto tag_invoke( + json::value_to_tag const&, json::value const& jv, + location const& loc) -> logger +{ + return as_checked_object( + jv, loc, + [obj_loc = loc](object_reader& r) -> logger + { + auto const level_str = r.expect_at("level"); + auto level = log::level{}; + if (level_str == "debug") + level = log::level::debug; + else if (level_str == "info") + level = log::level::info; + else if (level_str == "warn") + level = log::level::warn; + else if (level_str == "error") + level = log::level::error; + else + throw std::runtime_error{std::format( + "unable to parse log level {:?} at {}: expected one " + "of {{debug, info, warn, error}}", + level_str, obj_loc.sub("level").to_string())}; + return logger{level}; + }); +} + +auto json_value_to_app(json::value const& jv) -> app +{ + return as_checked_object( + jv, location{}, + [](object_reader& r) -> app + { + return { + .rwgps = r.expect_at("rwgps"), + .situations = r.expect_at("situations"), + .database = r.expect_at("database"), + .http_server = r.expect_at("http_server"), + .logger = r.expect_at("logger"), + }; + }); +} + +auto load_file(std::string const& filename) -> app +{ + auto f = std::ifstream{ + filename + }; // TODO: ensure that we are opening in binary mode? + if (!f.is_open()) + throw std::runtime_error{std::format("failed to open {}", filename)}; + auto jv = json::value{}; + try + { + jv = json::parse(f); + } + catch (boost::system::system_error const& e) + { + throw std::runtime_error{std::format( + "failed to parse: {}", e.code().message())}; } + return json_value_to_app(jv); +} } // namespace routemon::config -- cgit v1.3