diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2023-11-23 18:31:03 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2023-11-23 19:05:52 +0100 |
commit | e7d672ec1578319bad8e944e37c91fbcb8371e75 (patch) | |
tree | a6ac6b304ebcf5ada8323b755da68f7874da713b | |
parent | 710c2e9df4683ded59048a48a1d21dba9dd86e17 (diff) |
use explicit instantiation for vector serializers
-rw-r--r-- | serialize/magnum-color.cpp | 33 | ||||
-rw-r--r-- | serialize/magnum-color.hpp | 27 | ||||
-rw-r--r-- | serialize/magnum-vector.cpp | 130 | ||||
-rw-r--r-- | serialize/magnum-vector.hpp | 38 | ||||
-rw-r--r-- | serialize/magnum-vector2i.cpp | 56 | ||||
-rw-r--r-- | serialize/magnum-vector2i.hpp | 23 | ||||
-rw-r--r-- | serialize/wall-atlas.cpp | 2 |
7 files changed, 199 insertions, 110 deletions
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 <array> +#include <Magnum/Math/Color.h> +#include <nlohmann/json.hpp> + +namespace floormat { + +namespace { + +using c3_proxy = std::array<float, 3>; +using c4_proxy = std::array<float, 4>; +using c3ub_proxy = std::array<uint8_t, 3>; +using c4ub_proxy = std::array<uint8_t, 4>; + +} // namespace + +} // namespace floormat + +namespace nlohmann { + +using namespace floormat; + +void adl_serializer<Color3>::to_json(json& val, const Color3& p) { val = c3_proxy { p[0], p[1], p[2] }; } +void adl_serializer<Color3ub>::to_json(json& val, const Color3ub& p) { val = c3ub_proxy{ p[0], p[1], p[2] }; } +void adl_serializer<Color4>::to_json(json& val, const Color4& p) { val = c4_proxy { p[0], p[1], p[2], p[3] }; } +void adl_serializer<Color4ub>::to_json(json& val, const Color4ub& p) { val = c4ub_proxy{ p[0], p[1], p[2], p[3] }; } + +void adl_serializer<Color3>::from_json(const json& j, Color3& val) { auto p = c3_proxy{j}; val = { p[0], p[1], p[2] }; } +void adl_serializer<Color3ub>::from_json(const json& j, Color3ub& val) { auto p = c3ub_proxy{j}; val = { p[0], p[1], p[2] }; } +void adl_serializer<Color4>::from_json(const json& j, Color4& val) { auto p = c4_proxy{j}; val = { p[0], p[1], p[2], p[3] }; } +void adl_serializer<Color4ub>::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 <Magnum/Math/Math.h> +#include <nlohmann/json_fwd.hpp> + +template<> +struct nlohmann::adl_serializer<Magnum::Color3> { + 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<Magnum::Color4> { + 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<Magnum::Color3ub> { + 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<Magnum::Color4ub> { + 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 <Magnum/Math/Vector.h> +#include <cstdio> +#include <string> +#include <nlohmann/json.hpp> + +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<size_t N, typename T> +struct vec_serializer +{ + static void to_json(json& j, Math::Vector<N, T> val) + { + std::array<T, N> 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<N, T>& val) + { + std::array<T, N> array{}; + using nlohmann::from_json; + from_json(j, array); + for (auto i = 0uz; i < N; i++) + val[i] = array[i]; + } +}; + +template<typename T> +struct vec2_serializer +{ + static void to_json(json& j, Vector<2, T> val) + { + char buf[64]; + using type = std::conditional_t<std::is_signed_v<T>, intmax_t, uintmax_t>; + constexpr auto format_string = std::is_signed_v<T> ? "%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<std::is_signed_v<T>, intmax_t, uintmax_t>; + constexpr auto format_string = std::is_signed_v<T> ? "%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<size_t N, typename T> +void adl_serializer<Vector<N, T>>::to_json(json& j, Vector<N, T> val) +{ + if constexpr(N != 2 || !std::is_integral_v<T>) + vec_serializer<N, T>::to_json(j, val); + else + vec2_serializer<T>::to_json(j, val); +} + +template<size_t N, typename T> +void adl_serializer<Vector<N, T>>::from_json(const json& j, Vector<N, T>& val) +{ + if constexpr(N != 2 || !std::is_integral_v<T>) + vec_serializer<N, T>::from_json(j, val); + else + vec2_serializer<T>::from_json(j, val); +} + +#define FM_INST_VEC_SERIALIZER_1(N, Type) \ + template struct adl_serializer< Vector<N, Type>>; \ + template struct adl_serializer< Vector##N<Type>> + +#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 <Magnum/Math/Vector.h> -#include <nlohmann/json.hpp> +#include <nlohmann/json_fwd.hpp> namespace nlohmann { -template<size_t N, typename T> -struct adl_serializer<Magnum::Math::Vector<N, T>> { - using vec = Magnum::Math::Vector<N, T>; - static void to_json(json& j, const vec& val); - static void from_json(const json& j, vec& val); -}; - -template <size_t N, typename T> -void adl_serializer<Magnum::Math::Vector<N, T>>::to_json(json& j, const vec& val) +template<floormat::size_t N, typename T> +struct adl_serializer<Magnum::Math::Vector<N, T>> { - std::array<T, N> array{}; - for (auto i = 0uz; i < N; i++) - array[i] = val[i]; - using nlohmann::to_json; - to_json(j, array); -} - -template <size_t N, typename T> -void adl_serializer<Magnum::Math::Vector<N, T>>::from_json(const json& j, vec& val) -{ - std::array<T, N> 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<N, T> val); + static void from_json(const json& j, Magnum::Math::Vector<N, T>& val); +}; -template<typename T> requires (!std::is_integral_v<T>) struct adl_serializer<Magnum::Math::Vector2<T>> : adl_serializer<Magnum::Math::Vector<2, T>> {}; +template<typename T> struct adl_serializer<Magnum::Math::Vector2<T>> : adl_serializer<Magnum::Math::Vector<2, T>> {}; template<typename T> struct adl_serializer<Magnum::Math::Vector3<T>> : adl_serializer<Magnum::Math::Vector<3, T>> {}; template<typename T> struct adl_serializer<Magnum::Math::Vector4<T>> : adl_serializer<Magnum::Math::Vector<4, T>> {}; -template<typename T> struct adl_serializer<Magnum::Math::Color3<T>> : adl_serializer<Magnum::Math::Vector<3, T>> {}; -template<typename T> struct adl_serializer<Magnum::Math::Color4<T>> : adl_serializer<Magnum::Math::Vector<4, T>> {}; } // 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 <nlohmann/json.hpp> - -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<typename T> -requires std::is_integral_v<T> -void nlohmann::adl_serializer<Magnum::Math::Vector2<T>>::to_json(json& j, const Magnum::Math::Vector2<T>& val) -{ - char buf[64]; - using type = std::conditional_t<std::is_signed_v<T>, intmax_t, uintmax_t>; - constexpr auto format_string = std::is_signed_v<T> ? "%jd x %jd" : "%ju x %ju"; - snprintf(buf, sizeof(buf), format_string, (type)val[0], (type)val[1]); - j = buf; -} - -template<typename T> -requires std::is_integral_v<T> -void nlohmann::adl_serializer<Magnum::Math::Vector2<T>>::from_json(const json& j, Magnum::Math::Vector2<T>& val) -{ - using namespace floormat; - std::string str = j; - using type = std::conditional_t<std::is_signed_v<T>, intmax_t, uintmax_t>; - constexpr auto format_string = std::is_signed_v<T> ? "%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<Magnum::Math::Vector2<uint8_t>>; -template struct nlohmann::adl_serializer<Magnum::Math::Vector2<uint16_t>>; -template struct nlohmann::adl_serializer<Magnum::Math::Vector2<uint32_t>>; -template struct nlohmann::adl_serializer<Magnum::Math::Vector2<uint64_t>>; -template struct nlohmann::adl_serializer<Magnum::Math::Vector2<int8_t>>; -template struct nlohmann::adl_serializer<Magnum::Math::Vector2<int16_t>>; -template struct nlohmann::adl_serializer<Magnum::Math::Vector2<int32_t>>; -template struct nlohmann::adl_serializer<Magnum::Math::Vector2<int64_t>>; 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 <cstdio> -#include <string> -#include <Magnum/Math/Vector2.h> -#include <nlohmann/json_fwd.hpp> - -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<typename T> -requires std::is_integral_v<T> -struct adl_serializer<Magnum::Math::Vector2<T>> final -{ - static void to_json(json& j, const Magnum::Math::Vector2<T>& val); - static void from_json(const json& j, Magnum::Math::Vector2<T>& 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" |