1 #ifndef __GNUC__
2 #pragma once
3 #endif
4 #ifndef __XR_WRITER_H__
5 #define __XR_WRITER_H__
6
7 #include <string>
8 #include <vector>
9 #include <stack>
10 #include <functional>
11 #include "xr_vector2.h"
12 #include "xr_vector3.h"
13 #include "xr_color.h"
14
15 namespace xray_re {
16
17 class xr_packet;
18 class xr_ini_packet;
19
20 class xr_writer {
21 public:
22 xr_writer();
23 virtual ~xr_writer();
24
25 virtual void w_raw(const void* data, size_t size) = 0;
26 virtual void seek(size_t pos) = 0;
27 virtual size_t tell() = 0;
28
29 void open_chunk(uint32_t id);
30 void close_chunk();
31 void w_raw_chunk(uint32_t id, const void* data, size_t size);
32
33 void w_chunk(uint32_t id, const std::string& s);
34
35 template<typename T> void w_chunk(uint32_t id, const T& value);
36 template<typename T, typename F> void w_chunks(const T& container, F write);
37 template<typename T, typename F> void w_seq(const T& container, F write);
38 template<typename T> void w_seq(const T& container);
39 template<typename T> void w_cseq(size_t n, const T values[]);
40 template<typename T, typename F> void w_cseq(size_t n, const T values[], F write);
41 template<typename T> void w(const T& value);
42
43 void w_sz(const std::string& value);
44 void w_sz(const char* value);
45 void w_sf(const char* format, ...);
46 void w_s(const std::string& value);
47 void w_s(const char* value);
48 void w_u32(uint32_t value);
49 void w_s32(int32_t value);
50 void w_u24(uint32_t value);
51 void w_u16(uint16_t value);
52 void w_s16(int16_t value);
53 void w_u8(uint8_t value);
54 void w_s8(int8_t value);
55 void w_bool(bool value);
56 void w_float(float value);
57 void w_float_q16(float value, float min = 0, float max = 1.f);
58 void w_float_q8(float value, float min = 0, float max = 1.f);
59 void w_fvector3(const fvector3& v);
60 void w_fvector2(const fvector2& v);
61 void w_i32vector2(const i32vector2& v);
62 void w_fcolor(const fcolor& c);
63 void w_dir(const fvector3& v);
64 void w_sdir(const fvector3& v);
65 void w_size_u32(size_t value);
66 void w_size_u16(size_t value);
67 void w_size_u8(size_t value);
68
69 void w_packet(const xr_packet& packet);
70
71 template<typename T> struct f_w: public std::binary_function<T, xr_writer, void> {};
72 struct f_w_sz: public f_w<std::string> {
operatorf_w_sz73 void operator()(const std::string& s, xr_writer& w) { w.w_sz(s); }
74 };
75 template<typename T> struct f_w_const: public std::const_mem_fun1_t<void, T, xr_writer&> {
f_w_constf_w_const76 explicit f_w_const(void (T::*_pmf)(xr_writer& w) const): std::const_mem_fun1_t<void, T, xr_writer&>(_pmf) {}
77 };
78
79 private:
80 std::stack<size_t> m_open_chunks;
81
82 char buf[8192];
83 };
84
85 class xr_fake_writer: public xr_writer {
86 public:
87 xr_fake_writer();
88 virtual ~xr_fake_writer();
89 virtual void w_raw(const void* data, size_t size);
90 virtual void seek(size_t pos);
91 virtual size_t tell();
92
93 private:
94 size_t m_pos;
95 size_t m_size;
96 };
97
98 class xr_memory_writer: public xr_writer {
99 public:
100 xr_memory_writer();
101 ~xr_memory_writer();
102
103 virtual void w_raw(const void* data, size_t size);
104 virtual void seek(size_t pos);
105 virtual size_t tell();
106
107 const uint8_t* data() const;
108
109 bool save_to(const char* path);
110 bool save_to(const std::string& path);
111 bool save_to(const char* path, const std::string& name);
112
113 private:
114 std::vector<uint8_t> m_buffer;
115 size_t m_pos;
116 };
117
118 struct xr_guid;
119
120 class xr_ini_writer: public xr_memory_writer {
121 public:
122 xr_ini_writer();
123
124 void open_section(const char *name);
125 void open_section(std::string format, ...);
126 void close_section();
127 void write(const char *key, const char *value, bool enclose = true);
128 void write(const char *key, std::string value, bool enclose = true);
129 //void write(const char *key, std::string& value, bool enclose = true);
130 void write(const char *key, float value);
131 void write(const char *key, int8_t value);
132 void write(const char *key, int16_t value);
133 void write(const char *key, int32_t value);
134 void write(const char *key, int64_t value);
135 void write(const char *key, uint8_t value);
136 void write(const char *key, uint16_t value);
137 void write(const char *key, uint32_t value);
138 void write(const char *key, uint64_t value);
139 void write(const char *key, fvector2 value);
140 void write(const char *key, fvector3 value);
141 void write(const char *key, fcolor value);
142 void write(const char *key, xr_guid *value);
143 template<typename T, typename F> inline void w_sections(const T& container, F write, const char* prefix = "object");
144 template<typename T> inline void w_ini_seq(const T& container, const char* prefix);
145 template<typename T, typename F> inline void w_ini_seq(const T& container, F write, const char* prefix);
146 template<typename T, typename F> inline void w_ini_seq(const T& container, F write);
147
148
149 void write_packet(xr_ini_packet* packet);
150 private:
151 std::stack<std::string> m_section_stack;
152 };
153
xr_writer()154 inline xr_writer::xr_writer() {}
~xr_writer()155 inline xr_writer::~xr_writer() {}
w(const T & value)156 template<typename T> inline void xr_writer::w(const T& value) { w_raw(&value, sizeof(T)); }
w_u32(uint32_t value)157 inline void xr_writer::w_u32(uint32_t value) { w<uint32_t>(value); }
w_s32(int32_t value)158 inline void xr_writer::w_s32(int32_t value) { w<int32_t>(value); }
w_u24(uint32_t value)159 inline void xr_writer::w_u24(uint32_t value) { w_raw(&value, 3); }
w_u16(uint16_t value)160 inline void xr_writer::w_u16(uint16_t value) { w<uint16_t>(value); }
w_s16(int16_t value)161 inline void xr_writer::w_s16(int16_t value) { w<int16_t>(value); }
w_u8(uint8_t value)162 inline void xr_writer::w_u8(uint8_t value) { w<uint8_t>(value); }
w_s8(int8_t value)163 inline void xr_writer::w_s8(int8_t value) { w<int8_t>(value); }
w_bool(bool value)164 inline void xr_writer::w_bool(bool value) { w_u8(value ? 1 : 0); }
w_float(float value)165 inline void xr_writer::w_float(float value) { w<float>(value); }
w_fvector3(const fvector3 & v)166 inline void xr_writer::w_fvector3(const fvector3& v)
167 {
168 w_float(v.x);
169 w_float(v.y);
170 w_float(v.z);
171 }
w_fvector2(const fvector2 & v)172 inline void xr_writer::w_fvector2(const fvector2& v)
173 {
174 w_float(v.x);
175 w_float(v.y);
176 }
w_i32vector2(const i32vector2 & v)177 inline void xr_writer::w_i32vector2(const i32vector2& v)
178 {
179 w_s32(v.x);
180 w_s32(v.y);
181 }
w_fcolor(const fcolor & c)182 inline void xr_writer::w_fcolor(const fcolor&c)
183 {
184 w_float(c.r);
185 w_float(c.g);
186 w_float(c.b);
187 w_float(c.a);
188 }
189
w_size_u32(size_t value)190 inline void xr_writer::w_size_u32(size_t value) { w_u32(static_cast<uint32_t>(value & UINT32_MAX)); }
w_size_u16(size_t value)191 inline void xr_writer::w_size_u16(size_t value) { w_u16(static_cast<uint16_t>(value & UINT16_MAX)); }
w_size_u8(size_t value)192 inline void xr_writer::w_size_u8(size_t value) { w_u8(static_cast<uint8_t>(value & UINT8_MAX)); }
193
w_cseq(size_t n,const T values[])194 template<typename T> inline void xr_writer::w_cseq(size_t n, const T values[])
195 {
196 if (n)
197 w_raw(values, n*sizeof(T));
198 }
199
w_cseq(size_t n,const T values[],F write)200 template<typename T, typename F> inline void xr_writer::w_cseq(size_t n, const T values[], F write)
201 {
202 for (const T *p = values, *end = p + n; p != end; ++p)
203 write(*p, *this);
204 }
205
w_seq(const T & container)206 template<typename T> inline void xr_writer::w_seq(const T& container)
207 {
208 if (!container.empty())
209 w_raw(&container[0], container.size()*sizeof(typename T::value_type));
210 }
211
w_seq(const T & container,F write)212 template<typename T, typename F> inline void xr_writer::w_seq(const T& container, F write)
213 {
214 for (typename T::const_iterator it = container.begin(),
215 end = container.end(); it != end; ++it) {
216 write(*it, *this);
217 }
218 }
219
w_chunk(uint32_t id,const std::string & s)220 inline void xr_writer::w_chunk(uint32_t id, const std::string& s)
221 {
222 open_chunk(id);
223 w_sz(s);
224 close_chunk();
225 }
226
w_chunk(uint32_t id,const T & value)227 template<typename T> inline void xr_writer::w_chunk(uint32_t id, const T& value)
228 {
229 w_raw_chunk(id, &value, sizeof(T));
230 }
231
w_chunks(const T & container,F write)232 template<typename T, typename F> inline void xr_writer::w_chunks(const T& container, F write)
233 {
234 typename T::const_iterator it = container.begin(), end = container.end();
235 for (uint32_t id = 0; it != end; ++it) {
236 open_chunk(id++);
237 write(*it, *this);
238 close_chunk();
239 }
240 }
241
w_ini_seq(const T & container,const char * prefix)242 template<typename T> inline void xr_ini_writer::w_ini_seq(const T& container, const char* prefix)
243 {
244 char buf[1024];
245
246 typename T::const_iterator it = container.begin(), end = container.end();
247 for (uint32_t id = 0; it != end; ++it) {
248 #if defined(_MSC_VER) && _MSC_VER >= 1400
249 int n = sprintf_s(buf, sizeof(buf), "%s_%04d", prefix, id);
250 #else
251 int n = snprintf(buf, sizeof(buf), "%s_%04d", prefix, id);
252 #endif
253 if (n > 0)
254 write(buf, *it);
255 id++;
256 }
257 }
258
w_ini_seq(const T & container,F write)259 template<typename T, typename F> inline void xr_ini_writer::w_ini_seq(const T& container, F write)
260 {
261 uint32_t id = 0;
262 for (typename T::const_iterator it = container.begin(),
263 end = container.end(); it != end; ++it, ++id) {
264 write(*it, this, id);
265 }
266 }
267
w_ini_seq(const T & container,F write,const char * prefix)268 template<typename T, typename F> inline void xr_ini_writer::w_ini_seq(const T& container, F write, const char* prefix)
269 {
270 char buf[1024];
271 typename T::const_iterator it = container.begin(), end = container.end();
272
273 for (uint32_t id = 0; it != end; ++it, ++id) {
274 #if defined(_MSC_VER) && _MSC_VER >= 1400
275 int n = sprintf_s(buf, sizeof(buf), "%s_%04d", prefix, id);
276 #else
277 int n = snprintf(buf, sizeof(buf), "%s_%04d", prefix, id);
278 #endif
279 if (n > 0)
280 write(*it, *this, buf);
281 }
282 }
283
w_sections(const T & container,F write,const char * prefix)284 template<typename T, typename F> inline void xr_ini_writer::w_sections(const T& container, F write, const char* prefix)
285 {
286 typename T::const_iterator it = container.begin(), end = container.end();
287 for (uint32_t id = 0; it != end; ++it) {
288 open_section("%s_%d", prefix, id++);
289 write(*it, this);
290 close_section();
291 }
292 }
293
data()294 inline const uint8_t* xr_memory_writer::data() const { return &m_buffer[0]; }
295
296 } // end of namespace xray_re
297
298 #endif
299