-
Notifications
You must be signed in to change notification settings - Fork 2
/
reader.hpp
198 lines (141 loc) · 5.01 KB
/
reader.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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#pragma once
#include <istream>
#include "interface.hpp"
#include "substring.hpp"
namespace reflect {
class reader : interface {
struct null_reader;
public:
static reader* const null;
virtual explicit operator bool() const = 0;
virtual size_t offset() const = 0;
std::string peek(size_t offset, size_t) const;
void peek(std::vector<char>&, size_t offset, size_t) const;
virtual char peek() const = 0;
virtual char read() = 0;
virtual void seek(size_t offset) = 0;
virtual size_t size() const = 0;
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
inline std::string
reader::peek(size_t offset, size_t size) const {
std::string s;
reader& r = *const_cast<reader*>(this);
const auto start = this->offset();
r.seek(offset);
s.assign(size+1,0);
char* itr = s.data();
const char* const end = itr + size;
for (;itr < end; *itr++=r.read());
reflect_assert(s.back()=='\0');
s.resize(size);
r.seek(start);
reflect_assert(r.offset()==start);
return s;
}
inline void
reader::peek(std::vector<char>& v, size_t offset, size_t size) const {
reader& r = *const_cast<reader*>(this);
const auto start = this->offset();
r.seek(offset);
v.clear();
v.resize(size+1,0);
char* itr = v.data();
const char* const end = itr + size;
for (;itr < end; *itr++=r.read());
reflect_assert(v.back()=='\0');
v.resize(size);
r.seek(start);
reflect_assert(r.offset()==start);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
struct reader::null_reader final : reader {
static reader* instance() {
static null_reader _instance;
return &_instance;
}
explicit operator bool() const override { return false; }
size_t offset() const override { return 0; }
char peek() const override { return 0; }
char read() override { return 0; }
void seek(size_t offset) override {}
size_t size() const override { return 0; }
};
inline reader* const reader::null = reader::null_reader::instance();
//--------------------------------------------------------------------------
class stream_reader final : public reader {
using pos_type = std::istream::pos_type;
using off_type = std::istream::off_type;
std::istream* const _stream = nullptr;
const pos_type _head;
public: // structors
stream_reader() = default;
stream_reader(std::istream& stream)
:_stream(&stream)
,_head(stream.tellg()) {}
public: // overrides
explicit operator bool() const override {
return _stream and _stream->good();
}
size_t offset() const override {
return operator bool() ? size_t(_stream->tellg()-_head) : 0;
}
char peek() const override {
return operator bool() ? _stream->peek() : 0;
}
char read() override {
return operator bool() ? _stream->get() : 0;
}
void seek(size_t offset) override {
if (operator bool()) _stream->seekg(_head + off_type(offset));
}
size_t size() const override {
if (operator bool()) {
const auto start = _stream->tellg();
_stream->seekg(0,std::ios::end);
const auto end = _stream->tellg();
_stream->seekg(start);
return end - _head;
}
return 0;
}
};
//--------------------------------------------------------------------------
class string_reader final : public reader {
substring _string;
const char* _itr = nullptr;
public: // structors
string_reader() = default;
string_reader(substring s)
:_string(s)
,_itr(_string.begin()) {}
template<size_t SIZE>
string_reader(const char (&s)[SIZE])
:string_reader(substring(s)) {}
string_reader(const char* s)
:string_reader(substring(s)) {}
string_reader(const std::string& s)
:string_reader(substring(s)) {}
public: // overrides
explicit operator bool() const override {
return _itr < _string.end();
}
size_t offset() const override {
return size_t(_itr) - size_t(_string.begin());
}
char peek() const override {
return operator bool() ? *_itr : 0;
}
char read() override {
const char c = peek();
_itr = std::min(_itr+1,_string.end());
return c;
}
void seek(size_t offset) override {
_itr = std::min(_string.begin()+offset,_string.end());
}
size_t size() const override {
return _string.size();
}
};
} // namespace reflect