mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-17 19:13:55 +00:00
99 lines
2.7 KiB
C++
99 lines
2.7 KiB
C++
#pragma once
|
|
|
|
namespace utils
|
|
{
|
|
template <typename Traits>
|
|
class aligned_binary_writer;
|
|
|
|
template <typename T, typename Traits>
|
|
concept Writable = requires(const T ac, aligned_binary_writer<Traits>& writer) {
|
|
{ ac.write(writer) } -> std::same_as<void>;
|
|
};
|
|
|
|
template <typename Traits>
|
|
class aligned_binary_writer
|
|
{
|
|
public:
|
|
aligned_binary_writer(memory_interface& mem, uint64_t address)
|
|
: memory(mem),
|
|
base_address(address),
|
|
current_position(address)
|
|
{
|
|
}
|
|
|
|
void write(const void* data, size_t size, size_t alignment = 1)
|
|
{
|
|
align_to(alignment);
|
|
memory.write_memory(current_position, data, size);
|
|
current_position += size;
|
|
}
|
|
|
|
template <typename T>
|
|
requires(!is_optional<T>::value)
|
|
void write(const T& value)
|
|
{
|
|
constexpr auto is_trivially_copyable = std::is_trivially_copyable_v<T>;
|
|
|
|
if constexpr (Writable<T, Traits>)
|
|
{
|
|
value.write(*this);
|
|
}
|
|
else if constexpr (is_trivially_copyable)
|
|
{
|
|
write(&value, sizeof(T), alignof(T));
|
|
}
|
|
else
|
|
{
|
|
static_assert(std::is_trivially_copyable_v<T>, "Type must be trivially copyable or be writable!");
|
|
std::abort();
|
|
}
|
|
}
|
|
|
|
void write_ndr_pointer(bool not_null)
|
|
{
|
|
write<typename Traits::PVOID>(not_null ? 0x20000 : 0);
|
|
}
|
|
|
|
void write_ndr_u16string(const std::u16string& str)
|
|
{
|
|
size_t char_count = str.size() + 1;
|
|
size_t byte_length = char_count * sizeof(char16_t);
|
|
|
|
write<typename Traits::SIZE_T>(char_count);
|
|
write<typename Traits::SIZE_T>(0);
|
|
write<typename Traits::SIZE_T>(char_count);
|
|
write(str.c_str(), byte_length);
|
|
}
|
|
|
|
void pad(size_t count)
|
|
{
|
|
std::vector<uint8_t> padding(count, 0);
|
|
write(padding.data(), count);
|
|
}
|
|
|
|
void align_to(size_t alignment)
|
|
{
|
|
size_t offset_val = static_cast<size_t>(current_position) % alignment;
|
|
if (offset_val != 0)
|
|
{
|
|
pad(alignment - offset_val);
|
|
}
|
|
}
|
|
|
|
uint64_t position() const
|
|
{
|
|
return current_position;
|
|
}
|
|
|
|
uint64_t offset() const
|
|
{
|
|
return current_position - base_address;
|
|
}
|
|
|
|
private:
|
|
memory_interface& memory; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members)
|
|
uint64_t base_address;
|
|
uint64_t current_position;
|
|
};
|
|
}
|