#pragma once namespace memory { class byte_patch { public: virtual ~byte_patch() { memcpy(m_address, m_original_bytes.data(), m_original_bytes.size()); } /// /// To guarantee proper restoration of bytes all shared_ptr instances will be invalidated that point to this object. /// void restore() const { if (const auto it = std::find(m_patches.begin(), m_patches.end(), this); it != m_patches.end()) { it->reset(); m_patches.erase(it); } } template static std::shared_ptr make(TAddr address, std::remove_pointer_t> value) { auto patch = std::shared_ptr(new byte_patch(address, value)); m_patches.emplace_back(patch); return patch; } static void restore_all() { for (const auto& patch : m_patches) { patch->restore(); } } private: template byte_patch(TAddr address, std::remove_pointer_t> value) : m_address(address) { constexpr auto size = sizeof(std::remove_pointer_t>); m_original_bytes.resize(size); memcpy(m_original_bytes.data(), m_address, size); *address = value; } protected: static inline std::vector> m_patches; private: void* m_address; std::vector m_original_bytes; friend bool operator== (const std::shared_ptr a, const byte_patch* b); }; bool operator== (const std::shared_ptr a, const byte_patch* b) { return a->m_address == b->m_address; } }