// license:GPL-2.0+ // copyright-holders:Couriersud #ifndef PSTATE_H_ #define PSTATE_H_ /// /// \file pstate.h /// #include "palloc.h" #include "pstring.h" #include "ptypes.h" #include #include #include // ---------------------------------------------------------------------------------------- // state saving ... // ---------------------------------------------------------------------------------------- namespace plib { class state_manager_t { public: struct datatype_t { datatype_t(std::size_t bsize, bool bintegral, bool bfloat) : m_size(bsize), m_is_integral(bintegral), m_is_float(bfloat), m_is_custom(false) {} explicit datatype_t(bool bcustom) : m_size(0), m_is_integral(false), m_is_float(false), m_is_custom(bcustom) {} std::size_t size() const noexcept { return m_size; } bool is_integral() const noexcept { return m_is_integral; } bool is_float() const noexcept { return m_is_float; } bool is_custom() const noexcept { return m_is_custom; } private: std::size_t m_size; bool m_is_integral; bool m_is_float; bool m_is_custom; }; template static datatype_t dtype() { return datatype_t(sizeof(T), plib::is_integral::value || std::is_enum::value, std::is_floating_point::value); } class callback_t { public: using list_t = std::vector; virtual void register_state(state_manager_t &manager, const pstring &module) = 0; virtual void on_pre_save(state_manager_t &manager) = 0; virtual void on_post_load(state_manager_t &manager) = 0; protected: callback_t() = default; virtual ~callback_t() = default; COPYASSIGNMOVE(callback_t, default) }; struct entry_t { using list_t = std::vector; entry_t(const pstring &stname, const datatype_t &dt, const void *owner, const std::size_t count, void *ptr) : m_name(stname), m_dt(dt), m_owner(owner), m_callback(nullptr), m_count(count), m_ptr(ptr) { } entry_t(const pstring &stname, const void *owner, callback_t *callback) : m_name(stname), m_dt(datatype_t(true)), m_owner(owner), m_callback(callback), m_count(0), m_ptr(nullptr) { } pstring name() const noexcept { return m_name; } datatype_t dt() const noexcept { return m_dt; } const void * owner() const noexcept { return m_owner; } callback_t * callback() const noexcept { return m_callback; } std::size_t count() const noexcept { return m_count; } void * ptr() const noexcept { return m_ptr; } private: pstring m_name; datatype_t m_dt; const void * m_owner; callback_t * m_callback; std::size_t m_count; void * m_ptr; }; state_manager_t() = default; template //, typename std::enable_if::value || std::is_floating_point::value>::type> void save_item(const void *owner, C &state, const pstring &stname) { save_state_ptr( owner, stname, dtype(), 1, &state); } template void save_item(const void *owner, C (&state)[N], const pstring &stname) // NOLINT(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays) { save_state_ptr(owner, stname, dtype(), N, &(state[0])); } template void save_item(const void *owner, C *state, const pstring &stname, const std::size_t count) { save_state_ptr(owner, stname, dtype(), count, state); } template void save_item(const void *owner, std::vector &v, const pstring &stname) { save_state_ptr(owner, stname, dtype(), v.size(), v.data()); } template void save_item(const void *owner, std::array &a, const pstring &stname) { save_state_ptr(owner, stname, dtype(), N, a.data()); } void save_state_ptr(const void *owner, const pstring &stname, const datatype_t &dt, const std::size_t count, void *ptr) { m_save.emplace_back(stname, dt, owner, count, ptr); } void pre_save() { for (auto & s : m_custom) s.callback()->on_pre_save(*this); } void post_load() { for (auto & s : m_custom) s.callback()->on_post_load(*this); } void remove_save_items(const void *owner) { auto i = m_save.end(); while (i != m_save.begin()) { i--; if (i->owner() == owner) i = m_save.erase(i); } i = m_custom.end(); while (i > m_custom.begin()) { i--; if (i->owner() == owner) i = m_custom.erase(i); } } const std::vector save_list() const { std::vector ret; for (auto &i : m_save) ret.push_back(&i); return ret; } protected: private: entry_t::list_t m_save; entry_t::list_t m_custom; }; template<> inline void state_manager_t::save_item(const void *owner, callback_t &state, const pstring &stname) { m_custom.emplace_back(stname, owner, &state); state.register_state(*this, stname); } } // namespace plib #endif // PSTATE_H_