-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathbinary_writer.hpp
118 lines (101 loc) · 3.02 KB
/
binary_writer.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#pragma once
#include <cstdint>
#include <memory>
/// Interface to write little-endian bytes.
struct BinaryWriter
{
public:
explicit BinaryWriter()
: offset(0), max_offset(0)
{}
explicit BinaryWriter(size_t size) :
offset(0), max_offset(size), bytecode(new uint8_t[size])
{}
/// \returns the buffer with the generated bytes.
const void* buffer() const
{
return this->bytecode.get();
}
/// \returns the size of the buffer with the generated bytes.
size_t buffer_size() const
{
return this->max_offset;
}
size_t current_offset() const
{
return this->offset;
}
void emplace_u8(uint8_t value)
{
assert(this->offset + 1 <= max_offset);
bytecode[this->offset++] = reinterpret_cast<uint8_t&>(value);
}
void emplace_u16(uint16_t value)
{
//assert(this->offset + 2 <= max_offset);
emplace_u8((value & 0x00FF) >> 0);
emplace_u8((value & 0xFF00) >> 8);
}
void emplace_u32(uint32_t value)
{
//assert(this->offset + 4 <= max_offset);
emplace_u8((value & 0x000000FF) >> 0);
emplace_u8((value & 0x0000FF00) >> 8);
emplace_u8((value & 0x00FF0000) >> 16);
emplace_u8((value & 0xFF000000) >> 24);
}
void emplace_i8(int8_t value)
{
return emplace_u8(reinterpret_cast<uint8_t&>(value));
}
void emplace_i16(int16_t value)
{
return emplace_u16(reinterpret_cast<uint16_t&>(value));
}
void emplace_i32(int32_t value)
{
return emplace_u32(reinterpret_cast<uint32_t&>(value));
}
void emplace_bytes(size_t count, const void* bytes)
{
assert(this->offset + count <= max_offset);
std::memcpy(&this->bytecode[offset], bytes, count);
this->offset += count;
}
void emplace_fill(size_t count, uint8_t val)
{
assert(this->offset + count <= max_offset);
std::memset(&this->bytecode[offset], val, count);
this->offset += count;
}
void emplace_chars(size_t count, const char* data)
{
assert(this->offset + count <= max_offset);
std::strncpy(reinterpret_cast<char*>(&this->bytecode[offset]), data, count);
this->offset += count;
}
void emplace_chars(size_t count, const char* data, bool to_upper)
{
if(to_upper)
return emplace_chars(count, data, toupper_ascii);
else
return emplace_chars(count, data);
}
template<typename FuncT>
void emplace_chars(size_t count, const char* data, FuncT transform)
{
assert(this->offset + count <= max_offset);
for(size_t i = 0; i < count; ++i)
{
if(*data == 0)
this->bytecode[offset+i] = 0;
else
this->bytecode[offset+i] = transform(*data++);
}
this->offset += count;
}
private:
std::unique_ptr<uint8_t[]> bytecode; // size == max_offset
size_t offset;
size_t max_offset;
};