forked from tracktwo/xcomsave
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathxcomio.h
172 lines (132 loc) · 5.3 KB
/
xcomio.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
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
/*
XCom EW Saved Game Reader
Copyright(C) 2015
This program is free software; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301 USA.
*/
#ifndef XCOMREADER_H
#define XCOMREADER_H
#include <stdint.h>
#include <string>
#include "xcom.h"
#include "util.h"
namespace xcom
{
// A low-level i/o class for managing an xcom save. Provides basic
// read and write functionality of primitive types (ints, strings,
// bools, byte arrays, etc.).
class xcom_io
{
public:
static const constexpr int32_t initial_size = 1024 * 1024;
// Construct an xcom_io object from an existing buffer (e.g.
// a raw save file).
xcom_io(buffer<unsigned char>&& b) :
start_(std::move(b.buf)), length_(b.length)
{
ptr_ = start_.get();
}
// Construct an empty xcom_io object, e.g. for writing a save.
xcom_io()
{
start_ = std::make_unique<unsigned char[]>(initial_size);
ptr_ = start_.get();
length_ = initial_size;
}
public:
// Return the current offset of the cursor within the buffer.
std::ptrdiff_t offset() const {
return ptr_ - start_.get();
}
// Return the current size of the buffer.
size_t size() const {
return length_;
}
// Return a pointer to the current byte at the cursor.
const unsigned char * pointer() const {
return ptr_;
}
// Are we at the end of the file?
bool eof() const
{
return static_cast<size_t>(offset()) >= length_;
}
// Extract the raw buffer from the io object. After this the
// io object is empty (length 0 and holds no pointer).
buffer<unsigned char> release() {
buffer<unsigned char> b = { std::move(start_), length_ };
start_.reset();
ptr_ = nullptr;
length_ = 0;
return b;
}
enum class seek_kind {
start,
current,
end
};
// Check at least 'count' bytes remain in buffer.
bool bounds_check(size_t count) const;
// Seek to a position within the buffer based on the seek_kind
void seek(seek_kind k, std::ptrdiff_t offset);
// Compute a crc over the next length bytes from the cursor.
uint32_t crc(size_t length);
// Read a 32-bit signed integer
int32_t read_int();
// Read a single-precision float
float read_float();
// Read a string. Returned string is converted to UTF-8. The
// string is expected to be a Latin-1 string in the save file.
std::string read_string();
// Read a (possibly) unicode string from the save file. Returned
// string is in UTF-8, but has a corresponding flag indicating
// whether or not the string must be written to the save as a
// UTF-16 string.
xcom_string read_unicode_string(bool throw_on_error = true);
// Read a boolean value. Note bools take up 4 bytes in xcom saves.
bool read_bool();
// Read a single byte
unsigned char read_byte();
// Read count bytes from the save
std::unique_ptr<unsigned char[]> read_raw_bytes(int32_t count);
// Read count bytes from the save and store them in the buffer pointed
// to by outp.
void read_raw_bytes(int32_t count, unsigned char *outp);
// Ensure enough space exists in the internal buffer to hold count bytes.
void ensure(size_t count);
// Write a string. Str is expected to be in UTF-8 format but will be converted
// to Latin-1 on write.
void write_string(const std::string& str);
// Write a (possibly) unicode string. If the provided string is wide the string
// will be converted to UTF-16 before writing, otherwise it will be converted to Latin-1.
void write_unicode_string(const xcom_string &str);
// Write an integer
void write_int(int32_t val);
int16_t read_int16();
// Write a single-precision float
void write_float(float val);
// Write a boolean value
void write_bool(bool b);
// Write a single byte
void write_byte(unsigned char c);
// Write len bytes pointed to by buf
void write_raw(unsigned char *buf, int32_t len);
protected:
// The buffer itself, always points to the start of the owned memory.
std::unique_ptr<unsigned char[]> start_;
// The current cursor into the buffer.
unsigned char *ptr_;
// The number of bytes in the buffer pointed to by start_
size_t length_;
};
} // namespace xcom
#endif //XCOM_H