RetroLinker
Linker for several 8-bit, 16-bit and 32-bit formats
Loading...
Searching...
No Matches
reader.h
1#ifndef READER_H
2#define READER_H
3
4#include <cstring>
5#include <iostream>
6#include <memory>
7#include <string>
8#include <vector>
9#include "../common.h"
10
11namespace Linker
12{
14 {
15 };
16
20 class Reader : public std::enable_shared_from_this<Reader>
21 {
22 public:
26 EndianType endiantype;
27
55
60 {
62 Default,
64 Force,
66 Report,
67 };
70
71 inline OverflowHandlingMode GetActionOnOverflow()
72 {
74 {
76 default:
77 return on_overflow;
79 return IgnoreOnOverflow;
82 }
83 }
84
85 Reader(EndianType endiantype)
87 {
88 }
89
90 std::shared_ptr<Reader> CreateWindow(offset_t new_start_offset, offset_t new_maximum_size = offset_t(-1), offset_t displacement = 0);
91
92 virtual ~Reader() = default;
93
97 virtual size_t Read(void * data, size_t max_count = size_t(-1)) = 0;
98
102 void ReadData(size_t count, void * data);
103
107 void ReadData(size_t count, std::vector<uint8_t>& data, size_t offset = 0);
108
112 void ReadData(std::vector<uint8_t>& data, size_t offset = 0);
113
117 std::string ReadData(size_t count, bool terminate_at_null = false);
118
122 std::string ReadUTF16Data(size_t count, bool terminate_at_null = false);
123
127 template <class T, std::size_t N>
128 void ReadData(std::array<T, N>& data, size_t offset = 0)
129 {
130 if(offset >= N)
131 return;
132 ReadData(N - offset, reinterpret_cast<char *>(data.data()) + offset);
133 }
134
138 std::string ReadASCII(char terminator, size_t maximum = size_t(-1));
139
143 std::string ReadASCIIZ(size_t maximum = size_t(-1));
144
148 std::string ReadUTF16Data(const char terminator[2], size_t maximum = size_t(-1));
149
153 std::string ReadUTF16Data(char16_t terminator, size_t maximum, EndianType endiantype);
154
158 std::string ReadUTF16Data(char16_t terminator, size_t maximum = size_t(-1));
159
163 std::string ReadUTF16Data(char16_t terminator, EndianType endiantype);
164
168 std::string ReadUTF16ZData(size_t maximum = size_t(-1));
169
173 uint64_t ReadUnsigned(size_t bytes, EndianType endiantype);
174
178 uint64_t ReadUnsigned(size_t bytes);
179
183 uint64_t ReadSigned(size_t bytes, EndianType endiantype);
184
188 uint64_t ReadSigned(size_t bytes);
189
193 template <typename Clock>
194 Timestamp<Clock> ReadTimestamp(EndianType endiantype)
195 {
196 if constexpr(std::is_signed_v<typename Clock::rep>)
197 return Clock::to_time_point(ReadSigned(sizeof(typename Clock::rep), endiantype));
198 else
199 return Clock::to_time_point(ReadUnsigned(sizeof(typename Clock::rep), endiantype));
200 }
201
205 template <typename Clock>
206 Timestamp<Clock> ReadTimestamp()
207 {
208 if constexpr(std::is_signed_v<typename Clock::rep>)
209 return Clock::to_time_point(ReadSigned(sizeof(typename Clock::rep)));
210 else
211 return Clock::to_time_point(ReadUnsigned(sizeof(typename Clock::rep)));
212 }
213
217 virtual void Seek(offset_t offset) = 0;
218
222 virtual void Skip(relative_offset_t offset) = 0;
223
227 virtual void SeekEnd(relative_offset_t offset = 0) = 0;
228
232 virtual offset_t Tell() = 0;
233
237 virtual offset_t GetImageEnd();
238
242 offset_t GetRemainingCount();
243 };
244
248 class StreamReader : public Reader
249 {
250 public:
254 std::istream * in;
255
256 StreamReader(EndianType endiantype, std::istream * in = nullptr)
258 {
259 }
260
261 StreamReader(EndianType endiantype, std::istream& in)
262 : Reader(endiantype), in(&in)
263 {
264 }
265
266 size_t Read(void * data, size_t max_count = size_t(-1)) override;
267 void Seek(offset_t offset) override;
268 void Skip(relative_offset_t offset) override;
269 void SeekEnd(relative_offset_t offset = 0) override;
270 offset_t Tell() override;
271 };
272
276 class WindowReader : public Reader
277 {
278 public:
279 std::shared_ptr<Reader> reader;
280
282 offset_t start_offset;
284 offset_t maximum_size;
287
288 // The WindowReader offsets [window_offset, window_offset + maximum_size) is mapped to [start_offset, start_offset + maximum_size)
289 // everything outside the window is treated as out of bounds
290
291 protected:
292 void _ValidateParameters()
293 {
294 if(maximum_size != offset_t(-1))
295 {
296 assert(start_offset <= offset_t(-1) - maximum_size);
297 assert(window_offset <= offset_t(-1) - maximum_size);
298 }
299 }
300
302 void _ShiftStartOffset(offset_t addend)
303 {
304 if(window_offset > addend)
305 {
306 window_offset -= addend;
307 }
308 else
309 {
310 if(maximum_size != offset_t(-1) && maximum_size <= addend - window_offset)
311 {
312 maximum_size = 0;
313 }
314 else
315 {
316 maximum_size -= addend - window_offset;
317 start_offset += addend - window_offset; // TODO: overflow
318 }
319 window_offset = 0;
320 }
321
322 _ValidateParameters();
323 }
324
326 void _RestrictMaximumSize(offset_t new_maximum)
327 {
328 if(new_maximum < maximum_size)
329 {
330 maximum_size = new_maximum;
331 _ValidateParameters();
332 }
333 }
334
336 void _AddDisplacement(offset_t displacement)
337 {
338 window_offset += displacement; // TODO: overflow
339 _ValidateParameters();
340 }
341
342 static std::shared_ptr<Reader> _GetReader(std::shared_ptr<Reader> reader)
343 {
344 if(auto window_reader = std::dynamic_pointer_cast<WindowReader>(reader))
345 {
346 return window_reader->reader;
347 }
348 else
349 {
350 return reader;
351 }
352 }
353
354 static offset_t _GetStartOffset(std::shared_ptr<Reader> reader)
355 {
356 if(auto window_reader = std::dynamic_pointer_cast<WindowReader>(reader))
357 {
358 return window_reader->start_offset;
359 }
360 else
361 {
362 return 0;
363 }
364 }
365
366 static offset_t _GetMaximumSize(std::shared_ptr<Reader> reader)
367 {
368 if(auto window_reader = std::dynamic_pointer_cast<WindowReader>(reader))
369 {
370 return window_reader->maximum_size;
371 }
372 else
373 {
374 return offset_t(-1);
375 }
376 }
377
378 static offset_t _GetWindowOffset(std::shared_ptr<Reader> reader)
379 {
380 if(auto window_reader = std::dynamic_pointer_cast<WindowReader>(reader))
381 {
382 return window_reader->window_offset;
383 }
384 else
385 {
386 return 0;
387 }
388 }
389
390 public:
391 WindowReader(EndianType endiantype, std::shared_ptr<Reader> reader, offset_t start_offset, offset_t maximum_size, offset_t displacement = 0)
392 : Reader(endiantype), reader(_GetReader(reader)), start_offset(_GetStartOffset(reader)), maximum_size(_GetMaximumSize(reader)), window_offset(_GetWindowOffset(reader))
393 {
396 _AddDisplacement(displacement);
397 }
398
399 WindowReader(std::shared_ptr<Reader> reader, offset_t start_offset, offset_t maximum_size, offset_t displacement = 0)
400 : Reader(reader->endiantype), reader(_GetReader(reader)), start_offset(_GetStartOffset(reader)), maximum_size(_GetMaximumSize(reader)), window_offset(_GetWindowOffset(reader))
401 {
404 _AddDisplacement(displacement);
405 }
406
407 size_t Read(void * data, size_t max_count = size_t(-1)) override;
408 void Seek(offset_t offset) override;
409 void Skip(relative_offset_t offset) override;
410 void SeekEnd(relative_offset_t offset = 0) override;
411 offset_t Tell() override;
412
413 offset_t GetImageEnd() override;
414 };
415
416 class Image;
417
418 // TODO: untested
422 class ImageReader : public Reader
423 {
424 public:
425 std::shared_ptr<Image> image;
426 offset_t position = 0;
427
428 ImageReader(EndianType endiantype, std::shared_ptr<Image> image)
429 : Reader(endiantype), image(image)
430 {
431 }
432
433 size_t Read(void * data, size_t max_count = size_t(-1)) override;
434 void Seek(offset_t offset) override;
435 void Skip(relative_offset_t offset) override;
436 void SeekEnd(relative_offset_t offset = 0) override;
437 offset_t Tell() override;
438
439 offset_t GetImageEnd() override;
440 };
441}
442
443#endif /* READER_H */
Reader subclass that reads data from an internally stored image.
Definition reader.h:423
offset_t GetImageEnd() override
Returns the last location that can be read.
Definition reader.cc:367
offset_t Tell() override
Retrieve the current location.
Definition reader.cc:362
void Skip(relative_offset_t offset) override
Jump to a distance in the input stream.
Definition reader.cc:347
void Seek(offset_t offset) override
Jump to a specific location in the input stream.
Definition reader.cc:342
void SeekEnd(relative_offset_t offset=0) override
Jump to end of the input stream.
Definition reader.cc:352
size_t Read(void *data, size_t max_count=size_t(-1)) override
Read in as many bytes as possible.
Definition reader.cc:335
Definition reader.h:14
Abstract base class that encapsulates functionality needed to import binary data.
Definition reader.h:21
Timestamp< Clock > ReadTimestamp(EndianType endiantype)
Read a date-time value according to some epoch.
Definition reader.h:194
OverflowHandlingRequest
Describes how the user expects the parser to behave on read overflow.
Definition reader.h:60
@ Report
Terminate program as soon as boundary overflow happens, even if overflow is harmless.
@ Default
Let the parser routine decide.
@ Force
Ignore all boundary overflows and keep reading.
OverflowHandlingMode
Describes how ReadData and all other reading routines should behave when reading exceeds limits (end ...
Definition reader.h:32
@ IgnoreOnOverflow
Display error message, continue parsing.
Definition reader.h:38
@ TerminateOnOverflow
Execution immediately stops.
Definition reader.h:51
@ ReportOnOverflow
Throw a ReadOverflow exception.
Definition reader.h:44
std::string ReadASCIIZ(size_t maximum=size_t(-1))
Read a zero terminated ASCII string.
Definition reader.cc:81
std::string ReadASCII(char terminator, size_t maximum=size_t(-1))
Read an ASCII string up to a terminator.
Definition reader.cc:66
Timestamp< Clock > ReadTimestamp()
Read a date-time value according to some epoch.
Definition reader.h:206
virtual offset_t GetImageEnd()
Returns the last location that can be read.
Definition reader.cc:167
std::string ReadUTF16Data(size_t count, bool terminate_at_null=false)
Read in a sequence of 16-bit words.
Definition reader.cc:86
uint64_t ReadSigned(size_t bytes, EndianType endiantype)
Read a signed word.
Definition reader.cc:155
EndianType endiantype
The default endianness of the binary format, used for reading multibyte numeric data.
Definition reader.h:26
OverflowHandlingMode on_overflow
Intended behavior of reading routines on read overflow.
Definition reader.h:54
virtual void Seek(offset_t offset)=0
Jump to a specific location in the input stream.
virtual void Skip(relative_offset_t offset)=0
Jump to a distance in the input stream.
std::string ReadUTF16ZData(size_t maximum=size_t(-1))
Read a zero terminated string of 16-bit words.
Definition reader.cc:137
virtual size_t Read(void *data, size_t max_count=size_t(-1))=0
Read in as many bytes as possible.
virtual void SeekEnd(relative_offset_t offset=0)=0
Jump to end of the input stream.
void ReadData(size_t count, void *data)
Read in a sequence of bytes.
Definition reader.cc:22
static OverflowHandlingRequest global_overflow_behavior
Global flag to control how reading overflow should be handled.
Definition reader.h:69
virtual offset_t Tell()=0
Retrieve the current location.
offset_t GetRemainingCount()
Returns the byte count until the last location that can be read.
Definition reader.cc:176
void ReadData(std::array< T, N > &data, size_t offset=0)
Read in a sequence of bytes.
Definition reader.h:128
uint64_t ReadUnsigned(size_t bytes, EndianType endiantype)
Read an unsigned word.
Definition reader.cc:143
Reader subclass whose source is a C++ input stream.
Definition reader.h:249
void SeekEnd(relative_offset_t offset=0) override
Jump to end of the input stream.
Definition reader.cc:201
void Seek(offset_t offset) override
Jump to a specific location in the input stream.
Definition reader.cc:187
offset_t Tell() override
Retrieve the current location.
Definition reader.cc:208
size_t Read(void *data, size_t max_count=size_t(-1)) override
Read in as many bytes as possible.
Definition reader.cc:181
std::istream * in
The input stream.
Definition reader.h:254
void Skip(relative_offset_t offset) override
Jump to a distance in the input stream.
Definition reader.cc:194
Reader subclass that restricts access of another Reader to fixed window.
Definition reader.h:277
offset_t GetImageEnd() override
Returns the last location that can be read.
Definition reader.cc:319
void Seek(offset_t offset) override
Jump to a specific location in the input stream.
Definition reader.cc:232
offset_t maximum_size
The maximum number of bytes in the base reader that are accessible, offset_t(-1) is reserved to mean ...
Definition reader.h:284
void _ShiftStartOffset(offset_t addend)
Decrease the window by shifting its lower bound by addend.
Definition reader.h:302
void _RestrictMaximumSize(offset_t new_maximum)
Decrease the window by decrementing its upper bound.
Definition reader.h:326
void SeekEnd(relative_offset_t offset=0) override
Jump to end of the input stream.
Definition reader.cc:284
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 reader.h:336
offset_t start_offset
The first offset in the base reader that is accessible, 0 meaning all.
Definition reader.h:282
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 reader.h:286
offset_t Tell() override
Retrieve the current location.
Definition reader.cc:305
size_t Read(void *data, size_t max_count=size_t(-1)) override
Read in as many bytes as possible.
Definition reader.cc:213
void Skip(relative_offset_t offset) override
Jump to a distance in the input stream.
Definition reader.cc:251