SEDNL  .
Simple Event Driven Network Library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Namespaces | Constant Groups | Macros | Functions
Serializer.hpp File Reference

Allow serialization of instances. More...

#include <string>
#include "SEDNL/Packet.hpp"
#include "Serializer.ipp"

Go to the source code of this file.

Namespaces

 SedNL
 The SedNL library namespace.
 

Constant Groups

 SedNL
 The SedNL library namespace.
 

Macros

#define SEDNL_SERIALIZABLE(...)
 Allow objects to be serialized. More...
 

Functions

template<typename T , typename... Args>
void SedNL::serializer_serialize (Packet &packet, T &inst, Args &...args)
 
template<typename T , typename... Args>
void SedNL::serializer_unserialize (PacketReader &packet_reader, T &inst, Args &...args)
 

Detailed Description

Allow serialization of instances.

This file provide the macro and function definition needed to make your instances serialisable.

Basicaly, any class implementing void serialize(Packet& p) and void unserialize(PacketReader& p) is unserialisable.

The implementation provided by the macro SEDNL_SERIALIZABLE(...) simply call serializer_serialize(packet, *this, members...) and serializer_unserialize(packet_reader, *this, members...).

This means that if you don't like macro, you can wrote it by hand (but it's a bad idea, because the macro give you consistency : Using the macro, the unserialise function will always exactly work on the same members than the unserialise function).

If you want custom processing before / after serialisation / unserialisation you can implement some of the 4 folowing member functions :

void before_serialization();
void after_serialization();
void before_unserialization();
void after_unserialization();

As you can guess, they will be called before / after the serialization / unserialization process. Thats the recomanded way for costumisation of serialization and unserialization process.

A serializable instances (i.e. an instance of a serializable class) can be used with Packet::operator<<() and PacketReader::operator>>(). It means that you can read / write it as if it was a simple string.

If you want to read / write a bunch of data as a serialized object without actualy implementing a serializable class (for debug purpose, simple project where one of the two side don't need a class, etc...) you can use the convenience functions write_as_object(Packet& packet, Args&...) and read_as_object(PacketReader&, Args&...).

Here is a short example :

class Foo
{
public:
Foo()
:m_int(42), m_char(23), m_string("str")
{};
void before_serialization()
{
std::cout << "Before serialization" << std::endl;
};
void after_serialization()
{
std::cout << "After serialization" << std::endl;
};
void before_unserialization()
{
std::cout << "Before unserialization" << std::endl;
};
void after_unserialization()
{
std::cout << "After unserialization" << std::endl;
};
SEDNL_SERIALIZABLE(m_int, m_char, m_string);
private:
int m_int;
char m_char;
std::string m_string;
};
//Create a Foo instance
Foo first;
//Serialize the Foo instance
Packet p;
p << first; //same as first.serialize(p);
//Unserialize into the a instance
Foo second;
p >> second; //same as second.unserialize(p);

Definition in file Serializer.hpp.

Macro Definition Documentation

#define SEDNL_SERIALIZABLE (   ...)
Value:
inline void serialize(Packet& p) \
{ \
serializer_serialize(p, *this, __VA_ARGS__); \
} \
inline void unserialize(PacketReader& p) \
{ \
serializer_unserialize(p, *this, __VA_ARGS__); \
} \
inline void unserialize(const Packet& p) \
{ PacketReader r(p); unserialize(r); };

Allow objects to be serialized.

To allow one of you class to be serialisable, you can call the SEDNL_SERIALIZE() inside your class definition with the list of fields you would like to see serialized.

This will create two member methods serialize and unserialize.

Then, you can call your_instance.serialize(packet) and your_instance.unserialize(packet_reader).

A simple example of use is

class MyClass
{
public:
SEDNL_SERIALIZABLE(m_a, m_b);
private:
int m_a;
int m_b;
};

Here is the code generated by a call to this macro :

inline void serialize(Packet& p)
{
serializer_serialize(p, *this, __VA_ARGS__);
}
inline void unserialize(PacketReader& p)
{
serializer_unserialize(p, *this, __VA_ARGS__);
}
inline void unserialize(const Packet& p)
{
PacketReader r(p);
unserialize(r);
};