Luanti 5.11.0-dev
 
Loading...
Searching...
No Matches
serialize.h
Go to the documentation of this file.
1// Luanti
2// SPDX-License-Identifier: LGPL-2.1-or-later
3// Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5#pragma once
6
8#include "exceptions.h" // for SerializationError
9#include "ieee_float.h"
10
11#include "config.h"
12#include <cstring> // for memcpy
13#include <cassert>
14#include <iostream>
15#include <string>
16#include <string_view>
17
18/* make sure BYTE_ORDER macros are available */
19#ifdef _WIN32
20 #define BYTE_ORDER 1234
21#elif defined(__MACH__) && defined(__APPLE__)
22 #include <machine/endian.h>
23#elif defined(__FreeBSD__) || defined(__DragonFly__)
24 #include <sys/endian.h>
25#elif HAVE_ENDIAN_H
26 #include <endian.h>
27#else
28 #error "Can't detect endian (missing header)"
29#endif
30#ifndef LITTLE_ENDIAN
31 #define LITTLE_ENDIAN 1234
32#endif
33#ifndef BIG_ENDIAN
34 #define BIG_ENDIAN 4321
35#endif
36#if !defined(BYTE_ORDER) && defined(_BYTE_ORDER)
37 #define BYTE_ORDER _BYTE_ORDER
38#elif !defined(BYTE_ORDER) && defined(__BYTE_ORDER)
39 #define BYTE_ORDER __BYTE_ORDER
40#endif
41
42#define FIXEDPOINT_FACTOR 1000.0f
43
44// 0x7FFFFFFF / 1000.0f is not serializable.
45// The limited float precision at this magnitude may cause the result to round
46// to a greater value than can be represented by a 32 bit integer when increased
47// by a factor of FIXEDPOINT_FACTOR. As a result, [F1000_MIN..F1000_MAX] does
48// not represent the full range, but rather the largest safe range, of values on
49// all supported architectures. Note: This definition makes assumptions on
50// platform float-to-int conversion behavior.
51#define F1000_MIN ((float)(s32)((float)(-0x7FFFFFFF - 1) / FIXEDPOINT_FACTOR))
52#define F1000_MAX ((float)(s32)((float)(0x7FFFFFFF) / FIXEDPOINT_FACTOR))
53
54#define STRING_MAX_LEN 0xFFFF
55#define WIDE_STRING_MAX_LEN 0xFFFF
56// 64 MB ought to be enough for anybody - Billy G.
57#define LONG_STRING_MAX_LEN (64 * 1024 * 1024)
58
59
61
62#if HAVE_ENDIAN_H
63// use machine native byte swapping routines
64// Note: memcpy below is optimized out by modern compilers
65
66inline u16 readU16(const u8 *data)
67{
68 u16 val;
69 memcpy(&val, data, 2);
70 return be16toh(val);
71}
72
73inline u32 readU32(const u8 *data)
74{
75 u32 val;
76 memcpy(&val, data, 4);
77 return be32toh(val);
78}
79
80inline u64 readU64(const u8 *data)
81{
82 u64 val;
83 memcpy(&val, data, 8);
84 return be64toh(val);
85}
86
87inline void writeU16(u8 *data, u16 i)
88{
89 u16 val = htobe16(i);
90 memcpy(data, &val, 2);
91}
92
93inline void writeU32(u8 *data, u32 i)
94{
95 u32 val = htobe32(i);
96 memcpy(data, &val, 4);
97}
98
99inline void writeU64(u8 *data, u64 i)
100{
101 u64 val = htobe64(i);
102 memcpy(data, &val, 8);
103}
104
105#else
106// generic byte-swapping implementation
107
108inline u16 readU16(const u8 *data)
109{
110 return
111 ((u16)data[0] << 8) | ((u16)data[1] << 0);
112}
113
114inline u32 readU32(const u8 *data)
115{
116 return
117 ((u32)data[0] << 24) | ((u32)data[1] << 16) |
118 ((u32)data[2] << 8) | ((u32)data[3] << 0);
119}
120
121inline u64 readU64(const u8 *data)
122{
123 return
124 ((u64)data[0] << 56) | ((u64)data[1] << 48) |
125 ((u64)data[2] << 40) | ((u64)data[3] << 32) |
126 ((u64)data[4] << 24) | ((u64)data[5] << 16) |
127 ((u64)data[6] << 8) | ((u64)data[7] << 0);
128}
129
130inline void writeU16(u8 *data, u16 i)
131{
132 data[0] = (i >> 8) & 0xFF;
133 data[1] = (i >> 0) & 0xFF;
134}
135
136inline void writeU32(u8 *data, u32 i)
137{
138 data[0] = (i >> 24) & 0xFF;
139 data[1] = (i >> 16) & 0xFF;
140 data[2] = (i >> 8) & 0xFF;
141 data[3] = (i >> 0) & 0xFF;
142}
143
144inline void writeU64(u8 *data, u64 i)
145{
146 data[0] = (i >> 56) & 0xFF;
147 data[1] = (i >> 48) & 0xFF;
148 data[2] = (i >> 40) & 0xFF;
149 data[3] = (i >> 32) & 0xFF;
150 data[4] = (i >> 24) & 0xFF;
151 data[5] = (i >> 16) & 0xFF;
152 data[6] = (i >> 8) & 0xFF;
153 data[7] = (i >> 0) & 0xFF;
154}
155
156#endif // HAVE_ENDIAN_H
157
159
160inline u8 readU8(const u8 *data)
161{
162 return ((u8)data[0] << 0);
163}
164
165inline s8 readS8(const u8 *data)
166{
167 return (s8)readU8(data);
168}
169
170inline s16 readS16(const u8 *data)
171{
172 return (s16)readU16(data);
173}
174
175inline s32 readS32(const u8 *data)
176{
177 return (s32)readU32(data);
178}
179
180inline s64 readS64(const u8 *data)
181{
182 return (s64)readU64(data);
183}
184
185inline f32 readF1000(const u8 *data)
186{
187 return (f32)readS32(data) / FIXEDPOINT_FACTOR;
188}
189
190inline f32 readF32(const u8 *data)
191{
192 u32 u = readU32(data);
193
194 switch (g_serialize_f32_type) {
195 case FLOATTYPE_SYSTEM: {
196 f32 f;
197 memcpy(&f, &u, 4);
198 return f;
199 }
200 case FLOATTYPE_SLOW:
201 return u32Tof32Slow(u);
202 case FLOATTYPE_UNKNOWN: // First initialization
204 return readF32(data);
205 }
206 throw SerializationError("readF32: Unreachable code");
207}
208
209inline video::SColor readARGB8(const u8 *data)
210{
211 video::SColor p(readU32(data));
212 return p;
213}
214
215inline v2s16 readV2S16(const u8 *data)
216{
217 v2s16 p;
218 p.X = readS16(&data[0]);
219 p.Y = readS16(&data[2]);
220 return p;
221}
222
223inline v3s16 readV3S16(const u8 *data)
224{
225 v3s16 p;
226 p.X = readS16(&data[0]);
227 p.Y = readS16(&data[2]);
228 p.Z = readS16(&data[4]);
229 return p;
230}
231
232inline v2s32 readV2S32(const u8 *data)
233{
234 v2s32 p;
235 p.X = readS32(&data[0]);
236 p.Y = readS32(&data[4]);
237 return p;
238}
239
240inline v3s32 readV3S32(const u8 *data)
241{
242 v3s32 p;
243 p.X = readS32(&data[0]);
244 p.Y = readS32(&data[4]);
245 p.Z = readS32(&data[8]);
246 return p;
247}
248
249inline v3f readV3F1000(const u8 *data)
250{
251 v3f p;
252 p.X = readF1000(&data[0]);
253 p.Y = readF1000(&data[4]);
254 p.Z = readF1000(&data[8]);
255 return p;
256}
257
258inline v2f readV2F32(const u8 *data)
259{
260 v2f p;
261 p.X = readF32(&data[0]);
262 p.Y = readF32(&data[4]);
263 return p;
264}
265
266inline v3f readV3F32(const u8 *data)
267{
268 v3f p;
269 p.X = readF32(&data[0]);
270 p.Y = readF32(&data[4]);
271 p.Z = readF32(&data[8]);
272 return p;
273}
274
276
277inline void writeU8(u8 *data, u8 i)
278{
279 data[0] = i;
280}
281
282inline void writeS8(u8 *data, s8 i)
283{
284 writeU8(data, (u8)i);
285}
286
287inline void writeS16(u8 *data, s16 i)
288{
289 writeU16(data, (u16)i);
290}
291
292inline void writeS32(u8 *data, s32 i)
293{
294 writeU32(data, (u32)i);
295}
296
297inline void writeS64(u8 *data, s64 i)
298{
299 writeU64(data, (u64)i);
300}
301
302inline void writeF1000(u8 *data, f32 i)
303{
304 assert(i >= F1000_MIN && i <= F1000_MAX);
305 writeS32(data, i * FIXEDPOINT_FACTOR);
306}
307
308inline void writeF32(u8 *data, f32 i)
309{
310 switch (g_serialize_f32_type) {
311 case FLOATTYPE_SYSTEM: {
312 u32 u;
313 memcpy(&u, &i, 4);
314 return writeU32(data, u);
315 }
316 case FLOATTYPE_SLOW:
317 return writeU32(data, f32Tou32Slow(i));
318 case FLOATTYPE_UNKNOWN: // First initialization
320 return writeF32(data, i);
321 }
322 throw SerializationError("writeF32: Unreachable code");
323}
324
325inline void writeARGB8(u8 *data, video::SColor p)
326{
327 writeU32(data, p.color);
328}
329
330inline void writeV2S16(u8 *data, v2s16 p)
331{
332 writeS16(&data[0], p.X);
333 writeS16(&data[2], p.Y);
334}
335
336inline void writeV3S16(u8 *data, v3s16 p)
337{
338 writeS16(&data[0], p.X);
339 writeS16(&data[2], p.Y);
340 writeS16(&data[4], p.Z);
341}
342
343inline void writeV2S32(u8 *data, v2s32 p)
344{
345 writeS32(&data[0], p.X);
346 writeS32(&data[4], p.Y);
347}
348
349inline void writeV3S32(u8 *data, v3s32 p)
350{
351 writeS32(&data[0], p.X);
352 writeS32(&data[4], p.Y);
353 writeS32(&data[8], p.Z);
354}
355
356inline void writeV3F1000(u8 *data, v3f p)
357{
358 writeF1000(&data[0], p.X);
359 writeF1000(&data[4], p.Y);
360 writeF1000(&data[8], p.Z);
361}
362
363inline void writeV2F32(u8 *data, v2f p)
364{
365 writeF32(&data[0], p.X);
366 writeF32(&data[4], p.Y);
367}
368
369inline void writeV3F32(u8 *data, v3f p)
370{
371 writeF32(&data[0], p.X);
372 writeF32(&data[4], p.Y);
373 writeF32(&data[8], p.Z);
374}
375
379
380#define MAKE_STREAM_READ_FXN(T, N, S) \
381 inline T read ## N(std::istream &is) \
382 { \
383 char buf[S] = {0}; \
384 is.read(buf, sizeof(buf)); \
385 return read ## N((u8 *)buf); \
386 }
387
388#define MAKE_STREAM_WRITE_FXN(T, N, S) \
389 inline void write ## N(std::ostream &os, T val) \
390 { \
391 char buf[S]; \
392 write ## N((u8 *)buf, val); \
393 os.write(buf, sizeof(buf)); \
394 }
395
404MAKE_STREAM_READ_FXN(f32, F1000, 4);
413MAKE_STREAM_READ_FXN(video::SColor, ARGB8, 4);
414
432MAKE_STREAM_WRITE_FXN(video::SColor, ARGB8, 4);
433
437
438inline float clampToF1000(float v)
439{
440 return core::clamp(v, F1000_MIN, F1000_MAX);
441}
442
444{
445 return {clampToF1000(v.X), clampToF1000(v.Y), clampToF1000(v.Z)};
446}
447
448// Creates a string with the length as the first two bytes
449std::string serializeString16(std::string_view plain);
450
451// Reads a string with the length as the first two bytes
452std::string deSerializeString16(std::istream &is);
453
454// Creates a string with the length as the first four bytes
455std::string serializeString32(std::string_view plain);
456
457// Reads a string with the length as the first four bytes
458std::string deSerializeString32(std::istream &is);
459
460// Creates a string encoded in JSON format (almost equivalent to a C string literal)
461std::string serializeJsonString(std::string_view plain);
462
463// Reads a string encoded in JSON format
464std::string deSerializeJsonString(std::istream &is);
465
466// If the string contains spaces, quotes or control characters, encodes as JSON.
467// Else returns the string unmodified.
468std::string serializeJsonStringIfNeeded(std::string_view s);
469
470// Parses a string serialized by serializeJsonStringIfNeeded.
471std::string deSerializeJsonStringIfNeeded(std::istream &is);
Definition exceptions.h:45
u32 f32Tou32Slow(f32 f)
Definition ieee_float.cpp:64
FloatType getFloatSerializationType()
Definition ieee_float.cpp:95
f32 u32Tof32Slow(u32 i)
Definition ieee_float.cpp:35
FloatType
Definition ieee_float.h:10
@ FLOATTYPE_UNKNOWN
Definition ieee_float.h:11
@ FLOATTYPE_SLOW
Definition ieee_float.h:12
@ FLOATTYPE_SYSTEM
Definition ieee_float.h:13
core::vector2d< s32 > v2s32
Definition irr_v2d.h:13
core::vector2d< s16 > v2s16
Definition irr_v2d.h:12
core::vector2d< f32 > v2f
Definition irr_v2d.h:11
core::vector3d< s32 > v3s32
Definition irr_v3d.h:15
core::vector3d< s16 > v3s16
Definition irr_v3d.h:13
core::vector3df v3f
Definition irr_v3d.h:11
std::string serializeJsonStringIfNeeded(std::string_view s)
Definition serialize.cpp:251
v2s16 readV2S16(const u8 *data)
Definition serialize.h:215
void writeU16(u8 *data, u16 i)
Definition serialize.h:130
u32 readU32(const u8 *data)
Definition serialize.h:114
void writeV3S16(u8 *data, v3s16 p)
Definition serialize.h:336
std::string deSerializeJsonString(std::istream &is)
Definition serialize.cpp:220
v2s32 readV2S32(const u8 *data)
Definition serialize.h:232
void writeF1000(u8 *data, f32 i)
Definition serialize.h:302
void writeS16(u8 *data, s16 i)
Definition serialize.h:287
s64 readS64(const u8 *data)
Definition serialize.h:180
#define FIXEDPOINT_FACTOR
Definition serialize.h:42
void writeV2F32(u8 *data, v2f p)
Definition serialize.h:363
void writeF32(u8 *data, f32 i)
Definition serialize.h:308
void writeU64(u8 *data, u64 i)
Definition serialize.h:144
s32 readS32(const u8 *data)
Definition serialize.h:175
std::string deSerializeString32(std::istream &is)
Definition serialize.cpp:79
u8 readU8(const u8 *data)
Definition serialize.h:160
void writeV2S32(u8 *data, v2s32 p)
Definition serialize.h:343
video::SColor readARGB8(const u8 *data)
Definition serialize.h:209
std::string deSerializeJsonStringIfNeeded(std::istream &is)
Definition serialize.cpp:260
v3f readV3F1000(const u8 *data)
Definition serialize.h:249
v3s16 readV3S16(const u8 *data)
Definition serialize.h:223
void writeV2S16(u8 *data, v2s16 p)
Definition serialize.h:330
f32 readF32(const u8 *data)
Definition serialize.h:190
f32 readF1000(const u8 *data)
Definition serialize.h:185
void writeARGB8(u8 *data, video::SColor p)
Definition serialize.h:325
std::string serializeJsonString(std::string_view plain)
Definition serialize.cpp:110
#define MAKE_STREAM_READ_FXN(T, N, S)
Definition serialize.h:380
FloatType g_serialize_f32_type
Definition serialize.cpp:15
u64 readU64(const u8 *data)
Definition serialize.h:121
void writeU32(u8 *data, u32 i)
Definition serialize.h:136
void writeV3F32(u8 *data, v3f p)
Definition serialize.h:369
std::string serializeString16(std::string_view plain)
Definition serialize.cpp:22
void writeS8(u8 *data, s8 i)
Definition serialize.h:282
std::string deSerializeString16(std::istream &is)
Definition serialize.cpp:38
void writeV3S32(u8 *data, v3s32 p)
Definition serialize.h:349
std::string serializeString32(std::string_view plain)
Definition serialize.cpp:64
#define F1000_MIN
Definition serialize.h:51
u16 readU16(const u8 *data)
Definition serialize.h:108
v2f readV2F32(const u8 *data)
Definition serialize.h:258
float clampToF1000(float v)
Definition serialize.h:438
v3s32 readV3S32(const u8 *data)
Definition serialize.h:240
void writeV3F1000(u8 *data, v3f p)
Definition serialize.h:356
#define MAKE_STREAM_WRITE_FXN(T, N, S)
Definition serialize.h:388
void writeU8(u8 *data, u8 i)
Definition serialize.h:277
v3f readV3F32(const u8 *data)
Definition serialize.h:266
void writeS32(u8 *data, s32 i)
Definition serialize.h:292
s8 readS8(const u8 *data)
Definition serialize.h:165
s16 readS16(const u8 *data)
Definition serialize.h:170
#define F1000_MAX
Definition serialize.h:52
void writeS64(u8 *data, s64 i)
Definition serialize.h:297
static std::string p(std::string path)
Definition test_filesys.cpp:53