diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b1fd26247..ec6c7fbac 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,6 +2,7 @@ project(minetest) cmake_minimum_required( VERSION 2.6 ) INCLUDE(CheckCSourceRuns) +INCLUDE(CheckIncludeFiles) # Set some random things default to not being visible in the GUI mark_as_advanced(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH) @@ -313,6 +314,8 @@ if(ENABLE_REDIS) endif(REDIS_LIBRARY AND REDIS_INCLUDE_DIR) endif(ENABLE_REDIS) +CHECK_INCLUDE_FILES(endian.h HAVE_ENDIAN_H) + configure_file( "${PROJECT_SOURCE_DIR}/cmake_config.h.in" "${PROJECT_BINARY_DIR}/cmake_config.h" diff --git a/src/cmake_config.h.in b/src/cmake_config.h.in index 64a4c002b..e111a650d 100644 --- a/src/cmake_config.h.in +++ b/src/cmake_config.h.in @@ -20,6 +20,7 @@ #define CMAKE_VERSION_PATCH @VERSION_PATCH@ #define CMAKE_VERSION_PATCH_ORIG @VERSION_PATCH_ORIG@ #define CMAKE_VERSION_EXTRA_STRING "@VERSION_EXTRA@" +#define CMAKE_HAVE_ENDIAN_H @HAVE_ENDIAN_H@ #ifdef NDEBUG #define CMAKE_BUILD_TYPE "Release" diff --git a/src/config.h b/src/config.h index f1aef03aa..b07aa5d22 100644 --- a/src/config.h +++ b/src/config.h @@ -36,6 +36,8 @@ #define USE_REDIS 0 #endif +#define HAVE_ENDIAN_H 0 + #ifdef USE_CMAKE_CONFIG_H #include "cmake_config.h" #undef PROJECT_NAME @@ -72,6 +74,8 @@ #define PRODUCT_VERSION_STRING CMAKE_PRODUCT_VERSION_STRING #undef VERSION_EXTRA_STRING #define VERSION_EXTRA_STRING CMAKE_VERSION_EXTRA_STRING + #undef HAVE_ENDIAN_H + #define HAVE_ENDIAN_H CMAKE_HAVE_ENDIAN_H #endif #ifdef __ANDROID__ diff --git a/src/nodemetadata.cpp b/src/nodemetadata.cpp index 4cdd61767..0631d974a 100644 --- a/src/nodemetadata.cpp +++ b/src/nodemetadata.cpp @@ -130,12 +130,12 @@ void NodeMetadataList::deSerialize(std::istream &is, IGameDef *gamedef) { u16 p16 = readU16(is); - v3s16 p(0,0,0); - p.Z += p16 / MAP_BLOCKSIZE / MAP_BLOCKSIZE; - p16 -= p.Z * MAP_BLOCKSIZE * MAP_BLOCKSIZE; - p.Y += p16 / MAP_BLOCKSIZE; - p16 -= p.Y * MAP_BLOCKSIZE; - p.X += p16; + v3s16 p; + p.Z = p16 / MAP_BLOCKSIZE / MAP_BLOCKSIZE; + p16 &= MAP_BLOCKSIZE * MAP_BLOCKSIZE - 1; + p.Y = p16 / MAP_BLOCKSIZE; + p16 &= MAP_BLOCKSIZE - 1; + p.X = p16; if(m_data.find(p) != m_data.end()) { diff --git a/src/nodetimer.cpp b/src/nodetimer.cpp index 5fc652bb7..d4971c873 100644 --- a/src/nodetimer.cpp +++ b/src/nodetimer.cpp @@ -96,12 +96,12 @@ void NodeTimerList::deSerialize(std::istream &is, u8 map_format_version) { u16 p16 = readU16(is); - v3s16 p(0,0,0); - p.Z += p16 / MAP_BLOCKSIZE / MAP_BLOCKSIZE; - p16 -= p.Z * MAP_BLOCKSIZE * MAP_BLOCKSIZE; - p.Y += p16 / MAP_BLOCKSIZE; - p16 -= p.Y * MAP_BLOCKSIZE; - p.X += p16; + v3s16 p; + p.Z = p16 / MAP_BLOCKSIZE / MAP_BLOCKSIZE; + p16 &= MAP_BLOCKSIZE * MAP_BLOCKSIZE - 1; + p.Y = p16 / MAP_BLOCKSIZE; + p16 &= MAP_BLOCKSIZE - 1; + p.X = p16; NodeTimer t; t.deSerialize(is); diff --git a/src/staticobject.cpp b/src/staticobject.cpp index 973257fcf..16d98605b 100644 --- a/src/staticobject.cpp +++ b/src/staticobject.cpp @@ -22,42 +22,31 @@ with this program; if not, write to the Free Software Foundation, Inc., void StaticObject::serialize(std::ostream &os) { - char buf[12]; // type - buf[0] = type; - os.write(buf, 1); + writeU8(os, type); // pos - writeV3S32((u8*)buf, v3s32(pos.X*1000,pos.Y*1000,pos.Z*1000)); - os.write(buf, 12); + writeV3F1000(os, pos); // data os<::iterator i = m_stored.begin(); i != m_stored.end(); ++i) @@ -75,13 +64,10 @@ void StaticObjectList::serialize(std::ostream &os) } void StaticObjectList::deSerialize(std::istream &is) { - char buf[12]; // version - is.read(buf, 1); - u8 version = buf[0]; + u8 version = readU8(is); // count - is.read(buf, 2); - u16 count = readU16((u8*)buf); + u16 count = readU16(is); for(u16 i=0; i buf2(s_size); is.read(&buf2[0], s_size); - std::string s; s.reserve(s_size); s.append(&buf2[0], s_size); return s; @@ -86,9 +86,9 @@ std::wstring deSerializeWideString(std::istream &is) if(is.gcount() != 2) throw SerializationError("deSerializeString: size not read"); u16 s_size = readU16((u8*)buf); - if(s_size == 0) - return L""; std::wstring s; + if(s_size == 0) + return s; s.reserve(s_size); for(u32 i=0; i buf2(s_size); is.read(&buf2[0], s_size); - std::string s; s.reserve(s_size); s.append(&buf2[0], s_size); return s; diff --git a/src/util/serialize.h b/src/util/serialize.h index 3f9925287..79907799f 100644 --- a/src/util/serialize.h +++ b/src/util/serialize.h @@ -21,9 +21,63 @@ with this program; if not, write to the Free Software Foundation, Inc., #define UTIL_SERIALIZE_HEADER #include "../irrlichttypes_bloated.h" +#include "config.h" +#if HAVE_ENDIAN_H +#include +#include // for memcpy +#endif #include #include +#define FIXEDPOINT_FACTOR 1000.0f +#define FIXEDPOINT_INVFACTOR (1.0f/FIXEDPOINT_FACTOR) + +#if HAVE_ENDIAN_H +// use machine native byte swapping routines +// Note: memcpy below is optimized out by modern compilers + +inline void writeU64(u8* data, u64 i) +{ + u64 val = htobe64(i); + memcpy(data, &val, 8); +} + +inline void writeU32(u8* data, u32 i) +{ + u32 val = htobe32(i); + memcpy(data, &val, 4); +} + +inline void writeU16(u8* data, u16 i) +{ + u16 val = htobe16(i); + memcpy(data, &val, 2); +} + +inline u64 readU64(const u8* data) +{ + u64 val; + memcpy(&val, data, 8); + return be64toh(val); +} + +inline u32 readU32(const u8* data) +{ + u32 val; + memcpy(&val, data, 4); + return be32toh(val); +} + +inline u16 readU16(const u8* data) +{ + u16 val; + memcpy(&val, data, 2); + return be16toh(val); +} + +#else +// generic byte-swapping implementation + inline void writeU64(u8 *data, u64 i) { data[0] = ((i>>56)&0xff); @@ -50,11 +104,6 @@ inline void writeU16(u8 *data, u16 i) data[1] = ((i>> 0)&0xff); } -inline void writeU8(u8 *data, u8 i) -{ - data[0] = ((i>> 0)&0xff); -} - inline u64 readU64(const u8 *data) { return ((u64)data[0]<<56) | ((u64)data[1]<<48) @@ -73,6 +122,13 @@ inline u16 readU16(const u8 *data) return (data[0]<<8) | (data[1]<<0); } +#endif + +inline void writeU8(u8 *data, u8 i) +{ + data[0] = ((i>> 0)&0xff); +} + inline u8 readU8(const u8 *data) { return (data[0]<<0); @@ -100,10 +156,10 @@ inline s8 readS8(const u8 *data){ } inline void writeF1000(u8 *data, f32 i){ - writeS32(data, i*1000); + writeS32(data, i*FIXEDPOINT_FACTOR); } inline f32 readF1000(const u8 *data){ - return (f32)readS32(data)/1000.; + return (f32)readS32(data)*FIXEDPOINT_INVFACTOR; } inline void writeV3S32(u8 *data, v3s32 p) @@ -195,20 +251,12 @@ inline v3s16 readV3S16(const u8 *data) inline void writeARGB8(u8 *data, video::SColor p) { - writeU8(&data[0], p.getAlpha()); - writeU8(&data[1], p.getRed()); - writeU8(&data[2], p.getGreen()); - writeU8(&data[3], p.getBlue()); + writeU32(data, p.color); } inline video::SColor readARGB8(const u8 *data) { - video::SColor p( - readU8(&data[0]), - readU8(&data[1]), - readU8(&data[2]), - readU8(&data[3]) - ); + video::SColor p(readU32(data)); return p; } @@ -218,7 +266,7 @@ inline video::SColor readARGB8(const u8 *data) inline void writeU8(std::ostream &os, u8 p) { - char buf[1] = {0}; + char buf[1]; writeU8((u8*)buf, p); os.write(buf, 1); } @@ -231,7 +279,7 @@ inline u8 readU8(std::istream &is) inline void writeU16(std::ostream &os, u16 p) { - char buf[2] = {0}; + char buf[2]; writeU16((u8*)buf, p); os.write(buf, 2); } @@ -244,7 +292,7 @@ inline u16 readU16(std::istream &is) inline void writeU32(std::ostream &os, u32 p) { - char buf[4] = {0}; + char buf[4]; writeU32((u8*)buf, p); os.write(buf, 4); } @@ -257,46 +305,34 @@ inline u32 readU32(std::istream &is) inline void writeS32(std::ostream &os, s32 p) { - char buf[4] = {0}; - writeS32((u8*)buf, p); - os.write(buf, 4); + writeU32(os, (u32) p); } inline s32 readS32(std::istream &is) { - char buf[4] = {0}; - is.read(buf, 4); - return readS32((u8*)buf); + return (s32)readU32(is); } inline void writeS16(std::ostream &os, s16 p) { - char buf[2] = {0}; - writeS16((u8*)buf, p); - os.write(buf, 2); + writeU16(os, (u16) p); } inline s16 readS16(std::istream &is) { - char buf[2] = {0}; - is.read(buf, 2); - return readS16((u8*)buf); + return (s16)readU16(is); } inline void writeS8(std::ostream &os, s8 p) { - char buf[1] = {0}; - writeS8((u8*)buf, p); - os.write(buf, 1); + writeU8(os, (u8) p); } inline s8 readS8(std::istream &is) { - char buf[1] = {0}; - is.read(buf, 1); - return readS8((u8*)buf); + return (s8)readU8(is); } inline void writeF1000(std::ostream &os, f32 p) { - char buf[4] = {0}; + char buf[4]; writeF1000((u8*)buf, p); os.write(buf, 4); } @@ -322,7 +358,7 @@ inline v3f readV3F1000(std::istream &is) inline void writeV2F1000(std::ostream &os, v2f p) { - char buf[8] = {0}; + char buf[8]; writeV2F1000((u8*)buf, p); os.write(buf, 8); } @@ -335,7 +371,7 @@ inline v2f readV2F1000(std::istream &is) inline void writeV2S16(std::ostream &os, v2s16 p) { - char buf[4] = {0}; + char buf[4]; writeV2S16((u8*)buf, p); os.write(buf, 4); } @@ -348,7 +384,7 @@ inline v2s16 readV2S16(std::istream &is) inline void writeV2S32(std::ostream &os, v2s32 p) { - char buf[8] = {0}; + char buf[8]; writeV2S32((u8*)buf, p); os.write(buf, 8); } @@ -361,7 +397,7 @@ inline v2s32 readV2S32(std::istream &is) inline void writeV3S16(std::ostream &os, v3s16 p) { - char buf[6] = {0}; + char buf[6]; writeV3S16((u8*)buf, p); os.write(buf, 6); } @@ -374,7 +410,7 @@ inline v3s16 readV3S16(std::istream &is) inline void writeARGB8(std::ostream &os, video::SColor p) { - char buf[4] = {0}; + char buf[4]; writeARGB8((u8*)buf, p); os.write(buf, 4); }