Electively serialize to/from XML or binary in C++

Defining a shared interface

Given these prerequisites, I came up with the following interface for the Serializer and Deserializer class.

#ifndef VTE_CORE_SERIALIZER_H
#define VTE_CORE_SERIALIZER_H
#include <core/Types.h>
namespace vte
{
namespace core
{
class Serializer
{
public:
	virtual ~Serializer()
	{
	}
	virtual void beginAttribute( const std::string& name ) = 0;
	virtual void writeNumberOfElements( u32 numElements ) = 0;
	virtual void writeParameter( const std::string& name, const std::string& value ) = 0;
	virtual void writeParameter( const std::string& name, s32 value, const std::string& readable ) = 0;
	virtual void writeParameter( const std::string& name, const bool& value ) = 0;
	virtual void writeParameter( const std::string& name, const u32& value ) = 0;
	virtual void writeParameter( const std::string& name, const f32& value ) = 0;
	virtual void writeParameter( const std::string& name, const vec3& value ) = 0;
	virtual void writeParameter( const std::string& name, const irr::video::SColorf& value ) = 0;
	virtual void endAttribute() = 0;
};
} // namespace core
} // namespace vte
#endif
#ifndef VTE_CORE_DESERIALIZER_H
#define VTE_CORE_DESERIALIZER_H
#include <core/Types.h>
namespace vte
{
namespace core
{
class Deserializer
{
public:
	Deserializer()
	{
	}
	virtual ~Deserializer()
	{
	}
	virtual void beginAttribute( const std::string& name ) = 0;
	virtual u32 readNumberOfElements() = 0;
	virtual void readParameter( const std::string& name, std::string& value ) = 0;
	virtual void readParameter( const std::string& name, s32& value, std::string& readable ) = 0;
	virtual void readParameter( const std::string& name, bool& value ) = 0;
	virtual void readParameter( const std::string& name, u32& value ) = 0;
	virtual void readParameter( const std::string& name, f32& value ) = 0;
	virtual void readParameter( const std::string& name, vec3& value ) = 0;
	virtual void readParameter( const std::string& name, irr::video::SColorf& value ) = 0;
	virtual void endAttribute() = 0;
};
} // namespace core
} // namespace vte
#endif

Let’s have a look at the methods available.

  • beginAttribute starts a logical group of data. It’s required from the XML point of view where it will introduce a new enclosing tag. Therefore, this would be the very first method you would call in order to serialize something. Technically speaking, the XML serializer we will implement later appends a child element. Because no such information is required for binary serialization, the binary serializer implementation of this method would be empty.
  • writeNumberOfElements writes the number of child elements, if any. Now it’s the other way round: the XML serializer won’t write anything since the number of children is implicitly known by the number of child elements in the XML tree, contrary the the binary format, where we need to know how many child elements will follow.
  • writeParameter writes an actual item of information, like a std::string or an f32 (which is a typedef for a float)or some application-dependent types like irr::video::SColorf (which is the structure which holds color information in the Irrlicht engine, in case you were curious).
  • endAttribute finally closes a logical group of data. As with beginAttribute, the underlying implementation for XML serialization closes the enclosing tag while the binary one does nothing.

4 Comments

Leave a Reply

Your email address will not be published.