produced by Rachel-Kirkland
Inspiration came from
http://blog.csdn.net/Kiritow/article/details/53129096
https://github.com/byebyebryan/lazyxml/tree/master/LazyXML
-
This program implements a module to support binary serialization/deserialization. The serialized data is stored in the test_file folder as file.data.
-
-
Arithmetic types:
char, int, float, double, string
-
STL containers:
std::vector, std::list, std::set, std::map, std::pair
-
User-defined types
class cbox : public BS::Serializable{ public: int a; double b; std::string str; }
-
-
-
template<typename SerializableType> std::string serialize(SerializableType& a) { return a.serialize(); } template<typename SerializableType> int deserialize(std::string &str, SerializableType& a) { return a.deserialize(str); }
-
//Serialize for std::string (len+str.data()) template<> std::string serialize(std::string& s) { int len = s.size(); std::string ret; ret.append(BS::serialize(len)); ret.append(s.data(), len); return ret; } template<> int deserialize(std::string &str, std::string& s) { int len; BS::deserialize(str, len); s = str.substr(sizeof(len), len); return sizeof(int) + len; }
When serializing a string, the length of the string is serialized along with the contents of the string, thus effectively solving the problem of connecting a string to a string.
-
class Serializable{ public: virtual std::string serialize() = 0; virtual int deserialize(std::string&) = 0; };
For user-defined classes, you need to inherit to the template class and implement the serialization and deserialization methods yourself.
-
class OutStream { public: OutStream() : os(std::ios::binary) {} template<typename SerializableType> OutStream& operator<< (SerializableType& a) { std::string x = BS::serialize(a); os.write(x.data(), x.size()); return *this; } std::string str() { return os.str(); } public: std::ostringstream os; };
By defining a class for an output engine and overloading the output stream, the type to be serialized is fed into the output engine to obtain the serialized string.
Example for use:
OutStream oe; int a = 1; oe << a; oe.str(); //Get a serialized string
-
class InStream { public: InStream(std::string &s) : str(s), total(s.size()) {} template<typename SerializableType> InStream& operator>> (SerializableType& a) { int ret = BS::deserialize(str, a); str = str.substr(ret); return *this; } int size() { return total - str.size(); } protected: std::string str; int total; };
This type accepts serialized strings and deserializes them into the specified type by defining a class for the input engine and overloading the input stream.
Example for use:
InStream ie(str); //str: a string stored serialized data int a; ie >> a;
-
-
void TEST_BasicType() { std::cout << "\n====================================\n"; std::cout << "===TEST_BasicType=================\n"; std::cout << "====================================\n"; //int_test int a = 2, a1; BS::serialize_to_binaryfile(a, "test_file\\test_int.data"); BS::desrialize_from_binaryfile(a1, "test_file\\test_int.data"); std::cout << "binary_int_test\n"; ASSERT_EQ(a, a1); }
-
This program implement a wrapper module of tinyxml2 to support XML serialization. The serialized data is stored in the test_file folder as file.xml.
-
-
Arithmetic types:
char, int, float, double, string
-
STL containers:
std::vector, std::list, std::set, std::map, std::pair
-
User-defined types
class xbox: public XML_Seri::xmlSerialize { public: int a; double b; std::string str; };
-
-
-
template<typename T> struct VarType { static void reader(XMLElement * xmlElement, T & value) { std::cerr << "missing XML reading function for value type : " << typeid(T).name() << std::endl; assert(false); } static void writer(XMLElement * xmlElement, const std::string & name, const T & value) { std::cerr << "missing XML writing function for value type : " << typeid(T).name() << std::endl; assert(false); } };
Defines a class template, including two functions
static void reader(XMLElement * xmlElement, T & value)
andstatic void writer(XMLElement * xmlElement, const std::string & name, const T & value)
, which implemente the deserialization and serialization of the specified classT
respectively. After that, the class template is fully specialized and partially specialized according to different data types, so as to realize the deserialization and serialization functions of different data types.Example of full specialization
//read&write for char template<> struct VarType<char> { static void reader(tinyxml2::XMLElement * xmlElement, char &ch) { memcpy(&ch, xmlElement->GetText(), sizeof(char)); } static void writer(tinyxml2::XMLElement * xmlElement, const std::string & name, const char &ch) { tinyxml2::XMLElement * newElement = xmlElement->GetDocument()->NewElement(name.c_str()); newElement->SetText((const char*)&ch); xmlElement->InsertEndChild(newElement); } };
Take advantage of the built-in functions of the TinyXML2 module,
GetText()
andSetText()
to implement mutual transformation from string toXMLElement
.Example of partial specialization
//read&write for container type std::vector<T> template<typename T> struct VarType<std::vector<T>> { static void reader(XMLElement *xmlElement, std::vector<T> &value) { tinyxml2::XMLElement * childElement = xmlElement->FirstChildElement(); while (childElement) { T childValue; VarType<T>::reader(childElement, childValue); value.push_back(childValue); childElement = childElement->NextSiblingElement(); } } static void writer(XMLElement * xmlElement, const std::string & name, const std::vector<T> & value) { XMLElement * newElement = xmlElement->GetDocument()->NewElement(name.c_str()); for (auto &item : value) { VarType<T>::writer(newElement, "item", item); } xmlElement->InsertEndChild(newElement); } };
Serialization: Converts each element in the container to an
XMLElement
type, and inserts the convertedXMLElement
type node into the final linked list.Deserialization: Use a pointer of type
XMLElement
to traverse the list, converting each node to the specified data type, and usepush_back()
to store it in the container. -
Read and write functions of XML, Wrapper functions of serialization/deserialization (Omit the implementation)
//stream in from xml XMLDocument* ReadFromFile(const std::string &file_name) {} //deserialize from a xml file template<typename SerializableType> void deserialize_xml(SerializableType& a, const std::string &name, const std::string &file_name) {} //stream out to xml void WriteToFile(const XMLDocument *xmlDoc, const std::string &file_name) {} //serialize to a xml file template<typename SerializableType> void serialize_xml(SerializableType& a, const std::string &name, const std::string &file_name) {}
Serialization: convert the target type to an
XMLDocument
type:XMLDocument *xmlDoc
, and use the function:xmlDoc->Print(&xmlPrinter)
to write theXMLDocument
type as a string to the file file.xml.Deserialization: use
xmlDoc->Parse(str)
to read from file.xml and store into the objects of typeXMLDocument
. Use the previous full specialization or partial specialization function:reader(XMLElement*, T)
to convert anXMLDocument
type to an object of the specified type. -
class xmlSerialize { virtual void deserialize_xml(const std::string &name, const std::string &file_name) = 0; virtual void serialize_xml(const std::string &name, const std::string &file_name) = 0; };
For user-defined classes, you need to inherit to the template class and implement the serialization
void serialize_xml()
and deserializationvoid deserialize_xml()
methods yourself.
-
-
void TEST_Pair() { std::cout << "\n====================================\n"; std::cout << "===TEST_Pair=================\n"; std::cout << "====================================\n"; std::pair<int, double> p(2, 3.1), p2; //xml_test XML_Seri::serialize_xml(p, "std_pair", "test_file\\test_pair.xml"); XML_Seri::deserialize_xml(p2, "std_pair", "test_file\\test_pair.xml"); ASSERT_TRUE(p.first == p2.first); ASSERT_TRUE(p.second == p2.second); }