3#include "nlohmann/json.hpp"
5#include "ll/api/io/FileUtils.h"
6#include "ll/api/reflection/Deserialization.h"
7#include "ll/api/reflection/Serialization.h"
18template <std::derived_from<nlohmann::detail::json_default_base> T>
20 std::string operator()(T
const& t) {
return t.dump(4); }
23template <IsConfig T,
class J = nlohmann::ordered_json>
24inline bool saveConfig(T
const& config, std::filesystem::path
const& path) {
25 return file_utils::writeFile(path,
DumpType<J>{}(ll::reflection::serialize<J>(config).value()));
31template <std::derived_from<nlohmann::detail::json_default_base> T>
33 T operator()(std::string
const& content) {
return T::parse(content,
nullptr,
true,
true); }
36template <
class T,
class J>
37bool defaultConfigUpdater(T& config, J& data) {
38 data.erase(
"version");
39 auto patch = ll::reflection::serialize<J>(config);
40 patch.value().merge_patch(data);
41 data = *std::move(patch);
44template <IsConfig T,
class J = nlohmann::ordered_json,
class F =
bool(T&, J&)>
45inline bool loadConfig(T& config, std::filesystem::path
const& path, F&& updater = defaultConfigUpdater<T, J>) {
46 bool noNeedRewrite =
true;
47 namespace fs = std::filesystem;
48 if (!fs::exists(path)) {
49 saveConfig<T, J>(config, path);
51 auto content = file_utils::readFile(path);
52 if (content && !content->empty()) {
53 auto data{ParseType<J>{}(*content)};
54 if (!data.contains(
"version")) {
55 noNeedRewrite =
false;
56 }
else if ((int64)(data[
"version"]) != config.version) {
57 noNeedRewrite =
false;
59 if (noNeedRewrite || std::invoke(std::forward<F>(updater), config, data)) {
60 ll::reflection::deserialize(config, data).value();
63 noNeedRewrite =
false;
Definition Reflection.h:27