JSON.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. #pragma once
  2. #include "Builders/ColorBuilder.h"
  3. #include <glm/detail/qualifier.hpp>
  4. #include <glm/detail/type_vec1.hpp>
  5. #include <nlohmann/json.hpp>
  6. #include <optional>
  7. #include <string>
  8. #include <utility>
  9. #include "WallpaperEngine/Data/Builders/UserSettingBuilder.h"
  10. #include "WallpaperEngine/Data/Builders/VectorBuilder.h"
  11. #include "WallpaperEngine/Data/Model/Types.h"
  12. #include "WallpaperEngine/Data/Utils/SFINAE.h"
  13. #include "WallpaperEngine/Logging/Log.h"
  14. namespace WallpaperEngine::Data::JSON {
  15. using namespace WallpaperEngine::Data::Builders;
  16. using namespace WallpaperEngine::Data::Model;
  17. using namespace WallpaperEngine::Data::Utils::SFINAE;
  18. class JsonExtensions;
  19. using JSON = nlohmann::basic_json<
  20. std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, double, std::allocator,
  21. nlohmann::adl_serializer, std::vector<std::uint8_t>, JsonExtensions>;
  22. /**
  23. * Small extensions class that is used as base class of nlohmann's implementation.
  24. *
  25. * Provides shorthand methods to reduce the amount of handling required for specific situations
  26. * (mainly throwing readable exceptions when a value is missing, optional/default values, user settings...)
  27. */
  28. class JsonExtensions {
  29. public:
  30. using base_type = JSON;
  31. template <typename T, typename std::enable_if_t<is_glm_vec<T>::value, int> = 0> [[nodiscard]] T get () const {
  32. constexpr int length = GlmVecTraits<T>::length;
  33. constexpr glm::qualifier qualifier = GlmVecTraits<T>::qualifier;
  34. // call the specialized version of the function
  35. return get<length, typename GlmVecTraits<T>::type, qualifier> ();
  36. }
  37. template <int length, typename type, glm::qualifier qualifier>
  38. [[nodiscard]] glm::vec<length, type, qualifier> get () const {
  39. return VectorBuilder::parse<length, type, qualifier> (this->base ().get<std::string> ());
  40. }
  41. [[nodiscard]] Model::Color get () const { return ColorBuilder::parse (this->base ().get<std::string> ()); }
  42. [[nodiscard]] base_type require (const std::string& key, const std::string& message) const {
  43. auto base = this->base ();
  44. const auto it = base.find (key);
  45. if (it == base.end ()) {
  46. sLog.exception (message, ". Contents: ", base.dump ());
  47. }
  48. return *it;
  49. }
  50. template <typename T> [[nodiscard]] T require (const std::string& key, const std::string& message) const {
  51. auto base = this->base ();
  52. const auto it = base.find (key);
  53. if (it == base.end ()) {
  54. sLog.exception (message, ". Contents: ", base.dump ());
  55. }
  56. return (*it);
  57. }
  58. [[nodiscard]] std::optional<base_type> optional (const std::string& key) const noexcept {
  59. auto base = this->base ();
  60. const auto it = base.find (key);
  61. auto result = std::optional<base_type> {};
  62. if (it != base.end () && !it->is_null ()) {
  63. result.emplace (*it);
  64. }
  65. return result;
  66. }
  67. template <typename T> [[nodiscard]] std::optional<T> optional (const std::string& key) const noexcept {
  68. auto base = this->base ();
  69. const auto it = base.find (key);
  70. if (it == base.end () || it->is_null ()) {
  71. return std::nullopt;
  72. }
  73. return *it;
  74. }
  75. template <typename T> [[nodiscard]] T optional (const std::string& key, T defaultValue) const noexcept {
  76. auto base = this->base ();
  77. const auto it = base.find (key);
  78. if (it == base.end () || it->is_null ()) {
  79. return defaultValue;
  80. }
  81. return (*it);
  82. }
  83. [[nodiscard]] UserSettingUniquePtr user (const std::string& key, const Properties& properties) const;
  84. template <typename T>
  85. [[nodiscard]] UserSettingUniquePtr
  86. user (const std::string& key, const Properties& properties, T defaultValue) const {
  87. static_assert (std::is_same_v<T, Color> == false, "Use color() for color properties");
  88. const auto value = this->optional (key);
  89. if (!value.has_value ()) {
  90. return UserSettingBuilder::fromValue<T> (defaultValue);
  91. }
  92. // performs a second lookup, but handles the actual call to UserSettingParser outside of this header
  93. // this resolving the include loop
  94. return this->user (key, properties);
  95. }
  96. [[nodiscard]] UserSettingUniquePtr color (const std::string& key, const Properties& properties) const;
  97. [[nodiscard]] UserSettingUniquePtr
  98. color (const std::string& key, const Properties& properties, Color defaultValue) const {
  99. const auto value = this->optional (key);
  100. if (!value.has_value ()) {
  101. return UserSettingBuilder::fromValue<Color> (defaultValue);
  102. }
  103. // performs a second lookup, but handles the actual call to UserSettingParser outside of this header
  104. // this resolving the include loop
  105. return this->color (key, properties);
  106. }
  107. template <int length, typename type, glm::qualifier qualifier> operator glm::vec<length, type, qualifier> () const {
  108. return get<length, type, qualifier> ();
  109. }
  110. template <typename T, typename std::enable_if_t<is_glm_vec<T>::value> = 0> operator T () const {
  111. constexpr int length = GlmVecTraits<T>::length;
  112. constexpr glm::qualifier qualifier = GlmVecTraits<T>::qualifier;
  113. // call the specialized version of the function
  114. return operator glm::vec<length, typename GlmVecTraits<T>::type, qualifier> ();
  115. }
  116. private:
  117. /**
  118. * @return The base json object to be used by the extension methods
  119. */
  120. [[nodiscard]] const base_type& base () const { return *static_cast<const base_type*> (this); }
  121. };
  122. } // namespace WallpaperEngine::Data::JSON