22// This code is licensed under MIT license (see LICENSE for details)
33
44#pragma once
5+ #include < chrono>
56#include < optional>
67#include < json/json.hpp>
78
89using namespace std ::literals;
910
1011namespace json {
11- enum class conv_result { ok, opt, failed, updated };
12+ enum class conv_result : int { ok, opt, failed, updated };
1213 inline constexpr bool is_ok (conv_result res) noexcept {
1314 return res < conv_result::failed;
1415 }
@@ -19,11 +20,10 @@ namespace json {
1920 };
2021
2122 template <typename T>
22- concept LoadsJsonRaw = requires (T& lval,
23- node const & data,
24- std::string& dbg) {
25- { lval.from_json (data, dbg) } -> std::convertible_to<conv_result>;
26- };
23+ concept LoadsJsonRaw =
24+ requires (T& lval, node const & data, std::string& dbg) {
25+ { lval.from_json (data, dbg) } -> std::convertible_to<conv_result>;
26+ };
2727
2828 template <typename T>
2929 concept LoadsJson = requires (T& lval, map const & data, std::string& dbg) {
@@ -32,12 +32,13 @@ namespace json {
3232 };
3333
3434 template <typename T, typename ... Kind>
35- concept LoadsJsonEx = requires (T& lval,
36- Kind const *... data,
37- std::string& dbg) {
38- (NodeType<Kind> && ...);
39- { lval.from_json (data..., dbg) } -> std::convertible_to<conv_result>;
40- };
35+ concept LoadsJsonEx =
36+ requires (T& lval, Kind const *... data, std::string& dbg) {
37+ (NodeType<Kind> && ...);
38+ {
39+ lval.from_json (data..., dbg)
40+ } -> std::convertible_to<conv_result>;
41+ };
4142
4243 inline auto to_json (StoresJson auto const & obj) { return obj.to_json (); }
4344 inline long long to_json (std::integral auto val) {
@@ -99,6 +100,20 @@ namespace json {
99100 return conv_result::ok;
100101 }
101102
103+ template <std::floating_point Float>
104+ inline conv_result load (node const & src, Float& val, std::string&) {
105+ auto const float_data = cast<double >(src);
106+ auto const int_data = cast<long long >(src);
107+ if (float_data) {
108+ val = static_cast <Float>(*float_data);
109+ } else if (int_data) {
110+ val = static_cast <Float>(*int_data);
111+ } else {
112+ return conv_result::opt;
113+ }
114+ return conv_result::ok;
115+ }
116+
102117 inline conv_result load (node const & src, bool & val, std::string&) {
103118 auto const data = cast<bool >(src);
104119 val = data ? *data : false ;
@@ -152,8 +167,9 @@ namespace json {
152167 }
153168
154169 template <typename T>
155- concept LoadableJsonValue = LoadsJson<T> || LoadsJsonRaw<T> ||
156- std::integral<T> || std::same_as<T, std::chrono::sys_seconds> ||
170+ concept LoadableJsonValue =
171+ LoadsJson<T> || LoadsJsonRaw<T> || std::integral<T> ||
172+ std::floating_point<T> || std::same_as<T, std::chrono::sys_seconds> ||
157173 std::same_as<T, string> || std::same_as<T, std::string>;
158174
159175 inline void append_name (conv_result res,
@@ -249,6 +265,25 @@ namespace json {
249265 return result;
250266 }
251267
268+ template <LoadableJsonValue ValueType>
269+ inline conv_result load (map const & src,
270+ std::map<string, ValueType>& value,
271+ std::string& dbg) {
272+ auto result = conv_result::ok;
273+ value.clear ();
274+ // value.reserve(src.size());
275+ for (auto & [key, node_item] : src.items ()) {
276+ auto insert_result = value.insert ({key, {}});
277+ auto it = insert_result.first ;
278+ auto const res = json::load (node_item, it->second , dbg);
279+ if (res == conv_result::failed || res == conv_result::opt)
280+ value.erase (it);
281+ if (!is_ok (res)) result = res;
282+ if (result == conv_result::failed) break ;
283+ }
284+ return result;
285+ }
286+
252287 template <LoadableJsonValue ValueType>
253288 inline conv_result load (map const & src,
254289 string const & key,
@@ -281,6 +316,20 @@ namespace json {
281316 return conv_result::ok;
282317 }
283318
319+ template <LoadableJsonValue ValueType>
320+ inline conv_result load (map const & src,
321+ string const & key,
322+ std::map<string, ValueType>& value,
323+ std::string& dbg) {
324+ auto it = src.find (key);
325+ if (it == src.end ()) return conv_result::opt;
326+ auto const arr = cast<map>(it->second );
327+ if (!arr) return conv_result::opt;
328+ auto res = json::load (*arr, value, dbg);
329+ append_name (res, key, dbg);
330+ return res;
331+ }
332+
284333 template <typename T>
285334 concept JsonStorableValue = requires (T const & obj) {
286335 { to_json (obj) } -> std::convertible_to<node>;
0 commit comments