RetroLinker
Linker for several 8-bit, 16-bit and 32-bit formats
Loading...
Searching...
No Matches
writer.h
1#ifndef WRITER_H
2#define WRITER_H
3
4#include <iostream>
5#include <string>
6#include <vector>
7#include "../common.h"
8
9namespace Linker
10{
14 class Writer
15 {
16 public:
20 EndianType endiantype;
21
22 Writer(EndianType endiantype)
24 {
25 }
26
27 virtual ~Writer() = default;
28
32 virtual void WriteData(size_t count, const void * data) = 0;
33
37 size_t WriteData(size_t max_count, const std::vector<uint8_t>& data, size_t offset = 0);
38
42 size_t WriteData(const std::vector<uint8_t>& data, size_t offset = 0);
43
47 template <class T, std::size_t N>
48 void WriteData(const std::array<T, N>& data, size_t offset = 0)
49 {
50 if(offset >= N)
51 return;
52 WriteData(N - offset, reinterpret_cast<const char *>(data.data()) + offset);
53 }
54
58 void WriteData(size_t count, std::string text, char padding = '\0');
59
63 void WriteData(std::string text);
64
68 void WriteData(size_t count, std::istream& in);
69
73 void WriteWord(size_t bytes, uint64_t value, EndianType endiantype);
74
78 void WriteWord(size_t bytes, uint64_t value);
79
83 template <typename Clock>
84 void WriteTimestamp(Timestamp<Clock> timestamp, EndianType endiantype)
85 {
86 WriteWord(sizeof(typename Clock::rep), Clock::to_ticks(timestamp), endiantype);
87 }
88
92 template <typename Clock>
93 void WriteTimestamp(Timestamp<Clock> timestamp)
94 {
95 WriteWord(sizeof(typename Clock::rep), Clock::to_ticks(timestamp));
96 }
97
101 virtual void Seek(offset_t offset) = 0;
102
106 virtual void Skip(relative_offset_t offset) = 0;
107
111 virtual void SeekEnd(relative_offset_t offset = 0) = 0;
112
116 virtual offset_t Tell() = 0;
117
121 void FillTo(offset_t position);
122
126 void AlignTo(offset_t align);
127 };
128
132 class StreamWriter : public Writer
133 {
134 public:
138 std::ostream * out;
139
140 StreamWriter(EndianType endiantype, std::ostream * out = nullptr)
142 {
143 }
144
145 StreamWriter(EndianType endiantype, std::ostream& out)
147 {
148 }
149
150 protected:
151 void _FillNulls(size_t count);
152
153 public:
154 void WriteData(size_t count, const void * data) override;
155 void Seek(offset_t offset) override;
156 void Skip(relative_offset_t offset) override;
157 void SeekEnd(relative_offset_t offset = 0) override;
158 offset_t Tell() override;
159 };
160
164 class WindowWriter : public Writer
165 {
166 public:
167 std::shared_ptr<Writer> writer;
168
170 offset_t start_offset;
172 offset_t maximum_size;
175
176 // The WindowWriter offsets [window_offset, window_offset + maximum_size) is mapped to [start_offset, start_offset + maximum_size)
177 // everything outside the window is treated as out of bounds
178
179 protected:
180 void _ValidateParameters()
181 {
182 if(maximum_size != offset_t(-1))
183 {
184 assert(start_offset <= offset_t(-1) - maximum_size);
185 assert(window_offset <= offset_t(-1) - maximum_size);
186 }
187 }
188
190 void _ShiftStartOffset(offset_t addend)
191 {
192 if(window_offset > addend)
193 {
194 window_offset -= addend;
195 }
196 else
197 {
198 if(maximum_size != offset_t(-1) && maximum_size <= addend - window_offset)
199 {
200 maximum_size = 0;
201 }
202 else
203 {
204 maximum_size -= addend - window_offset;
205 start_offset += addend - window_offset; // TODO: overflow
206 }
207 window_offset = 0;
208 }
209
210 _ValidateParameters();
211 }
212
214 void _RestrictMaximumSize(offset_t new_maximum)
215 {
216 if(new_maximum < maximum_size)
217 {
218 maximum_size = new_maximum;
219 _ValidateParameters();
220 }
221 }
222
224 void _AddDisplacement(offset_t displacement)
225 {
226 window_offset += displacement; // TODO: overflow
227 _ValidateParameters();
228 }
229
230 static std::shared_ptr<Writer> _GetWriter(std::shared_ptr<Writer> writer)
231 {
232 if(auto window_writer = std::dynamic_pointer_cast<WindowWriter>(writer))
233 {
234 return window_writer->writer;
235 }
236 else
237 {
238 return writer;
239 }
240 }
241
242 static offset_t _GetStartOffset(std::shared_ptr<Writer> writer)
243 {
244 if(auto window_writer = std::dynamic_pointer_cast<WindowWriter>(writer))
245 {
246 return window_writer->start_offset;
247 }
248 else
249 {
250 return 0;
251 }
252 }
253
254 static offset_t _GetMaximumSize(std::shared_ptr<Writer> writer)
255 {
256 if(auto window_writer = std::dynamic_pointer_cast<WindowWriter>(writer))
257 {
258 return window_writer->maximum_size;
259 }
260 else
261 {
262 return offset_t(-1);
263 }
264 }
265
266 static offset_t _GetWindowOffset(std::shared_ptr<Writer> writer)
267 {
268 if(auto window_writer = std::dynamic_pointer_cast<WindowWriter>(writer))
269 {
270 return window_writer->window_offset;
271 }
272 else
273 {
274 return 0;
275 }
276 }
277
278 public:
279 WindowWriter(std::shared_ptr<Writer> writer, offset_t start_offset, offset_t maximum_size, offset_t displacement = 0)
280 : Writer(writer->endiantype), writer(_GetWriter(writer)), start_offset(_GetStartOffset(writer)), maximum_size(_GetMaximumSize(writer)), window_offset(_GetWindowOffset(writer))
281 {
284 _AddDisplacement(displacement);
285 }
286
287 void WriteData(size_t count, const void * data) override;
288 void Seek(offset_t offset) override;
289 void Skip(relative_offset_t offset) override;
290 void SeekEnd(relative_offset_t offset = 0) override;
291 offset_t Tell() override;
292 };
293
294 class Buffer;
295
296 // TODO: untested
300 class BufferWriter : public Writer
301 {
302 public:
303 std::shared_ptr<Linker::Buffer> buffer;
304 offset_t position = 0;
305
306 // TODO: allocate buffer if parameter not provided
307
308 BufferWriter(EndianType endiantype, std::shared_ptr<Linker::Buffer> buffer)
309 : Writer(endiantype), buffer(buffer)
310 {
311 }
312
313 void WriteData(size_t count, const void * data) override;
314 void Seek(offset_t offset) override;
315 void Skip(relative_offset_t offset) override;
316 void SeekEnd(relative_offset_t offset = 0) override;
317 offset_t Tell() override;
318 };
319}
320
321#endif /* WRITER_H */
Writer subclass that stores data into an internal buffer.
Definition writer.h:301
void WriteData(size_t count, const void *data) override
Write out a sequence of bytes.
Definition writer.cc:254
void SeekEnd(relative_offset_t offset=0) override
Jump to a specific offset from the end.
Definition writer.cc:274
void Skip(relative_offset_t offset) override
Jump to a distance in the output stream.
Definition writer.cc:269
void Seek(offset_t offset) override
Jump to a specific location in the ouput stream.
Definition writer.cc:260
offset_t Tell() override
Retrieve the current location.
Definition writer.cc:279
Writer subclass whose target is a C++ output stream.
Definition writer.h:133
offset_t Tell() override
Retrieve the current location.
Definition writer.cc:143
void WriteData(size_t count, const void *data) override
Write out a sequence of bytes.
Definition writer.cc:107
void Skip(relative_offset_t offset) override
Jump to a distance in the output stream.
Definition writer.cc:128
void SeekEnd(relative_offset_t offset=0) override
Jump to a specific offset from the end.
Definition writer.cc:135
std::ostream * out
The output stream.
Definition writer.h:138
void Seek(offset_t offset) override
Jump to a specific location in the ouput stream.
Definition writer.cc:112
Writer subclass that restricts access of another Writer to fixed window.
Definition writer.h:165
void SeekEnd(relative_offset_t offset=0) override
Jump to a specific offset from the end.
Definition writer.cc:219
void _RestrictMaximumSize(offset_t new_maximum)
Decrease the window by decrementing its upper bound.
Definition writer.h:214
void WriteData(size_t count, const void *data) override
Write out a sequence of bytes.
Definition writer.cc:148
offset_t Tell() override
Retrieve the current location.
Definition writer.cc:240
void Seek(offset_t offset) override
Jump to a specific location in the ouput stream.
Definition writer.cc:167
void Skip(relative_offset_t offset) override
Jump to a distance in the output stream.
Definition writer.cc:186
offset_t start_offset
The first offset in the base writer that is accessible, 0 meaning all.
Definition writer.h:170
offset_t window_offset
The lowest address that is allowed to be accessed, the offset at which the byte at start_offset is fo...
Definition writer.h:174
void _AddDisplacement(offset_t displacement)
Shift the address values at which the window is accessed, so the previous offset O is accessed at O +...
Definition writer.h:224
offset_t maximum_size
The maximum number of bytes in the base writer that are accessible, offset_t(-1) is reserved to mean ...
Definition writer.h:172
void _ShiftStartOffset(offset_t addend)
Decrease the window by shifting its lower bound by addend.
Definition writer.h:190
Abstract base class that encapsulates functionality needed to export binary data.
Definition writer.h:15
virtual void Skip(relative_offset_t offset)=0
Jump to a distance in the output stream.
void WriteTimestamp(Timestamp< Clock > timestamp, EndianType endiantype)
Write a date-time value according to some epoch.
Definition writer.h:84
void WriteTimestamp(Timestamp< Clock > timestamp)
Write a date-time value according to some epoch.
Definition writer.h:93
EndianType endiantype
The default endianness of the binary format, used for reading multibyte numeric data.
Definition writer.h:20
virtual offset_t Tell()=0
Retrieve the current location.
void FillTo(offset_t position)
Move to a specific offset, fill with zeroes if needed.
Definition writer.cc:75
virtual void Seek(offset_t offset)=0
Jump to a specific location in the ouput stream.
virtual void WriteData(size_t count, const void *data)=0
Write out a sequence of bytes.
virtual void SeekEnd(relative_offset_t offset=0)=0
Jump to a specific offset from the end.
void AlignTo(offset_t align)
Align the current pointer.
Definition writer.cc:96
void WriteWord(size_t bytes, uint64_t value, EndianType endiantype)
Write a word.
Definition writer.cc:63
void WriteData(const std::array< T, N > &data, size_t offset=0)
Write out a sequence of bytes.
Definition writer.h:48