To use the library, do the following:
If required, obtain a third party type traits library such as Loki or boost
For Mac OS X or Windows, open a project file. There are project files included for Xcode 2.4 or later (Mac OS X) and Visual C++ 2005 or later (Windows). The Visual C++ Express Editions can be used.
For Mac OS X or Windows, set up the paths to any third party libraries in the serialization library's project file.
For Mac OS X or
Windows, configure the serialization
library to select which third party library to use for type traits by
editing the config.hpp file
(or set up preprocessor macros). For example, to select Loki
as the type traits library:
#define USE_LOKI_LIBRARY 1
For Mac OS X or
Windows, if you are using other supported
libraries such as boost or Intel TBB then edit
the config.hpp file so that
the library will build with support for those libraries. The section
to edit looks like this:
// begin user/client settable defaults // If you wish to enable the support of a library then set the value to one; // if you wish to explicitly disable the support of a library because, for example, // you don't have it or don't want to use it, then set the value to zero. #if !defined(HAVE_LOKI_LIBRARY) #define HAVE_LOKI_LIBRARY 1 #endif #if !defined(HAVE_BOOST_LIBRARY) #define HAVE_BOOST_LIBRARY 1 #endif #if !defined(HAVE_TBB_LIBRARY) #define HAVE_TBB_LIBRARY 1 #endif // end user/client settable defaults
Build the library. You can build the library either as a static library or a dynamic/shared library by selecting the appropriate target or configuration. For Mac OS X or Windows, select the appropriate configuration or target and build it. For POSIX systems, open a shell terminal and change to the distribution's directory, then enter './configure && make' to configure and build the library.
Although optional, it is recommended that you build and run the test program. For Mac OS X, the Xcode project file includes the 'unitTestsDynamic' target which will build the library and test program, and execute the test rig. For Windows, build the DebugDynamic configuration in the Visual C++ project, and then run the test program. For POSIX systems, perform a 'make check' from the shell to build and run the test program.
For Mac OS X or Windows, add the library to your project so that it will be linked with the final executable. For Xcode and Visual C++, you can add the project file and then declare a dependency on the serialization project. For POSIX systems, install the shared library (if you built the library as such) by doing a 'make install', and then declare a dependency on the library in your makefile.
Write code to save or load objects. In either case, you need to instantiate an instance of ccs::serialization::storage. In the constructor of storage, specify the path to the database file to store the data into or load the data from. For example:
ccs::serialization::storage<> db("/path/to/stored/data.db");You should probably use a custom file extension so that the OS can automatically map the database files to your application/executable.
To save objects, use operator<< to
stream data to the storage file. For example
class Person {
public:
enum GENDER { UNKNOWN, MALE, FEMALE };
// default constructor is required
Person() : gender(UNKNOWN), age(0) {}
Person(GENDER g, string n, string addr, int age_) :
gender(g), name(n), address(addr), age(age_) {}
private:
GENDER gender;
string name, address;
int age;
};
vector<Person> employees;
employees.push_back(Person(Person::MALE, "Michael Smith",
"1234 Orange St.", 32));
ccs::serialization::storage<> db("/path/to/stored/data.db");
db << employees;To load objects, use operator>> to
stream data from the storage file. For example:
class Person {
public:
enum GENDER { UNKNOWN, MALE, FEMALE };
// default constructor is required
Person() : gender(UNKNOWN), age(0) {}
Person(GENDER g, string n, string addr, int age_) :
gender(g), name(n), address(addr), age(age_) {}
private:
GENDER gender;
string name, address;
int age;
};
vector<Person> employees;
ccs::serialization::storage<> db("/path/to/stored/data.db");
db >> employees;The database is closed and data is commited to it when the storage instance goes out of scope.
If any of the objects that are stored are user defined classes that are not directly supported by the library, you will need to write code to load and save the members of the class. If the class members are simple data types and you have the source code to the class, then intrusive non-split serialization can be used to serialize data. For example:
class Person {
public:
enum GENDER { UNKNOWN, MALE, FEMALE };
// default constructor is required
Person() : gender(UNKNOWN), age(0) {}
Person(GENDER g, string n, string addr, int age_) :
gender(g), name(n), address(addr), age(age_) {}
private:
// begin serialization code
friend class ccs::serialization::access;
template <typename S>
void serialize(S& s) { s & gender & name & address & age; }
// end serialization code
GENDER gender;
string name, address;
int age;
};As you can see, the library uses
operator& as the streaming operator for
members of a class/struct. This makes it easier to port code that uses
the boost
serialization library.
If you have more complex needs, please see the sections below on how to serialize your data, in particular, see the "Serializing user defined types" section.
Objects must be stored and retrieved in the same order. For example, suppose a drawing program wishes to save the user's drawing which consists of an ordered list of drawing shapes and an integer pair for the drawing canvas size, and a rectangle for the GUI window that displays the drawing. To make the data format future proof, an integer representing the document version is also stored. Thus the program will store an integer for the data's version number, then a vector of shapes, then 2 integers for the drawing canvas size, and then 4 integers for the GUI window location and size:
vector<shape*> shape_list;
ccs::serialization::storage<> db("/path/to/stored/data.db");
db << version << shape_list;
db << canvas.width << canvas.height;
db << window.left << window.top << window.width << window.height;To correctly load the data, the data must be streamed back in the same order to the same object types:
vector<shape*> shape_list;
ccs::serialization::storage<> db("/path/to/stored/data.db");
db >> version >> shape_list;
db >> canvas.width >> canvas.height;
db >> window.left >> window.top >> window.width >> window.height;Note that this example does not handle versioning. See the example in the "Limitations and work-arounds" section for an example of how to handle versioning.
You should now be able to add serialization to your program. For more information about using the library, please read the rest of this documentation.
The following chapters describe in more detail what is involved in using the library. First, the library's architecture is described so that you have a good idea of what the pieces are and how they fit together. Then the process of building and testing the library is described, followed by a description of linking with the library. The chapters following these then describe the rules and options available when using the library, and how to serialize specific types of data or objects. The last chapters describe advanced topics and the structure of the database file created by the library when your program calls it.