]> git.lizzy.rs Git - dragonfireclient.git/blob - src/util/serialize.h
Initially split utility.h to multiple files in util/
[dragonfireclient.git] / src / util / serialize.h
1 /*
2 Minetest-c55
3 Copyright (C) 2010-2012 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 <iostream>
25 #include <string>
26 #include "../exceptions.h"
27 #include "pointer.h"
28
29 inline void writeU64(u8 *data, u64 i)
30 {
31         data[0] = ((i>>56)&0xff);
32         data[1] = ((i>>48)&0xff);
33         data[2] = ((i>>40)&0xff);
34         data[3] = ((i>>32)&0xff);
35         data[4] = ((i>>24)&0xff);
36         data[5] = ((i>>16)&0xff);
37         data[6] = ((i>> 8)&0xff);
38         data[7] = ((i>> 0)&0xff);
39 }
40
41 inline void writeU32(u8 *data, u32 i)
42 {
43         data[0] = ((i>>24)&0xff);
44         data[1] = ((i>>16)&0xff);
45         data[2] = ((i>> 8)&0xff);
46         data[3] = ((i>> 0)&0xff);
47 }
48
49 inline void writeU16(u8 *data, u16 i)
50 {
51         data[0] = ((i>> 8)&0xff);
52         data[1] = ((i>> 0)&0xff);
53 }
54
55 inline void writeU8(u8 *data, u8 i)
56 {
57         data[0] = ((i>> 0)&0xff);
58 }
59
60 inline u64 readU64(u8 *data)
61 {
62         return ((u64)data[0]<<56) | ((u64)data[1]<<48)
63                 | ((u64)data[2]<<40) | ((u64)data[3]<<32)
64                 | ((u64)data[4]<<24) | ((u64)data[5]<<16)
65                 | ((u64)data[6]<<8) | ((u64)data[7]<<0);
66 }
67
68 inline u32 readU32(u8 *data)
69 {
70         return (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | (data[3]<<0);
71 }
72
73 inline u16 readU16(u8 *data)
74 {
75         return (data[0]<<8) | (data[1]<<0);
76 }
77
78 inline u8 readU8(u8 *data)
79 {
80         return (data[0]<<0);
81 }
82
83 inline void writeS32(u8 *data, s32 i){
84         writeU32(data, (u32)i);
85 }
86 inline s32 readS32(u8 *data){
87         return (s32)readU32(data);
88 }
89
90 inline void writeS16(u8 *data, s16 i){
91         writeU16(data, (u16)i);
92 }
93 inline s16 readS16(u8 *data){
94         return (s16)readU16(data);
95 }
96
97 inline void writeS8(u8 *data, s8 i){
98         writeU8(data, (u8)i);
99 }
100 inline s8 readS8(u8 *data){
101         return (s8)readU8(data);
102 }
103
104 inline void writeF1000(u8 *data, f32 i){
105         writeS32(data, i*1000);
106 }
107 inline f32 readF1000(u8 *data){
108         return (f32)readS32(data)/1000.;
109 }
110
111 inline void writeV3S32(u8 *data, v3s32 p)
112 {
113         writeS32(&data[0], p.X);
114         writeS32(&data[4], p.Y);
115         writeS32(&data[8], p.Z);
116 }
117 inline v3s32 readV3S32(u8 *data)
118 {
119         v3s32 p;
120         p.X = readS32(&data[0]);
121         p.Y = readS32(&data[4]);
122         p.Z = readS32(&data[8]);
123         return p;
124 }
125
126 inline void writeV3F1000(u8 *data, v3f p)
127 {
128         writeF1000(&data[0], p.X);
129         writeF1000(&data[4], p.Y);
130         writeF1000(&data[8], p.Z);
131 }
132 inline v3f readV3F1000(u8 *data)
133 {
134         v3f p;
135         p.X = (float)readF1000(&data[0]);
136         p.Y = (float)readF1000(&data[4]);
137         p.Z = (float)readF1000(&data[8]);
138         return p;
139 }
140
141 inline void writeV2F1000(u8 *data, v2f p)
142 {
143         writeF1000(&data[0], p.X);
144         writeF1000(&data[4], p.Y);
145 }
146 inline v2f readV2F1000(u8 *data)
147 {
148         v2f p;
149         p.X = (float)readF1000(&data[0]);
150         p.Y = (float)readF1000(&data[4]);
151         return p;
152 }
153
154 inline void writeV2S16(u8 *data, v2s16 p)
155 {
156         writeS16(&data[0], p.X);
157         writeS16(&data[2], p.Y);
158 }
159
160 inline v2s16 readV2S16(u8 *data)
161 {
162         v2s16 p;
163         p.X = readS16(&data[0]);
164         p.Y = readS16(&data[2]);
165         return p;
166 }
167
168 inline void writeV2S32(u8 *data, v2s32 p)
169 {
170         writeS32(&data[0], p.X);
171         writeS32(&data[2], p.Y);
172 }
173
174 inline v2s32 readV2S32(u8 *data)
175 {
176         v2s32 p;
177         p.X = readS32(&data[0]);
178         p.Y = readS32(&data[2]);
179         return p;
180 }
181
182 inline void writeV3S16(u8 *data, v3s16 p)
183 {
184         writeS16(&data[0], p.X);
185         writeS16(&data[2], p.Y);
186         writeS16(&data[4], p.Z);
187 }
188
189 inline v3s16 readV3S16(u8 *data)
190 {
191         v3s16 p;
192         p.X = readS16(&data[0]);
193         p.Y = readS16(&data[2]);
194         p.Z = readS16(&data[4]);
195         return p;
196 }
197
198 /*
199         The above stuff directly interfaced to iostream
200 */
201
202 inline void writeU8(std::ostream &os, u8 p)
203 {
204         char buf[1] = {0};
205         writeU8((u8*)buf, p);
206         os.write(buf, 1);
207 }
208 inline u8 readU8(std::istream &is)
209 {
210         char buf[1] = {0};
211         is.read(buf, 1);
212         return readU8((u8*)buf);
213 }
214
215 inline void writeU16(std::ostream &os, u16 p)
216 {
217         char buf[2] = {0};
218         writeU16((u8*)buf, p);
219         os.write(buf, 2);
220 }
221 inline u16 readU16(std::istream &is)
222 {
223         char buf[2] = {0};
224         is.read(buf, 2);
225         return readU16((u8*)buf);
226 }
227
228 inline void writeU32(std::ostream &os, u32 p)
229 {
230         char buf[4] = {0};
231         writeU32((u8*)buf, p);
232         os.write(buf, 4);
233 }
234 inline u32 readU32(std::istream &is)
235 {
236         char buf[4] = {0};
237         is.read(buf, 4);
238         return readU32((u8*)buf);
239 }
240
241 inline void writeS32(std::ostream &os, s32 p)
242 {
243         char buf[4] = {0};
244         writeS32((u8*)buf, p);
245         os.write(buf, 4);
246 }
247 inline s32 readS32(std::istream &is)
248 {
249         char buf[4] = {0};
250         is.read(buf, 4);
251         return readS32((u8*)buf);
252 }
253
254 inline void writeS16(std::ostream &os, s16 p)
255 {
256         char buf[2] = {0};
257         writeS16((u8*)buf, p);
258         os.write(buf, 2);
259 }
260 inline s16 readS16(std::istream &is)
261 {
262         char buf[2] = {0};
263         is.read(buf, 2);
264         return readS16((u8*)buf);
265 }
266
267 inline void writeS8(std::ostream &os, s8 p)
268 {
269         char buf[1] = {0};
270         writeS8((u8*)buf, p);
271         os.write(buf, 1);
272 }
273 inline s8 readS8(std::istream &is)
274 {
275         char buf[1] = {0};
276         is.read(buf, 1);
277         return readS8((u8*)buf);
278 }
279
280 inline void writeF1000(std::ostream &os, f32 p)
281 {
282         char buf[4] = {0};
283         writeF1000((u8*)buf, p);
284         os.write(buf, 4);
285 }
286 inline f32 readF1000(std::istream &is)
287 {
288         char buf[4] = {0};
289         is.read(buf, 4);
290         return readF1000((u8*)buf);
291 }
292
293 inline void writeV3F1000(std::ostream &os, v3f p)
294 {
295         char buf[12];
296         writeV3F1000((u8*)buf, p);
297         os.write(buf, 12);
298 }
299 inline v3f readV3F1000(std::istream &is)
300 {
301         char buf[12];
302         is.read(buf, 12);
303         return readV3F1000((u8*)buf);
304 }
305
306 inline void writeV2F1000(std::ostream &os, v2f p)
307 {
308         char buf[8] = {0};
309         writeV2F1000((u8*)buf, p);
310         os.write(buf, 8);
311 }
312 inline v2f readV2F1000(std::istream &is)
313 {
314         char buf[8] = {0};
315         is.read(buf, 8);
316         return readV2F1000((u8*)buf);
317 }
318
319 inline void writeV2S16(std::ostream &os, v2s16 p)
320 {
321         char buf[4] = {0};
322         writeV2S16((u8*)buf, p);
323         os.write(buf, 4);
324 }
325 inline v2s16 readV2S16(std::istream &is)
326 {
327         char buf[4] = {0};
328         is.read(buf, 4);
329         return readV2S16((u8*)buf);
330 }
331
332 inline void writeV3S16(std::ostream &os, v3s16 p)
333 {
334         char buf[6] = {0};
335         writeV3S16((u8*)buf, p);
336         os.write(buf, 6);
337 }
338 inline v3s16 readV3S16(std::istream &is)
339 {
340         char buf[6] = {0};
341         is.read(buf, 6);
342         return readV3S16((u8*)buf);
343 }
344
345 /*
346         More serialization stuff
347 */
348
349 // Creates a string with the length as the first two bytes
350 inline std::string serializeString(const std::string &plain)
351 {
352         //assert(plain.size() <= 65535);
353         if(plain.size() > 65535)
354                 throw SerializationError("String too long for serializeString");
355         char buf[2];
356         writeU16((u8*)&buf[0], plain.size());
357         std::string s;
358         s.append(buf, 2);
359         s.append(plain);
360         return s;
361 }
362
363 // Creates a string with the length as the first two bytes from wide string
364 inline std::string serializeWideString(const std::wstring &plain)
365 {
366         //assert(plain.size() <= 65535);
367         if(plain.size() > 65535)
368                 throw SerializationError("String too long for serializeString");
369         char buf[2];
370         writeU16((u8*)buf, plain.size());
371         std::string s;
372         s.append(buf, 2);
373         for(u32 i=0; i<plain.size(); i++)
374         {
375                 writeU16((u8*)buf, plain[i]);
376                 s.append(buf, 2);
377         }
378         return s;
379 }
380
381 // Reads a string with the length as the first two bytes
382 inline std::string deSerializeString(std::istream &is)
383 {
384         char buf[2];
385         is.read(buf, 2);
386         if(is.gcount() != 2)
387                 throw SerializationError("deSerializeString: size not read");
388         u16 s_size = readU16((u8*)buf);
389         if(s_size == 0)
390                 return "";
391         Buffer<char> buf2(s_size);
392         is.read(&buf2[0], s_size);
393         std::string s;
394         s.reserve(s_size);
395         s.append(&buf2[0], s_size);
396         return s;
397 }
398
399 // Reads a wide string with the length as the first two bytes
400 inline std::wstring deSerializeWideString(std::istream &is)
401 {
402         char buf[2];
403         is.read(buf, 2);
404         if(is.gcount() != 2)
405                 throw SerializationError("deSerializeString: size not read");
406         u16 s_size = readU16((u8*)buf);
407         if(s_size == 0)
408                 return L"";
409         std::wstring s;
410         s.reserve(s_size);
411         for(u32 i=0; i<s_size; i++)
412         {
413                 is.read(&buf[0], 2);
414                 wchar_t c16 = readU16((u8*)buf);
415                 s.append(&c16, 1);
416         }
417         return s;
418 }
419
420 // Creates a string with the length as the first four bytes
421 inline std::string serializeLongString(const std::string &plain)
422 {
423         char buf[4];
424         writeU32((u8*)&buf[0], plain.size());
425         std::string s;
426         s.append(buf, 4);
427         s.append(plain);
428         return s;
429 }
430
431 // Reads a string with the length as the first four bytes
432 inline std::string deSerializeLongString(std::istream &is)
433 {
434         char buf[4];
435         is.read(buf, 4);
436         if(is.gcount() != 4)
437                 throw SerializationError("deSerializeLongString: size not read");
438         u32 s_size = readU32((u8*)buf);
439         if(s_size == 0)
440                 return "";
441         Buffer<char> buf2(s_size);
442         is.read(&buf2[0], s_size);
443         std::string s;
444         s.reserve(s_size);
445         s.append(&buf2[0], s_size);
446         return s;
447 }
448
449 // Creates a string encoded in JSON format (almost equivalent to a C string literal)
450 std::string serializeJsonString(const std::string &plain);
451
452 // Reads a string encoded in JSON format
453 std::string deSerializeJsonString(std::istream &is);
454
455 #endif
456