diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2022-10-05 15:47:29 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2022-10-05 15:47:29 +0200 |
commit | 6731ab0243ba437595062558e56b800d5eca9cf5 (patch) | |
tree | 39025a8ca381ff6f71cbe316c7d72b32f506a9bf /serialize | |
parent | 2c26d57dc97eb7105a6dca2089fd42847a8c2b37 (diff) |
a
Diffstat (limited to 'serialize')
-rw-r--r-- | serialize/CMakeLists.txt | 5 | ||||
-rw-r--r-- | serialize/anim.cpp | 36 | ||||
-rw-r--r-- | serialize/anim.hpp | 47 | ||||
-rw-r--r-- | serialize/helper.hpp | 62 | ||||
-rw-r--r-- | serialize/vector.hpp | 41 |
5 files changed, 191 insertions, 0 deletions
diff --git a/serialize/CMakeLists.txt b/serialize/CMakeLists.txt new file mode 100644 index 00000000..e695aff2 --- /dev/null +++ b/serialize/CMakeLists.txt @@ -0,0 +1,5 @@ +find_package(nlohmann_json QUIET REQUIRED) +set(self "${PROJECT_NAME}-serialize") +link_libraries(Magnum::Magnum nlohmann_json::nlohmann_json) +file(GLOB sources "*.cpp" CONFIGURE_ARGS) +add_library(${self} STATIC ${sources}) diff --git a/serialize/anim.cpp b/serialize/anim.cpp new file mode 100644 index 00000000..c65c24a6 --- /dev/null +++ b/serialize/anim.cpp @@ -0,0 +1,36 @@ +#include "serialize/vector.hpp" +#include "serialize/helper.hpp" +#include "serialize/anim.hpp" + +#include <tuple> +#include <filesystem> +#include <Corrade/Utility/Debug.h> +#include <Corrade/Utility/DebugStl.h> + +namespace Magnum::Examples::Serialize { + +#if defined __clang__ || defined __CLION_IDE__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wweak-vtables" +# pragma clang diagnostic ignored "-Wcovered-switch-default" +#endif + +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(anim_frame, ground, offset, size) +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(anim_group, name, frames, ground) +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(anim, name, nframes, actionframe, fps, groups, width, height) + +#if defined __clang__ || defined __CLION_IDE__ +# pragma clang diagnostic pop +#endif + +std::tuple<anim, bool> anim::from_json(const std::filesystem::path& pathname) noexcept +{ + return json_helper<anim>::from_json(pathname); +} + +bool anim::to_json(const std::filesystem::path& pathname) const noexcept +{ + return json_helper<anim>::to_json(*this, pathname); +} + +} // namespace Magnum::Examples::Serialize diff --git a/serialize/anim.hpp b/serialize/anim.hpp new file mode 100644 index 00000000..f03e3c8c --- /dev/null +++ b/serialize/anim.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include <tuple> +#include <array> +#include <vector> +#include <string> + +#include <Magnum/Magnum.h> +#include <Magnum/Math/Vector2.h> + +namespace std::filesystem { class path; } + +namespace Magnum::Examples::Serialize { + +struct anim_frame final +{ + Magnum::Vector2i ground, offset, size; +}; + +enum class anim_direction : unsigned char +{ + N, NE, E, SE, S, SW, W, NW, + COUNT, +}; + +struct anim_group final +{ + std::string name; + std::vector<anim_frame> frames; + Magnum::Vector2i ground; +}; + +struct anim final +{ + static std::tuple<anim, bool> from_json(const std::filesystem::path& pathname) noexcept; + [[nodiscard]] bool to_json(const std::filesystem::path& pathname) const noexcept; + static constexpr int default_fps = 24; + + std::string name; + std::array<anim_group, (std::size_t)anim_direction::COUNT> groups; + int nframes = 0; + int width = 0, height = 0; + int actionframe = -1, fps = default_fps; +}; + +} // namespace Magnum::Examples::Serialize + diff --git a/serialize/helper.hpp b/serialize/helper.hpp new file mode 100644 index 00000000..f16ed60c --- /dev/null +++ b/serialize/helper.hpp @@ -0,0 +1,62 @@ +#pragma once +#include <tuple> +#include <fstream> +#include <exception> +#include <filesystem> +#include <nlohmann/json.hpp> +#include <Corrade/Utility/DebugStl.h> + +template<typename t> +struct json_helper final { + [[nodiscard]] static std::tuple<t, bool> from_json(const std::filesystem::path& pathname) noexcept; + [[nodiscard]] static bool to_json(const t& self, const std::filesystem::path& pathname) noexcept; +}; + +template<typename t> +std::tuple<t, bool> json_helper<t>::from_json(const std::filesystem::path& pathname) noexcept { + using namespace nlohmann; + using Corrade::Utility::Error; + std::ifstream s; + s.exceptions(s.exceptions() | std::ios::failbit | std::ios::badbit); + try { + s.open(pathname, std::ios_base::in); + } catch (const std::ios::failure& e) { + Error{Error::Flag::NoSpace} << "failed to open '" << pathname << "': " << e.what(); + return { {}, false }; + } + t ret; + try { + json j; + s >> j; + using nlohmann::from_json; + from_json(j, ret); + } catch (const std::exception& e) { + Error{Error::Flag::NoSpace} << "failed to parse '" << pathname << "': " << e.what(); + return { {}, false }; + } + return { std::move(ret), true }; +} + +template<typename t> +bool json_helper<t>::to_json(const t& self, const std::filesystem::path& pathname) noexcept { + using Corrade::Utility::Error; + try { + nlohmann::json j = self; + + std::ofstream s; + s.exceptions(s.exceptions() | std::ios::failbit | std::ios::badbit); + try { + s.open(pathname, std::ios_base::out | std::ios_base::trunc); + } catch (const std::ios::failure& e) { + Error{Error::Flag::NoSpace} << "failed to open '" << pathname << "' for writing: " << e.what(); + return false; + } + s << j.dump(4); + s.flush(); + } catch (const std::exception& e) { + Error{Error::Flag::NoSpace} << "failed writing to '" << pathname << "': " << e.what(); + return false; + } + + return true; +} diff --git a/serialize/vector.hpp b/serialize/vector.hpp new file mode 100644 index 00000000..39924a9b --- /dev/null +++ b/serialize/vector.hpp @@ -0,0 +1,41 @@ +#include <cstdio> +#include <string> +#include <exception> +#include <Magnum/Magnum.h> +#include <Magnum/Math/Vector2.h> +#include <nlohmann/json.hpp> + +namespace nlohmann { + +template<typename t> +struct adl_serializer<Magnum::Math::Vector2<t>> final { + static void to_json(json& j, const Magnum::Math::Vector2<t>& x); + static void from_json(const json& j, Magnum::Math::Vector2<t>& x); +}; + +template<typename t> +void adl_serializer<Magnum::Math::Vector2<t>>::to_json(json& j, const Magnum::Math::Vector2<t>& val) +{ + char buf[64]; + snprintf(buf, sizeof(buf), "%d x %d", val[0], val[1]); + j = buf; +} + +template<typename t> +void adl_serializer<Magnum::Math::Vector2<t>>::from_json(const json& j, Magnum::Math::Vector2<t>& val) +{ + std::string str = j; + int x = 0, y = 0, n = 0; + int ret = std::sscanf(str.c_str(), "%d x %d%n", &x, &y, &n); + if (ret != 2 || (std::size_t)n != str.size()) + { + std::string msg; msg.reserve(64 + str.size()); + msg += "failed to parse string '"; + msg += str; + msg += "' as Magnum::Vector2i"; + throw std::invalid_argument(msg); + } + val = { x, y }; +} + +} // namespace nlohmann |