X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Futil%2Fserialize.h;h=b3ec28eab58ccf10e826db8cd37e38b44a4b55ab;hb=e3bd6704a0eb65e9490347680441c7a08df36f7a;hp=58e59df224ce26c5a15aa44db07eab394214db6c;hpb=1a5b4b38f3457a8f1423305cef4e85d05da47d62;p=dragonfireclient.git diff --git a/src/util/serialize.h b/src/util/serialize.h index 58e59df22..b3ec28eab 100644 --- a/src/util/serialize.h +++ b/src/util/serialize.h @@ -17,18 +17,28 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef UTIL_SERIALIZE_HEADER -#define UTIL_SERIALIZE_HEADER +#pragma once -#include "../irrlichttypes_bloated.h" -#include "../exceptions.h" // for SerializationError -#include "../debug.h" // for assert +#include "irrlichttypes_bloated.h" +#include "exceptions.h" // for SerializationError +#include "debug.h" // for assert +#include "ieee_float.h" #include "config.h" #if HAVE_ENDIAN_H - #include + #ifdef _WIN32 + #define __BYTE_ORDER 0 + #define __LITTLE_ENDIAN 0 + #define __BIG_ENDIAN 1 + #elif defined(__MACH__) && defined(__APPLE__) + #include + #elif defined(__FreeBSD__) || defined(__DragonFly__) + #include + #else + #include + #endif #endif -#include // for memcpy +#include // for memcpy #include #include #include @@ -42,8 +52,8 @@ with this program; if not, write to the Free Software Foundation, Inc., // not represent the full range, but rather the largest safe range, of values on // all supported architectures. Note: This definition makes assumptions on // platform float-to-int conversion behavior. -#define F1000_MIN ((float)(s32)((-0x7FFFFFFF - 1) / FIXEDPOINT_FACTOR)) -#define F1000_MAX ((float)(s32)((0x7FFFFFFF) / FIXEDPOINT_FACTOR)) +#define F1000_MIN ((float)(s32)((float)(-0x7FFFFFFF - 1) / FIXEDPOINT_FACTOR)) +#define F1000_MAX ((float)(s32)((float)(0x7FFFFFFF) / FIXEDPOINT_FACTOR)) #define STRING_MAX_LEN 0xFFFF #define WIDE_STRING_MAX_LEN 0xFFFF @@ -51,6 +61,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #define LONG_STRING_MAX_LEN (64 * 1024 * 1024) +extern FloatType g_serialize_f32_type; + #if HAVE_ENDIAN_H // use machine native byte swapping routines // Note: memcpy below is optimized out by modern compilers @@ -179,6 +191,25 @@ inline f32 readF1000(const u8 *data) return (f32)readS32(data) / FIXEDPOINT_FACTOR; } +inline f32 readF32(const u8 *data) +{ + u32 u = readU32(data); + + switch (g_serialize_f32_type) { + case FLOATTYPE_SYSTEM: { + f32 f; + memcpy(&f, &u, 4); + return f; + } + case FLOATTYPE_SLOW: + return u32Tof32Slow(u); + case FLOATTYPE_UNKNOWN: // First initialization + g_serialize_f32_type = getFloatSerializationType(); + return readF32(data); + } + throw SerializationError("readF32: Unreachable code"); +} + inline video::SColor readARGB8(const u8 *data) { video::SColor p(readU32(data)); @@ -219,20 +250,29 @@ inline v3s32 readV3S32(const u8 *data) return p; } -inline v2f readV2F1000(const u8 *data) +inline v3f readV3F1000(const u8 *data) +{ + v3f p; + p.X = readF1000(&data[0]); + p.Y = readF1000(&data[4]); + p.Z = readF1000(&data[8]); + return p; +} + +inline v2f readV2F32(const u8 *data) { v2f p; - p.X = (float)readF1000(&data[0]); - p.Y = (float)readF1000(&data[4]); + p.X = readF32(&data[0]); + p.Y = readF32(&data[4]); return p; } -inline v3f readV3F1000(const u8 *data) +inline v3f readV3F32(const u8 *data) { v3f p; - p.X = (float)readF1000(&data[0]); - p.Y = (float)readF1000(&data[4]); - p.Z = (float)readF1000(&data[8]); + p.X = readF32(&data[0]); + p.Y = readF32(&data[4]); + p.Z = readF32(&data[8]); return p; } @@ -250,7 +290,7 @@ inline void writeS8(u8 *data, s8 i) inline void writeS16(u8 *data, s16 i) { - writeU16(data, (u16)i); + writeU16(data, (u16)i); } inline void writeS32(u8 *data, s32 i) @@ -269,6 +309,23 @@ inline void writeF1000(u8 *data, f32 i) writeS32(data, i * FIXEDPOINT_FACTOR); } +inline void writeF32(u8 *data, f32 i) +{ + switch (g_serialize_f32_type) { + case FLOATTYPE_SYSTEM: { + u32 u; + memcpy(&u, &i, 4); + return writeU32(data, u); + } + case FLOATTYPE_SLOW: + return writeU32(data, f32Tou32Slow(i)); + case FLOATTYPE_UNKNOWN: // First initialization + g_serialize_f32_type = getFloatSerializationType(); + return writeF32(data, i); + } + throw SerializationError("writeF32: Unreachable code"); +} + inline void writeARGB8(u8 *data, video::SColor p) { writeU32(data, p.color); @@ -300,17 +357,24 @@ inline void writeV3S32(u8 *data, v3s32 p) writeS32(&data[8], p.Z); } -inline void writeV2F1000(u8 *data, v2f p) +inline void writeV3F1000(u8 *data, v3f p) { writeF1000(&data[0], p.X); writeF1000(&data[4], p.Y); + writeF1000(&data[8], p.Z); } -inline void writeV3F1000(u8 *data, v3f p) +inline void writeV2F32(u8 *data, v2f p) { - writeF1000(&data[0], p.X); - writeF1000(&data[4], p.Y); - writeF1000(&data[8], p.Z); + writeF32(&data[0], p.X); + writeF32(&data[4], p.Y); +} + +inline void writeV3F32(u8 *data, v3f p) +{ + writeF32(&data[0], p.X); + writeF32(&data[4], p.Y); + writeF32(&data[8], p.Z); } //// @@ -342,12 +406,14 @@ MAKE_STREAM_READ_FXN(s16, S16, 2); MAKE_STREAM_READ_FXN(s32, S32, 4); MAKE_STREAM_READ_FXN(s64, S64, 8); MAKE_STREAM_READ_FXN(f32, F1000, 4); +MAKE_STREAM_READ_FXN(f32, F32, 4); MAKE_STREAM_READ_FXN(v2s16, V2S16, 4); MAKE_STREAM_READ_FXN(v3s16, V3S16, 6); MAKE_STREAM_READ_FXN(v2s32, V2S32, 8); MAKE_STREAM_READ_FXN(v3s32, V3S32, 12); -MAKE_STREAM_READ_FXN(v2f, V2F1000, 8); MAKE_STREAM_READ_FXN(v3f, V3F1000, 12); +MAKE_STREAM_READ_FXN(v2f, V2F32, 8); +MAKE_STREAM_READ_FXN(v3f, V3F32, 12); MAKE_STREAM_READ_FXN(video::SColor, ARGB8, 4); MAKE_STREAM_WRITE_FXN(u8, U8, 1); @@ -359,12 +425,14 @@ MAKE_STREAM_WRITE_FXN(s16, S16, 2); MAKE_STREAM_WRITE_FXN(s32, S32, 4); MAKE_STREAM_WRITE_FXN(s64, S64, 8); MAKE_STREAM_WRITE_FXN(f32, F1000, 4); +MAKE_STREAM_WRITE_FXN(f32, F32, 4); MAKE_STREAM_WRITE_FXN(v2s16, V2S16, 4); MAKE_STREAM_WRITE_FXN(v3s16, V3S16, 6); MAKE_STREAM_WRITE_FXN(v2s32, V2S32, 8); MAKE_STREAM_WRITE_FXN(v3s32, V3S32, 12); -MAKE_STREAM_WRITE_FXN(v2f, V2F1000, 8); MAKE_STREAM_WRITE_FXN(v3f, V3F1000, 12); +MAKE_STREAM_WRITE_FXN(v2f, V2F32, 8); +MAKE_STREAM_WRITE_FXN(v3f, V3F32, 12); MAKE_STREAM_WRITE_FXN(video::SColor, ARGB8, 4); //// @@ -372,22 +440,16 @@ MAKE_STREAM_WRITE_FXN(video::SColor, ARGB8, 4); //// // Creates a string with the length as the first two bytes -std::string serializeString(const std::string &plain); - -// Creates a string with the length as the first two bytes from wide string -std::string serializeWideString(const std::wstring &plain); +std::string serializeString16(const std::string &plain); // Reads a string with the length as the first two bytes -std::string deSerializeString(std::istream &is); - -// Reads a wide string with the length as the first two bytes -std::wstring deSerializeWideString(std::istream &is); +std::string deSerializeString16(std::istream &is); // Creates a string with the length as the first four bytes -std::string serializeLongString(const std::string &plain); +std::string serializeString32(const std::string &plain); // Reads a string with the length as the first four bytes -std::string deSerializeLongString(std::istream &is); +std::string deSerializeString32(std::istream &is); // Creates a string encoded in JSON format (almost equivalent to a C string literal) std::string serializeJsonString(const std::string &plain); @@ -395,251 +457,9 @@ std::string serializeJsonString(const std::string &plain); // Reads a string encoded in JSON format std::string deSerializeJsonString(std::istream &is); -// Creates a string consisting of the hexadecimal representation of `data` -std::string serializeHexString(const std::string &data, bool insert_spaces=false); - -// Creates a string containing comma delimited values of a struct whose layout is -// described by the parameter format -bool serializeStructToString(std::string *out, - std::string format, void *value); - -// Reads a comma delimited string of values into a struct whose layout is -// decribed by the parameter format -bool deSerializeStringToStruct(std::string valstr, - std::string format, void *out, size_t olen); - -//// -//// BufReader -//// - -extern SerializationError eof_ser_err; - -#define MAKE_BUFREADER_GETNOEX_FXN(T, N, S) \ - inline bool get ## N ## NoEx(T *val) \ - { \ - if (pos + S > size) \ - return false; \ - *val = read ## N(data + pos); \ - pos += S; \ - return true; \ - } - -#define MAKE_BUFREADER_GET_FXN(T, N) \ - inline T get ## N() \ - { \ - T val; \ - if (!get ## N ## NoEx(&val)) \ - throw eof_ser_err; \ - return val; \ - } - -class BufReader { -public: - BufReader(const u8 *data_, size_t size_) : - data(data_), - size(size_), - pos(0) - { - } - - MAKE_BUFREADER_GETNOEX_FXN(u8, U8, 1); - MAKE_BUFREADER_GETNOEX_FXN(u16, U16, 2); - MAKE_BUFREADER_GETNOEX_FXN(u32, U32, 4); - MAKE_BUFREADER_GETNOEX_FXN(u64, U64, 8); - MAKE_BUFREADER_GETNOEX_FXN(s8, S8, 1); - MAKE_BUFREADER_GETNOEX_FXN(s16, S16, 2); - MAKE_BUFREADER_GETNOEX_FXN(s32, S32, 4); - MAKE_BUFREADER_GETNOEX_FXN(s64, S64, 8); - MAKE_BUFREADER_GETNOEX_FXN(f32, F1000, 4); - MAKE_BUFREADER_GETNOEX_FXN(v2s16, V2S16, 4); - MAKE_BUFREADER_GETNOEX_FXN(v3s16, V3S16, 6); - MAKE_BUFREADER_GETNOEX_FXN(v2s32, V2S32, 8); - MAKE_BUFREADER_GETNOEX_FXN(v3s32, V3S32, 12); - MAKE_BUFREADER_GETNOEX_FXN(v2f, V2F1000, 8); - MAKE_BUFREADER_GETNOEX_FXN(v3f, V3F1000, 12); - MAKE_BUFREADER_GETNOEX_FXN(video::SColor, ARGB8, 4); - - bool getStringNoEx(std::string *val); - bool getWideStringNoEx(std::wstring *val); - bool getLongStringNoEx(std::string *val); - bool getRawDataNoEx(void *data, size_t len); - - MAKE_BUFREADER_GET_FXN(u8, U8); - MAKE_BUFREADER_GET_FXN(u16, U16); - MAKE_BUFREADER_GET_FXN(u32, U32); - MAKE_BUFREADER_GET_FXN(u64, U64); - MAKE_BUFREADER_GET_FXN(s8, S8); - MAKE_BUFREADER_GET_FXN(s16, S16); - MAKE_BUFREADER_GET_FXN(s32, S32); - MAKE_BUFREADER_GET_FXN(s64, S64); - MAKE_BUFREADER_GET_FXN(f32, F1000); - MAKE_BUFREADER_GET_FXN(v2s16, V2S16); - MAKE_BUFREADER_GET_FXN(v3s16, V3S16); - MAKE_BUFREADER_GET_FXN(v2s32, V2S32); - MAKE_BUFREADER_GET_FXN(v3s32, V3S32); - MAKE_BUFREADER_GET_FXN(v2f, V2F1000); - MAKE_BUFREADER_GET_FXN(v3f, V3F1000); - MAKE_BUFREADER_GET_FXN(video::SColor, ARGB8); - MAKE_BUFREADER_GET_FXN(std::string, String); - MAKE_BUFREADER_GET_FXN(std::wstring, WideString); - MAKE_BUFREADER_GET_FXN(std::string, LongString); - - inline void getRawData(void *val, size_t len) - { - if (!getRawDataNoEx(val, len)) - throw eof_ser_err; - } - - inline size_t remaining() - { - assert(pos <= size); - return size - pos; - } - - const u8 *data; - size_t size; - size_t pos; -}; - -#undef MAKE_BUFREADER_GET_FXN -#undef MAKE_BUFREADER_GETNOEX_FXN - - -//// -//// Vector-based write routines -//// - -inline void putU8(std::vector *dest, u8 val) -{ - dest->push_back((val >> 0) & 0xFF); -} - -inline void putU16(std::vector *dest, u16 val) -{ - dest->push_back((val >> 8) & 0xFF); - dest->push_back((val >> 0) & 0xFF); -} - -inline void putU32(std::vector *dest, u32 val) -{ - dest->push_back((val >> 24) & 0xFF); - dest->push_back((val >> 16) & 0xFF); - dest->push_back((val >> 8) & 0xFF); - dest->push_back((val >> 0) & 0xFF); -} - -inline void putU64(std::vector *dest, u64 val) -{ - dest->push_back((val >> 56) & 0xFF); - dest->push_back((val >> 48) & 0xFF); - dest->push_back((val >> 40) & 0xFF); - dest->push_back((val >> 32) & 0xFF); - dest->push_back((val >> 24) & 0xFF); - dest->push_back((val >> 16) & 0xFF); - dest->push_back((val >> 8) & 0xFF); - dest->push_back((val >> 0) & 0xFF); -} - -inline void putS8(std::vector *dest, s8 val) -{ - putU8(dest, val); -} - -inline void putS16(std::vector *dest, s16 val) -{ - putU16(dest, val); -} - -inline void putS32(std::vector *dest, s32 val) -{ - putU32(dest, val); -} - -inline void putS64(std::vector *dest, s64 val) -{ - putU64(dest, val); -} - -inline void putF1000(std::vector *dest, f32 val) -{ - putS32(dest, val * FIXEDPOINT_FACTOR); -} - -inline void putV2S16(std::vector *dest, v2s16 val) -{ - putS16(dest, val.X); - putS16(dest, val.Y); -} - -inline void putV3S16(std::vector *dest, v3s16 val) -{ - putS16(dest, val.X); - putS16(dest, val.Y); - putS16(dest, val.Z); -} - -inline void putV2S32(std::vector *dest, v2s32 val) -{ - putS32(dest, val.X); - putS32(dest, val.Y); -} +// If the string contains spaces, quotes or control characters, encodes as JSON. +// Else returns the string unmodified. +std::string serializeJsonStringIfNeeded(const std::string &s); -inline void putV3S32(std::vector *dest, v3s32 val) -{ - putS32(dest, val.X); - putS32(dest, val.Y); - putS32(dest, val.Z); -} - -inline void putV2F1000(std::vector *dest, v2f val) -{ - putF1000(dest, val.X); - putF1000(dest, val.Y); -} - -inline void putV3F1000(std::vector *dest, v3f val) -{ - putF1000(dest, val.X); - putF1000(dest, val.Y); - putF1000(dest, val.Z); -} - -inline void putARGB8(std::vector *dest, video::SColor val) -{ - putU32(dest, val.color); -} - -inline void putString(std::vector *dest, const std::string &val) -{ - if (val.size() > STRING_MAX_LEN) - throw SerializationError("String too long"); - - putU16(dest, val.size()); - dest->insert(dest->end(), val.begin(), val.end()); -} - -inline void putWideString(std::vector *dest, const std::wstring &val) -{ - if (val.size() > WIDE_STRING_MAX_LEN) - throw SerializationError("String too long"); - - putU16(dest, val.size()); - for (size_t i = 0; i != val.size(); i++) - putU16(dest, val[i]); -} - -inline void putLongString(std::vector *dest, const std::string &val) -{ - if (val.size() > LONG_STRING_MAX_LEN) - throw SerializationError("String too long"); - - putU32(dest, val.size()); - dest->insert(dest->end(), val.begin(), val.end()); -} - -inline void putRawData(std::vector *dest, const void *src, size_t len) -{ - dest->insert(dest->end(), (u8 *)src, (u8 *)src + len); -} - -#endif +// Parses a string serialized by serializeJsonStringIfNeeded. +std::string deSerializeJsonStringIfNeeded(std::istream &is);