From e7d672ec1578319bad8e944e37c91fbcb8371e75 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 23 Nov 2023 18:31:03 +0100 Subject: use explicit instantiation for vector serializers --- serialize/magnum-color.cpp | 33 +++++++++++ serialize/magnum-color.hpp | 27 +++++++++ serialize/magnum-vector.cpp | 130 ++++++++++++++++++++++++++++++++++++++++++ serialize/magnum-vector.hpp | 38 +++--------- serialize/magnum-vector2i.cpp | 56 ------------------ serialize/magnum-vector2i.hpp | 23 +------- serialize/wall-atlas.cpp | 2 +- 7 files changed, 199 insertions(+), 110 deletions(-) create mode 100644 serialize/magnum-color.cpp create mode 100644 serialize/magnum-color.hpp create mode 100644 serialize/magnum-vector.cpp delete mode 100644 serialize/magnum-vector2i.cpp diff --git a/serialize/magnum-color.cpp b/serialize/magnum-color.cpp new file mode 100644 index 00000000..390ce1f3 --- /dev/null +++ b/serialize/magnum-color.cpp @@ -0,0 +1,33 @@ +#include "magnum-color.hpp" +#include +#include +#include + +namespace floormat { + +namespace { + +using c3_proxy = std::array; +using c4_proxy = std::array; +using c3ub_proxy = std::array; +using c4ub_proxy = std::array; + +} // namespace + +} // namespace floormat + +namespace nlohmann { + +using namespace floormat; + +void adl_serializer::to_json(json& val, const Color3& p) { val = c3_proxy { p[0], p[1], p[2] }; } +void adl_serializer::to_json(json& val, const Color3ub& p) { val = c3ub_proxy{ p[0], p[1], p[2] }; } +void adl_serializer::to_json(json& val, const Color4& p) { val = c4_proxy { p[0], p[1], p[2], p[3] }; } +void adl_serializer::to_json(json& val, const Color4ub& p) { val = c4ub_proxy{ p[0], p[1], p[2], p[3] }; } + +void adl_serializer::from_json(const json& j, Color3& val) { auto p = c3_proxy{j}; val = { p[0], p[1], p[2] }; } +void adl_serializer::from_json(const json& j, Color3ub& val) { auto p = c3ub_proxy{j}; val = { p[0], p[1], p[2] }; } +void adl_serializer::from_json(const json& j, Color4& val) { auto p = c4_proxy{j}; val = { p[0], p[1], p[2], p[3] }; } +void adl_serializer::from_json(const json& j, Color4ub& val) { auto p = c4ub_proxy{j}; val = { p[0], p[1], p[2], p[3] }; } + +} // namespace nlohmann diff --git a/serialize/magnum-color.hpp b/serialize/magnum-color.hpp new file mode 100644 index 00000000..863eb711 --- /dev/null +++ b/serialize/magnum-color.hpp @@ -0,0 +1,27 @@ +#pragma once +#include +#include + +template<> +struct nlohmann::adl_serializer { + static void to_json(json& j, const Magnum::Color3& val); + static void from_json(const json& j, Magnum::Color3& val); +}; + +template<> +struct nlohmann::adl_serializer { + static void to_json(json& j, const Magnum::Color4& val); + static void from_json(const json& j, Magnum::Color4& val); +}; + +template<> +struct nlohmann::adl_serializer { + static void to_json(json& j, const Magnum::Color3ub& val); + static void from_json(const json& j, Magnum::Color3ub& val); +}; + +template<> +struct nlohmann::adl_serializer { + static void to_json(json& j, const Magnum::Color4ub& val); + static void from_json(const json& j, Magnum::Color4ub& val); +}; diff --git a/serialize/magnum-vector.cpp b/serialize/magnum-vector.cpp new file mode 100644 index 00000000..151730be --- /dev/null +++ b/serialize/magnum-vector.cpp @@ -0,0 +1,130 @@ +#include "magnum-vector.hpp" +#include "compat/format.hpp" +#include "compat/exception.hpp" +#include +#include +#include +#include + +namespace floormat::Serialize { + +namespace { + +[[noreturn]] void throw_failed_to_parse_vector2(const std::string& str) +{ + fm_throw("failed to parse Vector2 '{}'"_cf, str); +} + +[[noreturn]] void throw_vector2_overflow(const std::string& str) +{ + fm_throw("numeric overflow in Vector2 '{}'"_cf, str); +} + +using nlohmann::json; +using Math::Vector; +using Math::Vector2; +using Math::Vector3; +using Math::Vector4; + +template +struct vec_serializer +{ + static void to_json(json& j, Math::Vector val) + { + std::array array{}; + for (auto i = 0uz; i < N; i++) + array[i] = val[i]; + using nlohmann::to_json; + to_json(j, array); + } + static void from_json(const json& j, Math::Vector& val) + { + std::array array{}; + using nlohmann::from_json; + from_json(j, array); + for (auto i = 0uz; i < N; i++) + val[i] = array[i]; + } +}; + +template +struct vec2_serializer +{ + static void to_json(json& j, Vector<2, T> val) + { + char buf[64]; + using type = std::conditional_t, intmax_t, uintmax_t>; + constexpr auto format_string = std::is_signed_v ? "%jd x %jd" : "%ju x %ju"; + snprintf(buf, sizeof(buf), format_string, (type)val[0], (type)val[1]); + j = buf; + } + + static void from_json(const json& j, Vector<2, T>& val) + { + using namespace floormat; + std::string str = j; + using type = std::conditional_t, intmax_t, uintmax_t>; + constexpr auto format_string = std::is_signed_v ? "%jd x %jd%n" : "%ju x %ju%n"; + type x = 0, y = 0; + int n = 0; + int ret = std::sscanf(str.data(), format_string, &x, &y, &n); + if (ret != 2 || (size_t)n != str.size() || x != (T)x || y != (T)y) + throw_failed_to_parse_vector2(str); + if constexpr(sizeof(T) < sizeof(type)) + if (x != (type)(T)x || y != (type)(T)y) + throw_vector2_overflow(str); + val = { (T)x, (T)y }; + } +}; + +} // namespace +} // namespace floormat::Serialize + +namespace nlohmann { + +using floormat::Serialize::vec_serializer; +using floormat::Serialize::vec2_serializer; +using floormat::size_t; +using namespace Magnum::Math; + +template +void adl_serializer>::to_json(json& j, Vector val) +{ + if constexpr(N != 2 || !std::is_integral_v) + vec_serializer::to_json(j, val); + else + vec2_serializer::to_json(j, val); +} + +template +void adl_serializer>::from_json(const json& j, Vector& val) +{ + if constexpr(N != 2 || !std::is_integral_v) + vec_serializer::from_json(j, val); + else + vec2_serializer::from_json(j, val); +} + +#define FM_INST_VEC_SERIALIZER_1(N, Type) \ + template struct adl_serializer< Vector>; \ + template struct adl_serializer< Vector##N> + +#define FM_INST_VEC_SERIALIZER_F(Type) \ + +#define FM_INST_VEC_SERIALIZER(Type) \ + FM_INST_VEC_SERIALIZER_1(Type, float); \ + FM_INST_VEC_SERIALIZER_1(Type, double); \ + FM_INST_VEC_SERIALIZER_1(Type, int8_t); \ + FM_INST_VEC_SERIALIZER_1(Type, int16_t); \ + FM_INST_VEC_SERIALIZER_1(Type, int32_t); \ + FM_INST_VEC_SERIALIZER_1(Type, int64_t); \ + FM_INST_VEC_SERIALIZER_1(Type, uint8_t); \ + FM_INST_VEC_SERIALIZER_1(Type, uint16_t); \ + FM_INST_VEC_SERIALIZER_1(Type, uint32_t); \ + FM_INST_VEC_SERIALIZER_1(Type, uint64_t) + +FM_INST_VEC_SERIALIZER(2); +FM_INST_VEC_SERIALIZER(3); +FM_INST_VEC_SERIALIZER(4); + +} // namespace nlohmann diff --git a/serialize/magnum-vector.hpp b/serialize/magnum-vector.hpp index ddd09228..ac6206d6 100644 --- a/serialize/magnum-vector.hpp +++ b/serialize/magnum-vector.hpp @@ -1,41 +1,17 @@ #pragma once -#include "magnum-vector2i.hpp" -#include -#include +#include namespace nlohmann { -template -struct adl_serializer> { - using vec = Magnum::Math::Vector; - static void to_json(json& j, const vec& val); - static void from_json(const json& j, vec& val); -}; - -template -void adl_serializer>::to_json(json& j, const vec& val) +template +struct adl_serializer> { - std::array array{}; - for (auto i = 0uz; i < N; i++) - array[i] = val[i]; - using nlohmann::to_json; - to_json(j, array); -} - -template -void adl_serializer>::from_json(const json& j, vec& val) -{ - std::array array{}; - using nlohmann::from_json; - from_json(j, array); - for (auto i = 0uz; i < N; i++) - val[i] = array[i]; -} + static void to_json(json& j, Magnum::Math::Vector val); + static void from_json(const json& j, Magnum::Math::Vector& val); +}; -template requires (!std::is_integral_v) struct adl_serializer> : adl_serializer> {}; +template struct adl_serializer> : adl_serializer> {}; template struct adl_serializer> : adl_serializer> {}; template struct adl_serializer> : adl_serializer> {}; -template struct adl_serializer> : adl_serializer> {}; -template struct adl_serializer> : adl_serializer> {}; } // namespace nlohmann diff --git a/serialize/magnum-vector2i.cpp b/serialize/magnum-vector2i.cpp deleted file mode 100644 index 0b52d508..00000000 --- a/serialize/magnum-vector2i.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "magnum-vector2i.hpp" -#include "compat/exception.hpp" -#include - -using namespace floormat; - -void floormat::Serialize::throw_failed_to_parse_vector2(const std::string& str) -{ - fm_throw("failed to parse Vector2 '{}'"_cf, str); -} - -void floormat::Serialize::throw_vector2_overflow(const std::string& str) -{ - fm_throw("numeric overflow in Vector2 '{}'"_cf, str); -} - -using namespace nlohmann; - -template -requires std::is_integral_v -void nlohmann::adl_serializer>::to_json(json& j, const Magnum::Math::Vector2& val) -{ - char buf[64]; - using type = std::conditional_t, intmax_t, uintmax_t>; - constexpr auto format_string = std::is_signed_v ? "%jd x %jd" : "%ju x %ju"; - snprintf(buf, sizeof(buf), format_string, (type)val[0], (type)val[1]); - j = buf; -} - -template -requires std::is_integral_v -void nlohmann::adl_serializer>::from_json(const json& j, Magnum::Math::Vector2& val) -{ - using namespace floormat; - std::string str = j; - using type = std::conditional_t, intmax_t, uintmax_t>; - constexpr auto format_string = std::is_signed_v ? "%jd x %jd%n" : "%ju x %ju%n"; - type x = 0, y = 0; - int n = 0; - int ret = std::sscanf(str.data(), format_string, &x, &y, &n); - if (ret != 2 || (size_t)n != str.size() || x != (T)x || y != (T)y) - floormat::Serialize::throw_failed_to_parse_vector2(str); - if constexpr(sizeof(T) < sizeof(type)) - if (x != (type)(T)x || y != (type)(T)y) - floormat::Serialize::throw_vector2_overflow(str); - val = { (T)x, (T)y }; -} - -template struct nlohmann::adl_serializer>; -template struct nlohmann::adl_serializer>; -template struct nlohmann::adl_serializer>; -template struct nlohmann::adl_serializer>; -template struct nlohmann::adl_serializer>; -template struct nlohmann::adl_serializer>; -template struct nlohmann::adl_serializer>; -template struct nlohmann::adl_serializer>; diff --git a/serialize/magnum-vector2i.hpp b/serialize/magnum-vector2i.hpp index ddb79e98..caed2275 100644 --- a/serialize/magnum-vector2i.hpp +++ b/serialize/magnum-vector2i.hpp @@ -1,23 +1,2 @@ #pragma once -#include "compat/assert.hpp" -#include -#include -#include -#include - -namespace floormat::Serialize { - [[noreturn]] void throw_failed_to_parse_vector2(const std::string& str); - [[noreturn]] void throw_vector2_overflow(const std::string& str); -} - -namespace nlohmann { - -template -requires std::is_integral_v -struct adl_serializer> final -{ - static void to_json(json& j, const Magnum::Math::Vector2& val); - static void from_json(const json& j, Magnum::Math::Vector2& val); -}; - -} // namespace nlohmann +#include "magnum-vector.hpp" diff --git a/serialize/wall-atlas.cpp b/serialize/wall-atlas.cpp index c045678b..3d4a90dd 100644 --- a/serialize/wall-atlas.cpp +++ b/serialize/wall-atlas.cpp @@ -1,6 +1,6 @@ #include "wall-atlas.hpp" -#include "magnum-vector2i.hpp" #include "magnum-vector.hpp" +#include "magnum-color.hpp" #include "corrade-string.hpp" #include "compat/exception.hpp" #include "loader/loader.hpp" -- cgit v1.2.3