Usage
A guide on how to use GPDS
Terminology
value
vs. container
The value and container classes implement the core concept of GPDS's serialization design. Therefore, it's important to understand their difference and how to use them properly.
The following figure illustrates how these two classes are used to model a C++ object for the (de)serialization process:
Overview
This topic explains the usage of the GPDS library. See Overview for instructions on how to integrate the library into a project.
General usage
The following figure illustrates how GPDS is used by an address book application:
Make class serializable
A class needs to inherit from the container class in order to become serializable through GPDS.
Implement serialize interface
Implement the gpds::serialize interface by inheriting from the respective class to make your own class become serializable through GPDS as shown by the following UML class diagram:
Corresponding C++ code:
class car : public gpds::serialize { public: std::string manufacturer; std::string model; int year_of_construction; color color; virtual gpds::container to_container() const override { gpds::container c; c.add_value("manufacturer", manufacturer); c.add_value("model", model); c.add_value("year_of_construction", year_of_construction); c.add_value("color", color.to_container()); return c; } virtual void from_container(const pds::container& c) override { manufacturer = c.get_value<std::string>("manufacturer"); model = c.get_value<std::string>("model"); year_of_construction = c.get_value<int>("year_of_construction"); color.from_container( *c.get_value<gpds::container*>( "color" ) ); } }; class Color : public gpds::serialize { public: std::string name; int red; int green; int blue; virtual gpds::container to_container() const override { gpds::container c; c.add_attribute("format", "rgb"); c.add_attribute("name", name); c.add_value("red", red).add_attribute("depth", "32"); c.add_value("green", green).add_attribute("depth", "32"); c.add_value("blue", blue).add_attribute("depth", "32"); return c; } virtual void from_container(const gpds::container& c) override { // Retrieve format const std::string& format_string = c.get_attribute("format").value_or("n/a"); assert(format_string == std::string("rgb")); name = c.get_attribute("name").value_or("n/a"); red = c.get_value<int>("red"); green = c.get_value<int>("green"); blue = c.get_value<int>("blue"); } };
Once serialized with the XML archiver, the following output is produced:
<car> <color format="rgb" name="Black"> <blue depth="32">0</blue> <green depth="32">0</green> <red depth="32">0</red> </color> <manufacturer>Jeep</manufacturer> <model>Grand Cherokee</model> <year_of_construction>2009</year_of_construction> </car>
Serialize
Create an instance of archiver_xml (or of any other archiver class).
Call archiver::save() to serialize:
class car car;
std::sstream stream;
gpds::archiver_xml ar;
ar.save(stream, car, "car");
std::cout << stream.str() << std::endl
Deserialize
Create an instance of archiver_xml (or of any other archiver class).
Call archiver::load() to serialize:
class car car;
gpds::archiver_xml ar;
ar.load(stream, car, "car");
Nesting
The Container allows for nesting.
The Container class allows for nesting to produce serialized output that represents hierarchical/polymorphic data.
Created nested values
Nesting is achieved by passing a Container to Container::addValue().
Color color;
Gpds::Container c;
c.addValue( "color", color.toContainer() );
Retrieve nested values
Nested containers can be retrieved by calling
Container::getValue<Gpds::Container*>()
.
Color color;
color.fromContainer( *carContainer.getValue<Gpds::Container*>( "color" );