Core/Serialization: Add correct endianness handling

Core/File: Remove endianness handling


Former-commit-id: 6f7bba52057f36c507a024f7a7ea873658a3cfd3
This commit is contained in:
Lynix 2015-11-18 18:49:38 +01:00
parent be01b6f3b4
commit 3fb9e57360
12 changed files with 51 additions and 83 deletions

View File

@ -29,15 +29,15 @@ namespace Nz
template<typename T> template<typename T>
struct TypeTag {}; struct TypeTag {};
inline bool Serialize(OutputStream* output, bool value); inline bool Serialize(OutputStream* output, bool value, Endianness dataEndianness);
template<typename T> template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value, bool> Serialize(OutputStream* output, T value); std::enable_if_t<std::is_arithmetic<T>::value, bool> Serialize(OutputStream* output, T value, Endianness dataEndianness);
inline bool Unserialize(InputStream* input, bool* value); inline bool Unserialize(InputStream* input, bool* value, Endianness dataEndianness);
template<typename T> template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value, bool> Unserialize(InputStream* input, T* value); std::enable_if_t<std::is_arithmetic<T>::value, bool> Unserialize(InputStream* input, T* value, Endianness dataEndianness);
} }
#include <Nazara/Core/Algorithm.inl> #include <Nazara/Core/Algorithm.inl>

View File

@ -77,21 +77,25 @@ namespace Nz
seed = static_cast<std::size_t>(b * kMul); seed = static_cast<std::size_t>(b * kMul);
} }
inline bool Serialize(OutputStream* output, bool value) inline bool Serialize(OutputStream* output, bool value, Endianness dataEndianness)
{ {
NazaraAssert(output, "Invalid stream");
NazaraUnused(dataEndianness);
///TODO: Handle bits writing (Serializing 8 bits should only use one byte)
UInt8 buffer = (value) ? 1 : 0; UInt8 buffer = (value) ? 1 : 0;
return output->Write(&buffer, 1) == 1; return output->Write(&buffer, 1) == 1;
} }
template<typename T> template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value, bool> Serialize(OutputStream* output, T value) std::enable_if_t<std::is_arithmetic<T>::value, bool> Serialize(OutputStream* output, T value, Endianness dataEndianness)
{ {
NazaraAssert(output, "Invalid stream");
if (output->Write(&value, sizeof(T)) == sizeof(T)) if (output->Write(&value, sizeof(T)) == sizeof(T))
{ {
// Write down everything as little endian if (dataEndianness != Endianness_Unknown && dataEndianness != GetPlatformEndianness())
#if NAZARA_BIG_ENDIAN SwapBytes(&value, sizeof(T));
SwapBytes(&value, sizeof(T));
#endif
return true; return true;
} }
@ -99,9 +103,11 @@ namespace Nz
return false; return false;
} }
inline bool Unserialize(InputStream* input, bool* value) inline bool Unserialize(InputStream* input, bool* value, Endianness dataEndianness)
{ {
NazaraAssert(value, "Invalid pointer"); NazaraAssert(input, "Invalid stream");
NazaraAssert(value, "Invalid data pointer");
NazaraUnused(dataEndianness);
UInt8 buffer; UInt8 buffer;
if (input->Read(&buffer, 1) == 1) if (input->Read(&buffer, 1) == 1)
@ -114,16 +120,15 @@ namespace Nz
} }
template<typename T> template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value, bool> Unserialize(InputStream* input, T* value) std::enable_if_t<std::is_arithmetic<T>::value, bool> Unserialize(InputStream* input, T* value, Endianness dataEndianness)
{ {
NazaraAssert(value, "Invalid pointer"); NazaraAssert(input, "Invalid stream");
NazaraAssert(value, "Invalid data pointer");
if (input->Read(value, sizeof(T)) == sizeof(T)) if (input->Read(value, sizeof(T)) == sizeof(T))
{ {
// Write down everything as little endian if (dataEndianness != Endianness_Unknown && dataEndianness != GetPlatformEndianness())
#if NAZARA_BIG_ENDIAN SwapBytes(&value, sizeof(T));
SwapBytes(&value, sizeof(T));
#endif
return true; return true;
} }

View File

@ -27,7 +27,7 @@
namespace Nz namespace Nz
{ {
inline Endianness GetPlatformEndianness(); inline constexpr Endianness GetPlatformEndianness();
inline void SwapBytes(void* buffer, unsigned int size); inline void SwapBytes(void* buffer, unsigned int size);
} }

View File

@ -7,7 +7,7 @@
namespace Nz namespace Nz
{ {
inline Endianness GetPlatformEndianness() inline constexpr Endianness GetPlatformEndianness()
{ {
#if defined(NAZARA_BIG_ENDIAN) #if defined(NAZARA_BIG_ENDIAN)
return Endianness_BigEndian; return Endianness_BigEndian;

View File

@ -64,7 +64,6 @@ namespace Nz
bool Open(const String& filePath, unsigned int openMode = OpenMode_Current); bool Open(const String& filePath, unsigned int openMode = OpenMode_Current);
std::size_t Read(void* buffer, std::size_t size) override; std::size_t Read(void* buffer, std::size_t size) override;
std::size_t Read(void* buffer, std::size_t typeSize, unsigned int count);
bool Rename(const String& newFilePath); bool Rename(const String& newFilePath);
bool SetCursorPos(CursorPosition pos, Int64 offset = 0); bool SetCursorPos(CursorPosition pos, Int64 offset = 0);
@ -74,7 +73,6 @@ namespace Nz
using OutputStream::Write; using OutputStream::Write;
std::size_t Write(const void* buffer, std::size_t size) override; std::size_t Write(const void* buffer, std::size_t size) override;
std::size_t Write(const void* buffer, std::size_t typeSize, unsigned int count);
File& operator=(const String& filePath); File& operator=(const String& filePath);
File& operator=(const File&) = delete; File& operator=(const File&) = delete;
@ -99,7 +97,6 @@ namespace Nz
private: private:
NazaraMutexAttrib(m_mutex, mutable) NazaraMutexAttrib(m_mutex, mutable)
Endianness m_endianness;
String m_filePath; String m_filePath;
FileImpl* m_impl; FileImpl* m_impl;
}; };

View File

@ -14,7 +14,7 @@ namespace Nz
template<typename T> template<typename T>
InputStream& InputStream::operator>>(T& value) InputStream& InputStream::operator>>(T& value)
{ {
if (!Unserialize(this, &value)) if (!Unserialize(this, &value, m_dataEndianness))
NazaraError("Failed to unserialize value"); NazaraError("Failed to unserialize value");
return *this; return *this;

View File

@ -14,7 +14,7 @@ namespace Nz
template<typename T> template<typename T>
OutputStream& OutputStream::operator<<(const T& value) OutputStream& OutputStream::operator<<(const T& value)
{ {
if (!Serialize(this, value)) if (!Serialize(this, value, m_dataEndianness))
NazaraError("Failed to serialize value"); NazaraError("Failed to serialize value");
return *this; return *this;

View File

@ -8,6 +8,7 @@
#define NAZARA_STREAM_HPP #define NAZARA_STREAM_HPP
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Endianness.hpp>
#include <Nazara/Core/Enums.hpp> #include <Nazara/Core/Enums.hpp>
namespace Nz namespace Nz
@ -24,6 +25,7 @@ namespace Nz
virtual UInt64 GetCursorPos() const = 0; virtual UInt64 GetCursorPos() const = 0;
virtual String GetDirectory() const; virtual String GetDirectory() const;
virtual String GetPath() const; virtual String GetPath() const;
inline Endianness GetDataEndianness() const;
inline UInt32 GetOpenMode() const; inline UInt32 GetOpenMode() const;
inline UInt32 GetStreamOptions() const; inline UInt32 GetStreamOptions() const;
@ -31,14 +33,16 @@ namespace Nz
inline bool IsWritable() const; inline bool IsWritable() const;
virtual bool SetCursorPos(UInt64 offset) = 0; virtual bool SetCursorPos(UInt64 offset) = 0;
void SetStreamOptions(UInt32 options); inline void SetDataEndianness(Endianness endiannes);
inline void SetStreamOptions(UInt32 options);
Stream& operator=(const Stream&) = default; Stream& operator=(const Stream&) = default;
Stream& operator=(Stream&&) = default; Stream& operator=(Stream&&) = default;
protected: protected:
inline Stream(UInt32 openMode); inline Stream(UInt32 openMode);
Endianness m_dataEndianness;
UInt32 m_openMode; UInt32 m_openMode;
UInt32 m_streamOptions; UInt32 m_streamOptions;
}; };

View File

@ -5,11 +5,17 @@
namespace Nz namespace Nz
{ {
inline Stream::Stream(UInt32 openMode) : inline Stream::Stream(UInt32 openMode) :
m_dataEndianness(Endianness_Unknown),
m_openMode(openMode), m_openMode(openMode),
m_streamOptions(0) m_streamOptions(0)
{ {
} }
inline Endianness Stream::GetDataEndianness() const
{
return m_dataEndianness;
}
inline UInt32 Stream::GetOpenMode() const inline UInt32 Stream::GetOpenMode() const
{ {
return m_openMode; return m_openMode;
@ -30,6 +36,11 @@ namespace Nz
return m_openMode & OpenMode_ReadWrite || m_openMode & OpenMode_WriteOnly; return m_openMode & OpenMode_ReadWrite || m_openMode & OpenMode_WriteOnly;
} }
inline void Stream::SetDataEndianness(Endianness endiannes)
{
m_dataEndianness = endiannes;
}
inline void Stream::SetStreamOptions(UInt32 options) inline void Stream::SetStreamOptions(UInt32 options)
{ {
m_streamOptions = options; m_streamOptions = options;

View File

@ -8,6 +8,7 @@
#define NAZARA_STRING_HPP #define NAZARA_STRING_HPP
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Endianness.hpp>
#include <atomic> #include <atomic>
#include <iosfwd> #include <iosfwd>
#include <memory> #include <memory>
@ -326,8 +327,8 @@ namespace Nz
}; };
inline bool HashAppend(AbstractHash* hash, const String& string); inline bool HashAppend(AbstractHash* hash, const String& string);
NAZARA_CORE_API bool Serialize(OutputStream* output, const String& string); NAZARA_CORE_API bool Serialize(OutputStream* output, const String& string, Endianness dataEndianness);
NAZARA_CORE_API bool Unserialize(InputStream* input, String* string); NAZARA_CORE_API bool Unserialize(InputStream* input, String* string, Endianness dataEndianness);
} }
namespace std namespace std

View File

@ -32,7 +32,6 @@ namespace Nz
{ {
File::File() : File::File() :
Stream(OpenMode_Current), Stream(OpenMode_Current),
m_endianness(Endianness_Unknown),
m_impl(nullptr) m_impl(nullptr)
{ {
} }
@ -53,7 +52,6 @@ namespace Nz
Stream(std::move(file)), Stream(std::move(file)),
InputStream(std::move(file)), InputStream(std::move(file)),
OutputStream(std::move(file)), OutputStream(std::move(file)),
m_endianness(file.m_endianness),
m_filePath(std::move(file.m_filePath)), m_filePath(std::move(file.m_filePath)),
m_impl(file.m_impl) m_impl(file.m_impl)
{ {
@ -219,22 +217,6 @@ namespace Nz
} }
} }
std::size_t File::Read(void* buffer, std::size_t typeSize, unsigned int count)
{
std::size_t byteRead = Read(buffer, typeSize*count);
if (byteRead == 0)
return 0;
if (buffer && typeSize != 1 && m_endianness != Endianness_Unknown && m_endianness != GetPlatformEndianness())
{
unsigned int typeCount = byteRead/typeSize;
for (unsigned int i = 0; i < typeCount; ++i)
SwapBytes(reinterpret_cast<UInt8*>(buffer) + i*typeSize, typeSize);
}
return byteRead;
}
bool File::Rename(const String& newFilePath) bool File::Rename(const String& newFilePath)
{ {
NazaraLock(m_mutex) NazaraLock(m_mutex)
@ -311,13 +293,6 @@ namespace Nz
return m_impl->SetCursorPos(CursorPosition_AtBegin, offset); return m_impl->SetCursorPos(CursorPosition_AtBegin, offset);
} }
void File::SetEndianness(Endianness endianness)
{
NazaraLock(m_mutex)
m_endianness = endianness;
}
bool File::SetFile(const String& filePath) bool File::SetFile(const String& filePath)
{ {
NazaraLock(m_mutex) NazaraLock(m_mutex)
@ -359,29 +334,6 @@ namespace Nz
return m_impl->Write(buffer, size); return m_impl->Write(buffer, size);
} }
std::size_t File::Write(const void* buffer, std::size_t typeSize, unsigned int count)
{
if (count == 0 || typeSize == 0)
return 0;
NazaraAssert(buffer, "Invalid buffer");
NazaraLock(m_mutex)
if (m_endianness != Endianness_Unknown && m_endianness != GetPlatformEndianness() && typeSize != 1)
{
std::unique_ptr<char[]> buf(new char[count*typeSize]);
std::memcpy(buf.get(), buffer, count*typeSize);
for (unsigned int i = 0; i < count; ++i)
SwapBytes(&buf[i*typeSize], typeSize);
return Write(buf.get(), count*typeSize);
}
else
return Write(buffer, count*typeSize);
}
File& File::operator=(const String& filePath) File& File::operator=(const String& filePath)
{ {
SetFile(filePath); SetFile(filePath);
@ -393,10 +345,8 @@ namespace Nz
{ {
NazaraLock(m_mutex) NazaraLock(m_mutex)
std::swap(m_endianness, file.m_endianness);
std::swap(m_filePath, file.m_filePath); std::swap(m_filePath, file.m_filePath);
std::swap(m_impl, file.m_impl); std::swap(m_impl, file.m_impl);
std::swap(m_openMode, file.m_openMode);
return *this; return *this;
} }

View File

@ -4209,19 +4209,19 @@ namespace Nz
return emptyString; return emptyString;
} }
bool Serialize(OutputStream* output, const String& string) bool Serialize(OutputStream* output, const String& string, Endianness dataEndianness)
{ {
if (!Serialize<UInt32>(output, string.GetSize())) if (!Serialize<UInt32>(output, string.GetSize(), dataEndianness))
return false; return false;
output->Write(string.GetConstBuffer(), string.GetSize()); output->Write(string.GetConstBuffer(), string.GetSize());
return true; return true;
} }
bool Unserialize(InputStream* input, String* string) bool Unserialize(InputStream* input, String* string, Endianness dataEndianness)
{ {
UInt32 size; UInt32 size;
if (!Unserialize(input, &size)) if (!Unserialize(input, &size, dataEndianness))
return false; return false;
string->Resize(size); string->Resize(size);