]> git.lizzy.rs Git - minetest.git/blob - src/util/serialize.h
Merge remote branch 'origin/master'
[minetest.git] / src / util / serialize.h
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #ifndef UTIL_SERIALIZE_HEADER
21 #define UTIL_SERIALIZE_HEADER
22
23 #include "../irrlichttypes.h"
24 #include "../irrlichttypes_bloated.h"
25 #include "../irr_v2d.h"
26 #include "../irr_v3d.h"
27 #include <iostream>
28 #include <string>
29 #include "../exceptions.h"
30 #include "pointer.h"
31
32 inline void writeU64(u8 *data, u64 i)
33 {
34         data[0] = ((i>>56)&0xff);
35         data[1] = ((i>>48)&0xff);
36         data[2] = ((i>>40)&0xff);
37         data[3] = ((i>>32)&0xff);
38         data[4] = ((i>>24)&0xff);
39         data[5] = ((i>>16)&0xff);
40         data[6] = ((i>> 8)&0xff);
41         data[7] = ((i>> 0)&0xff);
42 }
43
44 inline void writeU32(u8 *data, u32 i)
45 {
46         data[0] = ((i>>24)&0xff);
47         data[1] = ((i>>16)&0xff);
48         data[2] = ((i>> 8)&0xff);
49         data[3] = ((i>> 0)&0xff);
50 }
51
52 inline void writeU16(u8 *data, u16 i)
53 {
54         data[0] = ((i>> 8)&0xff);
55         data[1] = ((i>> 0)&0xff);
56 }
57
58 inline void writeU8(u8 *data, u8 i)
59 {
60         data[0] = ((i>> 0)&0xff);
61 }
62
63 inline u64 readU64(const u8 *data)
64 {
65         return ((u64)data[0]<<56) | ((u64)data[1]<<48)
66                 | ((u64)data[2]<<40) | ((u64)data[3]<<32)
67                 | ((u64)data[4]<<24) | ((u64)data[5]<<16)
68                 | ((u64)data[6]<<8) | ((u64)data[7]<<0);
69 }
70
71 inline u32 readU32(const u8 *data)
72 {
73         return (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | (data[3]<<0);
74 }
75
76 inline u16 readU16(const u8 *data)
77 {
78         return (data[0]<<8) | (data[1]<<0);
79 }
80
81 inline u8 readU8(const u8 *data)
82 {
83         return (data[0]<<0);
84 }
85
86 inline void writeS32(u8 *data, s32 i){
87         writeU32(data, (u32)i);
88 }
89 inline s32 readS32(const u8 *data){
90         return (s32)readU32(data);
91 }
92
93 inline void writeS16(u8 *data, s16 i){
94         writeU16(data, (u16)i);
95 }
96 inline s16 readS16(const u8 *data){
97         return (s16)readU16(data);
98 }
99
100 inline void writeS8(u8 *data, s8 i){
101         writeU8(data, (u8)i);
102 }
103 inline s8 readS8(const u8 *data){
104         return (s8)readU8(data);
105 }
106
107 inline void writeF1000(u8 *data, f32 i){
108         writeS32(data, i*1000);
109 }
110 inline f32 readF1000(const u8 *data){
111         return (f32)readS32(data)/1000.;
112 }
113
114 inline void writeV3S32(u8 *data, v3s32 p)
115 {
116         writeS32(&data[0], p.X);
117         writeS32(&data[4], p.Y);
118         writeS32(&data[8], p.Z);
119 }
120 inline v3s32 readV3S32(const u8 *data)
121 {
122         v3s32 p;
123         p.X = readS32(&data[0]);
124         p.Y = readS32(&data[4]);
125         p.Z = readS32(&data[8]);
126         return p;
127 }
128
129 inline void writeV3F1000(u8 *data, v3f p)
130 {
131         writeF1000(&data[0], p.X);
132         writeF1000(&data[4], p.Y);
133         writeF1000(&data[8], p.Z);
134 }
135 inline v3f readV3F1000(const u8 *data)
136 {
137         v3f p;
138         p.X = (float)readF1000(&data[0]);
139         p.Y = (float)readF1000(&data[4]);
140         p.Z = (float)readF1000(&data[8]);
141         return p;
142 }
143
144 inline void writeV2F1000(u8 *data, v2f p)
145 {
146         writeF1000(&data[0], p.X);
147         writeF1000(&data[4], p.Y);
148 }
149 inline v2f readV2F1000(const u8 *data)
150 {
151         v2f p;
152         p.X = (float)readF1000(&data[0]);
153         p.Y = (float)readF1000(&data[4]);
154         return p;
155 }
156
157 inline void writeV2S16(u8 *data, v2s16 p)
158 {
159         writeS16(&data[0], p.X);
160         writeS16(&data[2], p.Y);
161 }
162
163 inline v2s16 readV2S16(const u8 *data)
164 {
165         v2s16 p;
166         p.X = readS16(&data[0]);
167         p.Y = readS16(&data[2]);
168         return p;
169 }
170
171 inline void writeV2S32(u8 *data, v2s32 p)
172 {
173         writeS32(&data[0], p.X);
174         writeS32(&data[2], p.Y);
175 }
176
177 inline v2s32 readV2S32(const u8 *data)
178 {
179         v2s32 p;
180         p.X = readS32(&data[0]);
181         p.Y = readS32(&data[2]);
182         return p;
183 }
184
185 inline void writeV3S16(u8 *data, v3s16 p)
186 {
187         writeS16(&data[0], p.X);
188         writeS16(&data[2], p.Y);
189         writeS16(&data[4], p.Z);
190 }
191
192 inline v3s16 readV3S16(const u8 *data)
193 {
194         v3s16 p;
195         p.X = readS16(&data[0]);
196         p.Y = readS16(&data[2]);
197         p.Z = readS16(&data[4]);
198         return p;
199 }
200
201 inline void writeARGB8(u8 *data, video::SColor p)
202 {
203         writeU8(&data[0], p.getAlpha());
204         writeU8(&data[1], p.getRed());
205         writeU8(&data[2], p.getGreen());
206         writeU8(&data[3], p.getBlue());
207 }
208
209 inline video::SColor readARGB8(const u8 *data)
210 {
211         video::SColor p(
212                 readU8(&data[0]),
213                 readU8(&data[1]),
214                 readU8(&data[2]),
215                 readU8(&data[3])
216         );
217         return p;
218 }
219
220 /*
221         The above stuff directly interfaced to iostream
222 */
223
224 inline void writeU8(std::ostream &os, u8 p)
225 {
226         char buf[1] = {0};
227         writeU8((u8*)buf, p);
228         os.write(buf, 1);
229 }
230 inline u8 readU8(std::istream &is)
231 {
232         char buf[1] = {0};
233         is.read(buf, 1);
234         return readU8((u8*)buf);
235 }
236
237 inline void writeU16(std::ostream &os, u16 p)
238 {
239         char buf[2] = {0};
240         writeU16((u8*)buf, p);
241         os.write(buf, 2);
242 }
243 inline u16 readU16(std::istream &is)
244 {
245         char buf[2] = {0};
246         is.read(buf, 2);
247         return readU16((u8*)buf);
248 }
249
250 inline void writeU32(std::ostream &os, u32 p)
251 {
252         char buf[4] = {0};
253         writeU32((u8*)buf, p);
254         os.write(buf, 4);
255 }
256 inline u32 readU32(std::istream &is)
257 {
258         char buf[4] = {0};
259         is.read(buf, 4);
260         return readU32((u8*)buf);
261 }
262
263 inline void writeS32(std::ostream &os, s32 p)
264 {
265         char buf[4] = {0};
266         writeS32((u8*)buf, p);
267         os.write(buf, 4);
268 }
269 inline s32 readS32(std::istream &is)
270 {
271         char buf[4] = {0};
272         is.read(buf, 4);
273         return readS32((u8*)buf);
274 }
275
276 inline void writeS16(std::ostream &os, s16 p)
277 {
278         char buf[2] = {0};
279         writeS16((u8*)buf, p);
280         os.write(buf, 2);
281 }
282 inline s16 readS16(std::istream &is)
283 {
284         char buf[2] = {0};
285         is.read(buf, 2);
286         return readS16((u8*)buf);
287 }
288
289 inline void writeS8(std::ostream &os, s8 p)
290 {
291         char buf[1] = {0};
292         writeS8((u8*)buf, p);
293         os.write(buf, 1);
294 }
295 inline s8 readS8(std::istream &is)
296 {
297         char buf[1] = {0};
298         is.read(buf, 1);
299         return readS8((u8*)buf);
300 }
301
302 inline void writeF1000(std::ostream &os, f32 p)
303 {
304         char buf[4] = {0};
305         writeF1000((u8*)buf, p);
306         os.write(buf, 4);
307 }
308 inline f32 readF1000(std::istream &is)
309 {
310         char buf[4] = {0};
311         is.read(buf, 4);
312         return readF1000((u8*)buf);
313 }
314
315 inline void writeV3F1000(std::ostream &os, v3f p)
316 {
317         char buf[12];
318         writeV3F1000((u8*)buf, p);
319         os.write(buf, 12);
320 }
321 inline v3f readV3F1000(std::istream &is)
322 {
323         char buf[12];
324         is.read(buf, 12);
325         return readV3F1000((u8*)buf);
326 }
327
328 inline void writeV2F1000(std::ostream &os, v2f p)
329 {
330         char buf[8] = {0};
331         writeV2F1000((u8*)buf, p);
332         os.write(buf, 8);
333 }
334 inline v2f readV2F1000(std::istream &is)
335 {
336         char buf[8] = {0};
337         is.read(buf, 8);
338         return readV2F1000((u8*)buf);
339 }
340
341 inline void writeV2S16(std::ostream &os, v2s16 p)
342 {
343         char buf[4] = {0};
344         writeV2S16((u8*)buf, p);
345         os.write(buf, 4);
346 }
347 inline v2s16 readV2S16(std::istream &is)
348 {
349         char buf[4] = {0};
350         is.read(buf, 4);
351         return readV2S16((u8*)buf);
352 }
353
354 inline void writeV3S16(std::ostream &os, v3s16 p)
355 {
356         char buf[6] = {0};
357         writeV3S16((u8*)buf, p);
358         os.write(buf, 6);
359 }
360 inline v3s16 readV3S16(std::istream &is)
361 {
362         char buf[6] = {0};
363         is.read(buf, 6);
364         return readV3S16((u8*)buf);
365 }
366
367 inline void writeARGB8(std::ostream &os, video::SColor p)
368 {
369         char buf[4] = {0};
370         writeARGB8((u8*)buf, p);
371         os.write(buf, 4);
372 }
373
374 inline video::SColor readARGB8(std::istream &is)
375 {
376         char buf[4] = {0};
377         is.read(buf, 4);
378         return readARGB8((u8*)buf);
379 }
380
381 /*
382         More serialization stuff
383 */
384
385 // Creates a string with the length as the first two bytes
386 inline std::string serializeString(const std::string &plain)
387 {
388         //assert(plain.size() <= 65535);
389         if(plain.size() > 65535)
390                 throw SerializationError("String too long for serializeString");
391         char buf[2];
392         writeU16((u8*)&buf[0], plain.size());
393         std::string s;
394         s.append(buf, 2);
395         s.append(plain);
396         return s;
397 }
398
399 // Creates a string with the length as the first two bytes from wide string
400 inline std::string serializeWideString(const std::wstring &plain)
401 {
402         //assert(plain.size() <= 65535);
403         if(plain.size() > 65535)
404                 throw SerializationError("String too long for serializeString");
405         char buf[2];
406         writeU16((u8*)buf, plain.size());
407         std::string s;
408         s.append(buf, 2);
409         for(u32 i=0; i<plain.size(); i++)
410         {
411                 writeU16((u8*)buf, plain[i]);
412                 s.append(buf, 2);
413         }
414         return s;
415 }
416
417 // Reads a string with the length as the first two bytes
418 inline std::string deSerializeString(std::istream &is)
419 {
420         char buf[2];
421         is.read(buf, 2);
422         if(is.gcount() != 2)
423                 throw SerializationError("deSerializeString: size not read");
424         u16 s_size = readU16((u8*)buf);
425         if(s_size == 0)
426                 return "";
427         Buffer<char> buf2(s_size);
428         is.read(&buf2[0], s_size);
429         std::string s;
430         s.reserve(s_size);
431         s.append(&buf2[0], s_size);
432         return s;
433 }
434
435 // Reads a wide string with the length as the first two bytes
436 inline std::wstring deSerializeWideString(std::istream &is)
437 {
438         char buf[2];
439         is.read(buf, 2);
440         if(is.gcount() != 2)
441                 throw SerializationError("deSerializeString: size not read");
442         u16 s_size = readU16((u8*)buf);
443         if(s_size == 0)
444                 return L"";
445         std::wstring s;
446         s.reserve(s_size);
447         for(u32 i=0; i<s_size; i++)
448         {
449                 is.read(&buf[0], 2);
450                 wchar_t c16 = readU16((u8*)buf);
451                 s.append(&c16, 1);
452         }
453         return s;
454 }
455
456 // Creates a string with the length as the first four bytes
457 inline std::string serializeLongString(const std::string &plain)
458 {
459         char buf[4];
460         writeU32((u8*)&buf[0], plain.size());
461         std::string s;
462         s.append(buf, 4);
463         s.append(plain);
464         return s;
465 }
466
467 // Reads a string with the length as the first four bytes
468 inline std::string deSerializeLongString(std::istream &is)
469 {
470         char buf[4];
471         is.read(buf, 4);
472         if(is.gcount() != 4)
473                 throw SerializationError("deSerializeLongString: size not read");
474         u32 s_size = readU32((u8*)buf);
475         if(s_size == 0)
476                 return "";
477         Buffer<char> buf2(s_size);
478         is.read(&buf2[0], s_size);
479         std::string s;
480         s.reserve(s_size);
481         s.append(&buf2[0], s_size);
482         return s;
483 }
484
485 // Creates a string encoded in JSON format (almost equivalent to a C string literal)
486 std::string serializeJsonString(const std::string &plain);
487
488 // Reads a string encoded in JSON format
489 std::string deSerializeJsonString(std::istream &is);
490
491 #endif
492