Here are several files from the project I'm working on which I use to implement serialization of objects. So, what's in this post:
1. IrrCustomTypes.h - typedef's irr::wchar, also I use String, Char, STR, CHR so I can easily switch to irr::8/irr::core::stringc whenever I want
2. Stream.h/.cpp - implementation of infinite reading/writing stream. Note that you have to write something to Stream before you read from it.
3. IrrStreaming.h/.cpp - implementation of (de)serialization of basic Irrlicht types based on Stream. This is also an example of usage of Stream.
Hope you find this useful
Code: Select all
CStream s;
// Serialization
String str(STR("Test"));
s << str;
// Deserialization:
String str2;
s >> str2;
// str2 is now "Test"
Code: Select all
/*
IrrCustomTypes.h
Custom Irrlicht-style types
*/
#ifndef IrrCustomTypes_h
#define IrrCustomTypes_h
#include <Irrlicht.h>
namespace irr
{
typedef wchar_t wchar;
}
typedef irr::core::stringw String;
typedef irr::wchar Char;
#define STR(S) L##S
#define CHR(C) L##C
#endif // IrrCustomTypes_h
Code: Select all
/*
Stream.h
*/
#ifndef Stream_h
#define Stream_h
#include <Irrlicht.h>
//! I/O stream, infinite read/write, without seeking
class CStream
{
private:
//! Stream buffer
irr::u8* Buffer;
//! Stream buffer size
irr::u32 BufferSize;
//! Writing position
irr::u32 WritePos;
//! Reading position
irr::u32 ReadPos;
//! Can stream be written to?
bool Writable;
public:
//! Constructor
CStream();
//! Consturctor for read-only stream
CStream(void* buffer, irr::u32 bufferSize);
//! Pointer to readable area
inline void* GetReadPtr()
{
return &Buffer[ReadPos];
}
//! Number of bytes which can be read
inline irr::u32 GetReadSize()
{
return WritePos - ReadPos;
}
//! Pointer to writable area
inline void* GetWritePtr()
{
return &Buffer[WritePos];
}
//! Ensures that spacified number of bytes can be written to GetWritePtr()
void EnsureWriteSize(irr::u32 minWriteSize);
//! Advance read position by specified number of bytes
void AdvanceReadPos(irr::u32 delta);
//! Advance write position by specified number of bytes
void AdvanceWritePos(irr::u32 delta);
//! General writing function, buffer can be NULL (skipping)
irr::u32 Write(void *buffer, irr::u32 size);
//! General reading function, buffer can be NULL (skipping)
irr::u32 Read(void *buffer, irr::u32 size);
//! Copies data from another stream to this
irr::u32 Copy(CStream &source, irr::u32 size);
};
// Serialization declaration
#define DeclareSerialization_(T, REF) \
CStream& operator << (CStream& stream, T (REF obj));
#define DeclareSerialization(T) DeclareSerialization_(T,)
#define DeclareSerializationRef(T) DeclareSerialization_(T, &)
#define DeclareSerializationPtr(T) DeclareSerialization_(T, *)
// Serialization implementation
#define ImplementSerialization_(T, REF) \
CStream& operator << (CStream& stream, T (REF obj))
#define ImplementSerialization(T) ImplementSerialization_(T,)
#define ImplementSerializationRef(T) ImplementSerialization_(T, &)
#define ImplementSerializationPtr(T) ImplementSerialization_(T, *)
// Deserialization declaration
#define DeclareDeserialization_(T, REF) \
CStream& operator >> (CStream& stream, T (REF obj));
#define DeclareDeserialization(T) DeclareDeserialization_(T,)
#define DeclareDeserializationRef(T) DeclareDeserialization_(T, &)
#define DeclareDeserializationPtr(T) DeclareDeserialization_(T, *)
// Deserialization implementation
#define ImplementDeserialization_(T, REF) \
CStream& operator >> (CStream& stream, T (REF obj))
#define ImplementDeserialization(T) ImplementDeserialization_(T,)
#define ImplementDeserializationRef(T) ImplementDeserialization_(T, &)
#define ImplementDeserializationPtr(T) ImplementDeserialization_(T, *)
#endif // Stream_h
Code: Select all
/*
Stream.cpp
*/
#include "Stream.h"
const irr::u32 MaxEmptyBufferSize = 1024;
//! Constructor
CStream::CStream() :
Buffer(0),
BufferSize(0),
WritePos(0),
ReadPos(0),
Writable(true)
{
}
//! Consturctor for read-only stream
CStream::CStream(void* buffer, irr::u32 bufferSize) :
Buffer((irr::u8*)buffer),
BufferSize(bufferSize),
WritePos(bufferSize),
ReadPos(0),
Writable(false)
{
}
//! Ensures that spacified number of bytes can be written to GetWritePtr()
void CStream::EnsureWriteSize(irr::u32 minWriteSize)
{
if (!Writable)
return;
irr::u32 lastPos = WritePos + minWriteSize;
if (lastPos > BufferSize)
{
if (BufferSize == 0)
BufferSize = 16;
while (lastPos > BufferSize)
BufferSize *= 4;
irr::u8* oldBuffer = Buffer;
Buffer = new irr::u8[BufferSize];
if (oldBuffer)
{
memcpy(&Buffer[ReadPos], &oldBuffer[ReadPos], WritePos - ReadPos);
delete oldBuffer;
}
}
}
//! Advance read position by specified number of bytes
void CStream::AdvanceReadPos(irr::u32 delta)
{
ReadPos += delta;
if (ReadPos > WritePos)
ReadPos = WritePos;
if ((ReadPos == WritePos) || ((ReadPos < WritePos) && (ReadPos >= MaxEmptyBufferSize)))
{
irr::u32 writtenSize = WritePos - ReadPos;
if (writtenSize > 0)
memcpy(&Buffer[0], &Buffer[ReadPos], writtenSize);
ReadPos = 0;
WritePos = writtenSize;
}
}
//! Advance write position by specified number of bytes
void CStream::AdvanceWritePos(irr::u32 delta)
{
if (!Writable)
return;
WritePos += delta;
/*
if ((WritePos == ReadPos) || ((WritePos < ReadPos) && (WritePos >= MaxEmptyBufferSize)))
{
irr::u32 bufferSize = ReadPos - WritePos;
if (bufferSize > 0)
memcpy(&Buffer[0], &Buffer[WritePos], bufferSize);
WritePos = 0;
ReadPos = bufferSize;
}
*/
}
//! General writing function
irr::u32 CStream::Write(void *buffer, irr::u32 size)
{
if (!Writable)
return 0;
EnsureWriteSize(size);
memcpy(&Buffer[WritePos], buffer, size);
AdvanceWritePos(size);
return size;
}
//! General reading function
irr::u32 CStream::Read(void *buffer, irr::u32 size)
{
irr::u32 readSize = GetReadSize();
if (readSize > size)
readSize = size;
memcpy(buffer, &Buffer[ReadPos], readSize);
AdvanceReadPos(readSize);
return readSize;
}
//! Copies data from another stream to this
irr::u32 CStream::Copy(CStream &source, irr::u32 size)
{
if (!Writable)
return 0;
EnsureWriteSize(size);
return Read(source.GetReadPtr(), size);
}
Code: Select all
/*
IrrStreaming.h
*/
#ifndef IrrStreaming_h
#define IrrStreaming_h
#include "Stream.h"
#include "IrrCustomTypes.h"
//! Serialization of Irrlicht basic types
inline ImplementSerialization(irr::u8) { stream.Write(&obj, 1); }
inline ImplementSerialization(irr::s8) { stream.Write(&obj, 1); }
inline ImplementSerialization(irr::u16) { stream.Write(&obj, 2); }
inline ImplementSerialization(irr::s16) { stream.Write(&obj, 2); }
inline ImplementSerialization(irr::u32) { stream.Write(&obj, 4); }
inline ImplementSerialization(irr::s32) { stream.Write(&obj, 4); }
inline ImplementSerialization(irr::f32) { stream.Write(&obj, 4); }
inline ImplementSerializationRef(irr::f64) { stream.Write(&obj, 8); }
inline ImplementSerialization(irr::c8) { stream.Write(&obj, 1); }
inline ImplementSerialization(irr::wchar) { stream.Write(&obj, 2); }
DeclareSerializationRef(irr::core::stringc);
DeclareSerializationRef(irr::core::stringw);
//! Deserialization of Irrlicht basic types
inline ImplementDeserializationRef(irr::u8) { stream.Read(&obj, 1); }
inline ImplementDeserializationRef(irr::s8) { stream.Read(&obj, 1); }
inline ImplementDeserializationRef(irr::u16) { stream.Read(&obj, 2); }
inline ImplementDeserializationRef(irr::s16) { stream.Read(&obj, 2); }
inline ImplementDeserializationRef(irr::u32) { stream.Read(&obj, 4); }
inline ImplementDeserializationRef(irr::s32) { stream.Read(&obj, 4); }
inline ImplementDeserializationRef(irr::f32) { stream.Read(&obj, 4); }
inline ImplementDeserializationRef(irr::f64) { stream.Read(&obj, 8); }
inline ImplementDeserializationRef(irr::c8) { stream.Read(&obj, 1); }
inline ImplementDeserializationRef(irr::wchar) { stream.Read(&obj, 2); }
DeclareDeserializationRef(irr::core::stringc);
DeclareDeserializationRef(irr::core::stringw);
#endif // IrrStreaming_h
Code: Select all
/*
IrrStreaming.cpp
*/
#include "IrrStreaming.h"
//! Serialization of irr::core::stringc
ImplementSerializationRef(irr::core::stringc)
{
irr::u32 len = obj.size();
stream << len;
for (irr::u32 i = 0; i < len; i++)
stream << obj[i];
return stream;
}
//! Deserialization of irr::core::stringc
ImplementDeserializationRef(irr::core::stringc)
{
irr::u32 len;
irr::c8 ch;
stream >> len;
obj = "";
obj.reserve(len);
for (irr::u32 i = 0; i < len; i++)
{
stream >> ch;
obj.append(ch);
}
return stream;
}
//! Serialization of irr::core::stringw
ImplementSerializationRef(irr::core::stringw)
{
irr::u32 len = obj.size();
stream << len;
for (irr::u32 i = 0; i < len; i++)
stream << obj[i];
return stream;
}
//! Deserialization of irr::core::stringw
ImplementDeserializationRef(irr::core::stringw)
{
irr::u32 len;
irr::wchar ch;
stream >> len;
obj = "";
obj.reserve(len);
for (irr::u32 i = 0; i < len; i++)
{
stream >> ch;
obj.append(ch);
}
return stream;
}