7#include <nlohmann/json.hpp>
12#include "functional.h"
26 inline std::string load_file(std::filesystem::path const& from, std::error_code& ec)
28 auto source = ghassanpl::make_mmap_source<char>(from, ec);
29 return ec ? std::string{} : std::string{ source.begin(), source.end() };
34 inline std::string load_file(std::filesystem::path const& from)
37 auto source = ghassanpl::make_mmap_source<char>(from, ec);
38 if (ec == std::errc::file_too_large) /// zero-sized file
41 throw std::runtime_error(format("file '{}' could not be loaded: {}", from.string(), ec.message()));
42 return std::string{ source.begin(), source.end() };
46 inline expected<std::string, std::error_code> try_load_file(std::filesystem::path const& from)
49 auto result = load_file(from, ec);
50 return ec ? unexpected(ec) : expected<std::string, std::error_code>{ std::move(result) };
53 inline bool save_file(std::filesystem::path const& to, std::string_view string, std::error_code& ec)
56 std::ofstream out{ to };
57 out.write(string.data(), string.size());
61 inline void save_file(std::filesystem::path const& to, std::string_view string)
63 std::ofstream out{ to };
64 out.exceptions(std::ios::badbit | std::ios::failbit);
65 out.write(string.data(), string.size());
78 inline std::vector<std::string> load_file(std::filesystem::path const& from, std::error_code& ec)
80 auto source = ghassanpl::make_mmap_source<char>(from, ec);
84 return resulting([&](std::vector<std::string>& result) {
85 ghassanpl::string_ops::split({ source.begin(), source.end() }, '\n', op::emplace_back_to(result));
89 inline std::vector<std::string> load_file(std::filesystem::path const& from)
92 auto source = ghassanpl::make_mmap_source<char>(from, ec);
93 if (ec == std::errc::file_too_large) /// zero-sized file
96 throw std::runtime_error(format("file '{}' could not be loaded: {}", from.string(), ec.message()));
98 return resulting([&](std::vector<std::string>& result) {
99 ghassanpl::string_ops::split({ source.begin(), source.end() }, '\n', op::emplace_back_to(result));
103 template <typename CALLBACK>
104 requires std::invocable<CALLBACK, std::string_view>
105 inline void load_file(std::filesystem::path const& from, CALLBACK&& callback)
108 auto source = ghassanpl::make_mmap_source<char>(from, ec);
109 if (ec == std::errc::file_too_large) /// zero-sized file
112 throw std::runtime_error(format("file '{}' could not be loaded: {}", from.string(), ec.message()));
114 ghassanpl::string_ops::split({ source.begin(), source.end() }, '\n', callback);
117 inline expected<std::vector<std::string>, std::error_code> try_load_file(std::filesystem::path const& from)
120 auto result = load_file(from, ec);
121 return ec ? unexpected(ec) : expected<std::vector<std::string>, std::error_code>{ std::move(result) };
124 template <std::ranges::range T>
125 inline bool save_file(std::filesystem::path const& to, T string_range, std::error_code& ec)
128 std::ofstream out{ to };
129 for (auto& string : string_range)
131 out.write(std::to_address(std::ranges::begin(string)), std::ranges::size(string));
137 template <std::ranges::range T>
138 inline void save_file(std::filesystem::path const& to, T string_range)
140 std::ofstream out{ to };
141 out.exceptions(std::ios::badbit | std::ios::failbit);
142 for (auto& string : string_range)
144 out.write(std::to_address(std::ranges::begin(string)), std::ranges::size(string));
158 inline const nlohmann::json empty_json = nlohmann::json{};
159 inline const nlohmann::json empty_json_array = nlohmann::json::array();
160 inline const nlohmann::json empty_json_object = nlohmann::json::object();
163 using jtype = nlohmann::json::value_t;
165 inline expected<nlohmann::json, std::error_code> load_file(std::filesystem::path
const& from)
167 std::error_code ec{};
168 auto source = ghassanpl::make_mmap_source<char>(from, ec);
169 if (ec != std::error_code{})
170 return unexpected(ec);
171 return nlohmann::json::parse(source);
174 inline nlohmann::json try_load_file(std::filesystem::path
const& from, nlohmann::json or_json)
177 auto source = ghassanpl::make_mmap_source<char>(from, ec);
178 return ec ? std::move(or_json) : nlohmann::json::parse(source);
181 inline nlohmann::json try_load_file(std::filesystem::path
const& from)
184 auto source = ghassanpl::make_mmap_source<char>(from, ec);
185 return ec ? empty_json : nlohmann::json::parse(source);
188 inline void save_file(std::filesystem::path
const&
to, nlohmann::json
const& j,
bool pretty =
true)
190 std::ofstream out{
to };
191 nlohmann::detail::serializer<nlohmann::json> s{ nlohmann::detail::output_adapter<char, std::string>(out),
'\t', nlohmann::detail::error_handler_t::strict };
192 s.dump(j, pretty,
false, 1);
195 constexpr const char* type_name(nlohmann::json::value_t type)
noexcept
199 using enum nlohmann::detail::value_t;
220 template <
typename VISIT_FUNC>
221 auto visit(nlohmann::json
const& j, VISIT_FUNC&& func)
225 using enum nlohmann::detail::value_t;
226 case object:
return func(j.get_ref<nlohmann::json::object_t
const&>());
227 case array:
return func(j.get_ref<nlohmann::json::array_t
const&>());
228 case string:
return func(j.get_ref<nlohmann::json::string_t
const&>());
229 case boolean:
return func(j.get_ref<nlohmann::json::boolean_t
const&>());
230 case number_integer:
return func(j.get_ref<nlohmann::json::number_integer_t
const&>());
231 case number_unsigned:
return func(j.get_ref<nlohmann::json::number_unsigned_t
const&>());
232 case number_float:
return func(j.get_ref<nlohmann::json::number_float_t
const&>());
233 case binary:
return func(j.get_ref<nlohmann::json::binary_t
const&>());
235 return func(
nullptr);
248 inline expected<nlohmann::json, std::error_code> load_file(std::filesystem::path
const& from)
250 std::error_code ec{};
251 auto source = ghassanpl::make_mmap_source<char>(from, ec);
252 if (ec != std::error_code{})
253 return unexpected(ec);
254 return nlohmann::json::from_ubjson(source);
257 inline nlohmann::json try_load_file(std::filesystem::path
const& from, nlohmann::json or_json)
260 auto source = ghassanpl::make_mmap_source<char>(from, ec);
261 return ec ? std::move(or_json) : nlohmann::json::from_ubjson(source);
264 inline nlohmann::json try_load_file(std::filesystem::path
const& from)
267 auto source = ghassanpl::make_mmap_source<char>(from, ec);
268 return ec ? json::empty_json : nlohmann::json::from_ubjson(source);
271 inline expected<void, std::error_code> save_file(std::filesystem::path
const&
to, nlohmann::json
const& j)
274 std::ios_base::iostate exceptionMask = out.exceptions() | std::ios::failbit;
275 out.exceptions(exceptionMask);
278 out.open(
to, std::ios::binary);
280 catch (std::ios_base::failure& e)
282 return unexpected(e.code());
284 nlohmann::json::to_ubjson(j, nlohmann::detail::output_adapter<char, std::string>(out),
true,
true);
298 inline expected<nlohmann::json, std::error_code> load_file(std::filesystem::path
const& from)
300 std::error_code ec{};
301 auto source = ghassanpl::make_mmap_source<uint8_t>(from, ec);
302 if (ec != std::error_code{})
303 return unexpected(ec);
304 return nlohmann::json::from_cbor(source);
307 inline nlohmann::json try_load_file(std::filesystem::path
const& from, nlohmann::json or_json)
310 auto source = ghassanpl::make_mmap_source<uint8_t>(from, ec);
311 return ec ? std::move(or_json) : nlohmann::json::from_cbor(source);
314 inline nlohmann::json try_load_file(std::filesystem::path
const& from)
317 auto source = ghassanpl::make_mmap_source<uint8_t>(from, ec);
318 return ec ? json::empty_json : nlohmann::json::from_cbor(source);
321 inline void save_file(std::filesystem::path
const&
to, nlohmann::json
const& j)
323 std::ofstream out{
to, std::ios::binary };
324 nlohmann::json::to_cbor(j, nlohmann::detail::output_adapter<char, std::string>(out));
338 inline nlohmann::json const& get(nlohmann::json const& g, std::string_view key, jtype type = jtype::discarded)
340 if (auto it = g.find(key); it != g.end() && (type == jtype::discarded || it->type() == type))
342 return json::empty_json;
347 inline std::string get(nlohmann::json const& g, std::string_view key, std::string_view default_value, jtype type = jtype::discarded)
349 if (auto it = g.find(key); it != g.end() && (type == jtype::discarded || it->type() == type))
350 return (std::string)*it;
351 return std::string{ default_value };
356 template <std::integral T>
357 inline T get(nlohmann::json const& g, std::string_view key, T default_value, jtype type = jtype::discarded)
359 if (auto it = g.find(key); it != g.end() && (type == jtype::discarded || it->type() == type))
361 return default_value;
366 template <std::floating_point T>
367 inline T get(nlohmann::json const& g, std::string_view key, T default_value, jtype type = jtype::discarded)
369 if (auto it = g.find(key); it != g.end() && (type == jtype::discarded || it->type() == type))
371 return default_value;
375 inline nlohmann::json const& get_array(nlohmann::json const& g, std::string_view key)
377 if (auto it = g.find(key); it != g.end() && it->type() == jtype::array)
379 return json::empty_json_array;
384 template <typename T>
385 inline void field(T& val, nlohmann::json const& g, std::string_view key)
389 auto it = g.find(key);
398 std::throw_with_nested(std::runtime_error{ std::format("while trying to convert value at key \"{}\" to type {}", key, typeid(T).name()) });
401 throw std::runtime_error(std::format("no key \"{}\" found", key));
406 template <typename T>
407 inline void field(T& val, nlohmann::json const& g, size_t key)
416 std::throw_with_nested(std::runtime_error{ std::format("while trying to convert value at element {} to type {}", key, typeid(T).name()) });
422 template <typename T>
423 inline bool field_opt(T& val, nlohmann::json const& g, std::string_view key)
427 auto it = g.find(key);
436 std::throw_with_nested(std::runtime_error{ std::format("while trying to convert value at key \"{}\" to type {}", key, typeid(T).name()) });
449 inline nlohmann::json try_load_file(std::filesystem::path const& from, nlohmann::json const& or_json = json::empty_json)
452 auto source = ghassanpl::make_mmap_source<char>(from, ec);
453 return ec ? or_json : nlohmann::json::from_ubjson(source);
456 inline nlohmann::json load_file(std::filesystem::path const& from, std::error_code& ec)
458 auto source = ghassanpl::make_mmap_source<char>(from, ec);
459 return ec ? nlohmann::json{} : nlohmann::json::from_ubjson(source);
462 inline nlohmann::json load_file(std::filesystem::path const& from)
466 return nlohmann::json::from_ubjson(ghassanpl::make_mmap_source<char>(from));
470 std::throw_with_nested(std::runtime_error{ format("while trying to load ubjson file {}", from.string()) });
474 inline void save_file(std::filesystem::path const& to, nlohmann::json const& j)
476 std::ofstream out{ to };
477 nlohmann::json::to_ubjson(j, nlohmann::detail::output_adapter<char, std::string>(out), true, true);
489 inline nlohmann::json try_load_file(std::filesystem::path const& from, nlohmann::json const& or_json = json::empty_json)
492 auto source = ghassanpl::make_mmap_source<char>(from, ec);
493 return ec ? or_json : nlohmann::json::from_cbor(source);
497 inline void save_file(std::filesystem::path const& to, nlohmann::json const& j)
499 std::ofstream out{ to };
500 nlohmann::json::to_cbor(j, nlohmann::detail::output_adapter<char, std::string>(out));
nlohmann::json::value_t jtype
Smaller name for nlohmann::json::value_t.
auto visit(nlohmann::json const &j, VISIT_FUNC &&func)
Calls func with the actual value inside j; similar to std::visit.
constexpr CONTAINER to(RANGE &&range, TYPES &&... args)
to<container>();