LeviLamina
Loading...
Searching...
No Matches
Config.h
1#pragma once
2
3#include "nlohmann/json.hpp"
4
5#include "ll/api/io/FileUtils.h"
6#include "ll/api/reflection/Deserialization.h"
7#include "ll/api/reflection/Serialization.h"
8
9namespace ll::config {
10
11template <class T>
12concept IsConfig =
13 ll::reflection::Reflectable<T> && std::integral<std::remove_cvref_t<decltype((std::declval<T>().version))>>;
14
15template <class T>
16struct DumpType;
17
18template <std::derived_from<nlohmann::detail::json_default_base> T>
19struct DumpType<T> {
20 std::string operator()(T const& t) { return t.dump(4); }
21};
22
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()));
26}
27
28template <class T>
29struct ParseType;
30
31template <std::derived_from<nlohmann::detail::json_default_base> T>
32struct ParseType<T> {
33 T operator()(std::string const& content) { return T::parse(content, nullptr, true, true); }
34};
35
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);
42 return true;
43}
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);
50 }
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;
58 }
59 if (noNeedRewrite || std::invoke(std::forward<F>(updater), config, data)) {
60 ll::reflection::deserialize(config, data).value();
61 }
62 } else {
63 noNeedRewrite = false;
64 }
65 return noNeedRewrite;
66}
67
68} // namespace ll::config
Definition Config.h:12
Definition Reflection.h:27
Definition Config.h:16
Definition Config.h:29