#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;
}
}