-
Notifications
You must be signed in to change notification settings - Fork 0
/
BinaryReader.h
94 lines (73 loc) · 2.48 KB
/
BinaryReader.h
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
#ifndef HEADER_1070385A3DA2192D
#define HEADER_1070385A3DA2192D
#pragma once
#include <stdexcept>
#include <vector>
#include <string>
#include <filesystem>
namespace fs = std::filesystem;
class BinaryReader {
public:
std::vector<uint8_t> buffer;
unsigned long long int position = 0;
explicit BinaryReader(std::vector<uint8_t> buffer) : buffer(buffer) {}
template<typename T>
[[nodiscard]] T read() {
// These wouldn't make sense
static_assert(std::is_same<T, std::string>() == false);
static_assert(std::is_same<T, fs::path>() == false);
if (position + sizeof(T) > buffer.size()) {
throw std::out_of_range("Trying to read out of range of buffer");
}
T result = *reinterpret_cast<T*>(&buffer[position]);
position += sizeof(T);
return result;
}
[[nodiscard]] std::string read_string(const size_t size) {
if (position + size > buffer.size()) {
throw std::out_of_range("Trying to read out of range of buffer");
}
std::string result = { reinterpret_cast<char*>(&buffer[position]), static_cast<size_t>(size) };
if (const size_t pos = result.find_first_of('\0', 0); pos != std::string::npos) {
result.resize(pos);
}
position += size;
return result;
}
[[nodiscard]] std::string read_c_string() {
std::string string(reinterpret_cast<char*>(buffer.data() + position));
position += string.size() + 1;
if (position > buffer.size()) {
throw std::out_of_range("Trying to read out of range of buffer");
}
return string;
}
void advance_c_string() {
position += std::string(reinterpret_cast<char*>(buffer.data() + position)).size() + 1;
if (position > buffer.size()) {
throw std::out_of_range("Trying to read out of range of buffer");
}
}
template<typename T>
[[nodiscard]] std::vector<T> read_vector(const size_t size) {
// These wouldn't make sense
static_assert(std::is_same<T, std::string>() == false);
static_assert(std::is_same<T, fs::path>() == false);
if (position + sizeof(T) * size > buffer.size()) {
throw std::out_of_range("Trying to read out of range of buffer");
}
std::vector<T> result(reinterpret_cast<T*>(&buffer[position]), reinterpret_cast<T*>(&buffer[position]) + size);
position += sizeof(T) * size;
return result;
}
[[nodiscard]] long long remaining() const {
return buffer.size() - position;
}
void advance(const size_t amount) {
if (position + amount > buffer.size()) {
throw std::out_of_range("Trying to advance past the end of the buffer");
}
position += amount;
}
};
#endif // header guard