Add a dedicated library for working with JSON (#2047)
This commit is contained in:
@@ -1,70 +1,117 @@
|
||||
#include "nvprefs_common.h"
|
||||
// external includes
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
// local includes
|
||||
#include "nvprefs_common.h"
|
||||
#include "undo_data.h"
|
||||
|
||||
namespace {
|
||||
using json = nlohmann::json;
|
||||
|
||||
const auto opengl_swapchain_our_value_key = "/opengl_swapchain/our_value";
|
||||
const auto opengl_swapchain_undo_value_key = "/opengl_swapchain/undo_value";
|
||||
// Separate namespace for ADL, otherwise we need to define json
|
||||
// functions in the same namespace as our types
|
||||
namespace nlohmann {
|
||||
using data_t = nvprefs::undo_data_t::data_t;
|
||||
using opengl_swapchain_t = data_t::opengl_swapchain_t;
|
||||
|
||||
} // namespace
|
||||
template <typename T>
|
||||
struct adl_serializer<std::optional<T>> {
|
||||
static void
|
||||
to_json(json &j, const std::optional<T> &opt) {
|
||||
if (opt == std::nullopt) {
|
||||
j = nullptr;
|
||||
}
|
||||
else {
|
||||
j = *opt;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
from_json(const json &j, std::optional<T> &opt) {
|
||||
if (j.is_null()) {
|
||||
opt = std::nullopt;
|
||||
}
|
||||
else {
|
||||
opt = j.template get<T>();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct adl_serializer<data_t> {
|
||||
static void
|
||||
to_json(json &j, const data_t &data) {
|
||||
j = json { { "opengl_swapchain", data.opengl_swapchain } };
|
||||
}
|
||||
|
||||
static void
|
||||
from_json(const json &j, data_t &data) {
|
||||
j.at("opengl_swapchain").get_to(data.opengl_swapchain);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct adl_serializer<opengl_swapchain_t> {
|
||||
static void
|
||||
to_json(json &j, const opengl_swapchain_t &opengl_swapchain) {
|
||||
j = json {
|
||||
{ "our_value", opengl_swapchain.our_value },
|
||||
{ "undo_value", opengl_swapchain.undo_value }
|
||||
};
|
||||
}
|
||||
|
||||
static void
|
||||
from_json(const json &j, opengl_swapchain_t &opengl_swapchain) {
|
||||
j.at("our_value").get_to(opengl_swapchain.our_value);
|
||||
j.at("undo_value").get_to(opengl_swapchain.undo_value);
|
||||
}
|
||||
};
|
||||
} // namespace nlohmann
|
||||
|
||||
namespace nvprefs {
|
||||
|
||||
void
|
||||
undo_data_t::set_opengl_swapchain(uint32_t our_value, std::optional<uint32_t> undo_value) {
|
||||
data.set_at_pointer(opengl_swapchain_our_value_key, our_value);
|
||||
if (undo_value) {
|
||||
data.set_at_pointer(opengl_swapchain_undo_value_key, *undo_value);
|
||||
}
|
||||
else {
|
||||
data.set_at_pointer(opengl_swapchain_undo_value_key, nullptr);
|
||||
}
|
||||
data.opengl_swapchain = data_t::opengl_swapchain_t {
|
||||
our_value,
|
||||
undo_value
|
||||
};
|
||||
}
|
||||
|
||||
std::tuple<bool, uint32_t, std::optional<uint32_t>>
|
||||
std::optional<undo_data_t::data_t::opengl_swapchain_t>
|
||||
undo_data_t::get_opengl_swapchain() const {
|
||||
auto get_value = [this](const auto &key) -> std::tuple<bool, std::optional<uint32_t>> {
|
||||
try {
|
||||
auto value = data.at_pointer(key);
|
||||
if (value.is_null()) {
|
||||
return { true, std::nullopt };
|
||||
}
|
||||
else if (value.is_number()) {
|
||||
return { true, value.template to_number<uint32_t>() };
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
error_message(std::string("Couldn't find ") + key + " element");
|
||||
return { false, std::nullopt };
|
||||
};
|
||||
|
||||
auto [our_value_present, our_value] = get_value(opengl_swapchain_our_value_key);
|
||||
auto [undo_value_present, undo_value] = get_value(opengl_swapchain_undo_value_key);
|
||||
|
||||
if (!our_value_present || !undo_value_present || !our_value) {
|
||||
return { false, 0, std::nullopt };
|
||||
}
|
||||
|
||||
return { true, *our_value, undo_value };
|
||||
return data.opengl_swapchain;
|
||||
}
|
||||
|
||||
std::string
|
||||
undo_data_t::write() const {
|
||||
return boost::json::serialize(data);
|
||||
try {
|
||||
// Keep this assignment otherwise data will be treated as an array due to
|
||||
// initializer list shenanigangs.
|
||||
const json json_data = data;
|
||||
return json_data.dump();
|
||||
}
|
||||
catch (const std::exception &err) {
|
||||
error_message(std::string { "failed to serialize json data" });
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
undo_data_t::read(const std::vector<char> &buffer) {
|
||||
data = boost::json::parse(std::string_view(buffer.data(), buffer.size()));
|
||||
try {
|
||||
data = json::parse(std::begin(buffer), std::end(buffer));
|
||||
}
|
||||
catch (const std::exception &err) {
|
||||
error_message(std::string { "failed to parse json data: " } + err.what());
|
||||
data = {};
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
undo_data_t::merge(const undo_data_t &newer_data) {
|
||||
auto [opengl_swapchain_saved, opengl_swapchain_our_value, opengl_swapchain_undo_value] = newer_data.get_opengl_swapchain();
|
||||
if (opengl_swapchain_saved) {
|
||||
set_opengl_swapchain(opengl_swapchain_our_value, opengl_swapchain_undo_value);
|
||||
const auto &swapchain_data = newer_data.get_opengl_swapchain();
|
||||
if (swapchain_data) {
|
||||
set_opengl_swapchain(swapchain_data->our_value, swapchain_data->undo_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user