generated from LizardByte/template-base
-
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add JSON serialization capabilities (#49)
- Loading branch information
1 parent
dbceacf
commit 4e8fd6d
Showing
24 changed files
with
587 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# | ||
# Loads the nlohmann_json library giving the priority to the system package first, with a fallback | ||
# to the submodule. | ||
# | ||
include_guard(GLOBAL) | ||
|
||
find_package(nlohmann_json 3.11 QUIET GLOBAL) | ||
if(NOT nlohmann_json_FOUND) | ||
message(STATUS "nlohmann_json v3.11.x package not found in the system. Falling back to submodule.") | ||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../third-party/json third-party/json) | ||
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
#pragma once | ||
|
||
#ifdef DD_JSON_DETAIL | ||
// system includes | ||
#include <nlohmann/json.hpp> | ||
|
||
namespace display_device { | ||
// A shared "toJson" implementation. Extracted here for UTs + coverage. | ||
template <typename Type> | ||
std::string | ||
toJsonHelper(const Type &obj, const std::optional<unsigned int> &indent, bool *success) { | ||
try { | ||
if (success) { | ||
*success = true; | ||
} | ||
|
||
nlohmann::json json_obj = obj; | ||
return json_obj.dump(static_cast<int>(indent.value_or(-1))); | ||
} | ||
catch (const std::exception &err) { // GCOVR_EXCL_BR_LINE for fallthrough branch | ||
if (success) { | ||
*success = false; | ||
} | ||
|
||
return err.what(); | ||
} | ||
} | ||
|
||
// A shared "fromJson" implementation. Extracted here for UTs + coverage. | ||
template <typename Type> | ||
bool | ||
fromJsonHelper(const std::string &string, Type &obj, std::string *error_message = nullptr) { | ||
try { | ||
if (error_message) { | ||
error_message->clear(); | ||
} | ||
|
||
Type parsed_obj = nlohmann::json::parse(string); | ||
obj = std::move(parsed_obj); | ||
return true; | ||
} | ||
catch (const std::exception &err) { | ||
if (error_message) { | ||
*error_message = err.what(); | ||
} | ||
|
||
return false; | ||
} | ||
} | ||
|
||
#define DD_JSON_DEFINE_CONVERTER(Type) \ | ||
std::string toJson(const Type &obj, const std::optional<unsigned int> &indent, bool *success) { \ | ||
return toJsonHelper(obj, indent, success); \ | ||
} \ | ||
bool fromJson(const std::string &string, Type &obj, std::string *error_message) { \ | ||
return fromJsonHelper<Type>(string, obj, error_message); \ | ||
} | ||
} // namespace display_device | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#pragma once | ||
|
||
// local includes | ||
#include "jsonserializerdetails.h" | ||
|
||
#ifdef DD_JSON_DETAIL | ||
namespace display_device { | ||
// Enums | ||
DD_JSON_DECLARE_SERIALIZE_TYPE(HdrState) | ||
DD_JSON_DECLARE_SERIALIZE_TYPE(SingleDisplayConfiguration::DevicePreparation) | ||
|
||
// Structs | ||
DD_JSON_DECLARE_SERIALIZE_TYPE(Resolution) | ||
DD_JSON_DECLARE_SERIALIZE_TYPE(Point) | ||
DD_JSON_DECLARE_SERIALIZE_TYPE(EnumeratedDevice::Info) | ||
DD_JSON_DECLARE_SERIALIZE_TYPE(EnumeratedDevice) | ||
DD_JSON_DECLARE_SERIALIZE_TYPE(SingleDisplayConfiguration) | ||
} // namespace display_device | ||
#endif |
84 changes: 84 additions & 0 deletions
84
src/common/include/displaydevice/detail/jsonserializerdetails.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
#pragma once | ||
|
||
#ifdef DD_JSON_DETAIL | ||
// system includes | ||
#include <nlohmann/json.hpp> | ||
|
||
// Special versions of the NLOHMANN definitions to remove the "m_" prefix in string form ('cause I like it that way ;P) | ||
#define DD_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.m_##v1; | ||
#define DD_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.m_##v1); | ||
|
||
// Coverage has trouble with inlined functions when they are included in different units, | ||
// therefore the usual macro was split into declaration and definition | ||
#define DD_JSON_DECLARE_SERIALIZE_TYPE(Type) \ | ||
void to_json(nlohmann::json &nlohmann_json_j, const Type &nlohmann_json_t); \ | ||
void from_json(const nlohmann::json &nlohmann_json_j, Type &nlohmann_json_t); | ||
|
||
#define DD_JSON_DEFINE_SERIALIZE_STRUCT(Type, ...) \ | ||
void to_json(nlohmann::json &nlohmann_json_j, const Type &nlohmann_json_t) { \ | ||
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(DD_JSON_TO, __VA_ARGS__)) \ | ||
} \ | ||
\ | ||
void from_json(const nlohmann::json &nlohmann_json_j, Type &nlohmann_json_t) { \ | ||
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(DD_JSON_FROM, __VA_ARGS__)) \ | ||
} | ||
|
||
// Coverage has trouble with getEnumMap() function since it has a lot of "fallthrough" | ||
// branches when creating a map, therefore the macro has baked in pattern to disable branch coverage | ||
// in GCOVR | ||
#define DD_JSON_DEFINE_SERIALIZE_ENUM_GCOVR_EXCL_BR_LINE(Type, ...) \ | ||
const std::map<Type, nlohmann::json> & \ | ||
getEnumMap(const Type &) { \ | ||
static_assert(std::is_enum<Type>::value, #Type " must be an enum!"); \ | ||
static const std::map<Type, nlohmann::json> map = __VA_ARGS__; \ | ||
return map; \ | ||
} \ | ||
\ | ||
void to_json(nlohmann::json &nlohmann_json_j, const Type &nlohmann_json_t) { \ | ||
nlohmann_json_j = findInEnumMap<Type>(#Type " is missing enum mapping!", [nlohmann_json_t](const auto &pair) { return pair.first == nlohmann_json_t; })->second; \ | ||
} \ | ||
\ | ||
void from_json(const nlohmann::json &nlohmann_json_j, Type &nlohmann_json_t) { \ | ||
nlohmann_json_t = findInEnumMap<Type>(#Type " is missing enum mapping!", [&nlohmann_json_j](const auto &pair) { return pair.second == nlohmann_json_j; })->first; \ | ||
} | ||
|
||
namespace display_device { | ||
// A shared function for enums to find values in the map. Extracted here for UTs + coverage | ||
template <class T, class Predicate> | ||
std::map<T, nlohmann::json>::const_iterator | ||
findInEnumMap(const char *error_msg, Predicate predicate) { | ||
const auto &map { getEnumMap(T {}) }; | ||
auto it { std::find_if(std::begin(map), std::end(map), predicate) }; | ||
if (it == std::end(map)) { // GCOVR_EXCL_BR_LINE for fallthrough branch | ||
throw std::runtime_error(error_msg); // GCOVR_EXCL_BR_LINE for fallthrough branch | ||
} | ||
return it; | ||
} | ||
} // namespace display_device | ||
|
||
namespace nlohmann { | ||
// Specialization for optional types until they actually implement it. | ||
template <typename T> | ||
struct adl_serializer<std::optional<T>> { | ||
static void | ||
to_json(json &nlohmann_json_j, const std::optional<T> &nlohmann_json_t) { | ||
if (nlohmann_json_t == std::nullopt) { | ||
nlohmann_json_j = nullptr; | ||
} | ||
else { | ||
nlohmann_json_j = *nlohmann_json_t; | ||
} | ||
} | ||
|
||
static void | ||
from_json(const json &nlohmann_json_j, std::optional<T> &nlohmann_json_t) { | ||
if (nlohmann_json_j.is_null()) { | ||
nlohmann_json_t = std::nullopt; | ||
} | ||
else { | ||
nlohmann_json_t = nlohmann_json_j.template get<T>(); | ||
} | ||
} | ||
}; | ||
} // namespace nlohmann | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#pragma once | ||
|
||
// local includes | ||
#include "types.h" | ||
|
||
/** | ||
* @brief Helper MACRO to declare the toJson and fromJson converters for a type. | ||
* | ||
* EXAMPLES: | ||
* ```cpp | ||
* EnumeratedDeviceList devices; | ||
* DD_LOG(info) << "Got devices:\n" << toJson(devices); | ||
* ``` | ||
*/ | ||
#define DD_JSON_DECLARE_CONVERTER(Type) \ | ||
[[nodiscard]] std::string toJson(const Type &obj, const std::optional<unsigned int> &indent = 2u, bool *success = nullptr); \ | ||
[[nodiscard]] bool fromJson(const std::string &string, Type &obj, std::string *error_message = nullptr); // NOLINT(*-macro-parentheses) | ||
|
||
// Shared converters (add as needed) | ||
namespace display_device { | ||
DD_JSON_DECLARE_CONVERTER(EnumeratedDeviceList) | ||
DD_JSON_DECLARE_CONVERTER(SingleDisplayConfiguration) | ||
} // namespace display_device |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// header include | ||
#include "displaydevice/json.h" | ||
|
||
// special ordered include of details | ||
#define DD_JSON_DETAIL | ||
// clang-format off | ||
#include "displaydevice/detail/jsonserializer.h" | ||
#include "displaydevice/detail/jsonconverter.h" | ||
// clang-format on | ||
|
||
namespace display_device { | ||
DD_JSON_DEFINE_CONVERTER(EnumeratedDeviceList) | ||
DD_JSON_DEFINE_CONVERTER(SingleDisplayConfiguration) | ||
} // namespace display_device |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// special ordered include of details | ||
#define DD_JSON_DETAIL | ||
// clang-format off | ||
#include "displaydevice/types.h" | ||
#include "displaydevice/detail/jsonserializer.h" | ||
// clang-format on | ||
|
||
namespace display_device { | ||
// Enums | ||
DD_JSON_DEFINE_SERIALIZE_ENUM_GCOVR_EXCL_BR_LINE(HdrState, { { HdrState::Disabled, "Disabled" }, | ||
{ HdrState::Enabled, "Enabled" } }) | ||
DD_JSON_DEFINE_SERIALIZE_ENUM_GCOVR_EXCL_BR_LINE(SingleDisplayConfiguration::DevicePreparation, { { SingleDisplayConfiguration::DevicePreparation::VerifyOnly, "VerifyOnly" }, | ||
{ SingleDisplayConfiguration::DevicePreparation::EnsureActive, "EnsureActive" }, | ||
{ SingleDisplayConfiguration::DevicePreparation::EnsurePrimary, "EnsurePrimary" }, | ||
{ SingleDisplayConfiguration::DevicePreparation::EnsureOnlyDisplay, "EnsureOnlyDisplay" } }) | ||
|
||
// Structs | ||
DD_JSON_DEFINE_SERIALIZE_STRUCT(Resolution, width, height) | ||
DD_JSON_DEFINE_SERIALIZE_STRUCT(Point, x, y) | ||
DD_JSON_DEFINE_SERIALIZE_STRUCT(EnumeratedDevice::Info, resolution, resolution_scale, refresh_rate, primary, origin_point, hdr_state) | ||
DD_JSON_DEFINE_SERIALIZE_STRUCT(EnumeratedDevice, device_id, display_name, friendly_name, info) | ||
DD_JSON_DEFINE_SERIALIZE_STRUCT(SingleDisplayConfiguration, device_id, device_prep, resolution, refresh_rate, hdr_state) | ||
} // namespace display_device |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
src/windows/include/displaydevice/windows/detail/jsonserializer.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#pragma once | ||
|
||
// local includes | ||
#include "displaydevice/detail/jsonserializer.h" | ||
|
||
#ifdef DD_JSON_DETAIL | ||
namespace display_device { | ||
// Structs | ||
DD_JSON_DECLARE_SERIALIZE_TYPE(Rational) | ||
DD_JSON_DECLARE_SERIALIZE_TYPE(DisplayMode) | ||
} // namespace display_device | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#pragma once | ||
|
||
// local includes | ||
#include "displaydevice/json.h" | ||
#include "types.h" | ||
|
||
// Windows' converters (add as needed) | ||
namespace display_device { | ||
DD_JSON_DECLARE_CONVERTER(ActiveTopology) | ||
DD_JSON_DECLARE_CONVERTER(DeviceDisplayModeMap) | ||
DD_JSON_DECLARE_CONVERTER(HdrStateMap) | ||
} // namespace display_device |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// header include | ||
#include "displaydevice/windows/json.h" | ||
|
||
// special ordered include of details | ||
#define DD_JSON_DETAIL | ||
// clang-format off | ||
#include "displaydevice/windows/detail/jsonserializer.h" | ||
#include "displaydevice/detail/jsonconverter.h" | ||
// clang-format on | ||
|
||
namespace display_device { | ||
DD_JSON_DEFINE_CONVERTER(ActiveTopology) | ||
DD_JSON_DEFINE_CONVERTER(DeviceDisplayModeMap) | ||
DD_JSON_DEFINE_CONVERTER(HdrStateMap) | ||
} // namespace display_device |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// special ordered include of details | ||
#define DD_JSON_DETAIL | ||
// clang-format off | ||
#include "displaydevice/windows/types.h" | ||
#include "displaydevice/windows/detail/jsonserializer.h" | ||
// clang-format on | ||
|
||
namespace display_device { | ||
// Structs | ||
DD_JSON_DEFINE_SERIALIZE_STRUCT(Rational, numerator, denominator) | ||
DD_JSON_DEFINE_SERIALIZE_STRUCT(DisplayMode, resolution, refresh_rate) | ||
} // namespace display_device |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.