class iSerializable { public: virtual void serialize (Node node) = 0; };
class ConcreteClass : public iSerializable { public: virtual void serialize (Node node) override { node.set_name ("BaseClass"); node.serialize (m_int, "int"); node.serialize (m_uint, "uint"); } private: int m_int = 10; unsigned int m_uint = 200; };
xml_node m_node;
template <typename T> void serialize (T& value, const wstring& name) { value.serialize (get_node (name)); }
template <> void serialize (int& value, const string& name) { xml_attribute it = m_node.attribute (name.c_str ()); if (it) value = it.as_int (); else m_node.append_attribute (name.c_str ()).set_value (value); }
template <> void serialize (iSerializable*& object, const string& name)
{ if (!object) m_factory->get_object (object, m_node.find_child_by_attribute ("name", name.c_str ()).name ()); object->serialize (get_node_by_attr (name)); }
struct ObjectBase { wstring name; ObjectBase (const string& _name) : name (_name) {} virtual void* get_copy () = 0; }; template <typename Data> struct Object : public ObjectBase { Object (const string& _name) : ObjectBase (_name) {} virtual void* get_copy () override { return (void*) new Data (); } };
template <typename T> void set_object (const string& name) { if (std::find_if ( m_prototypes.begin (), m_prototypes.end (), [name] (ObjectBase* obj) { return obj->name == name; } ) == m_prototypes.end () ) m_prototypes.push_back (new Object<T> (name)); } template <typename T> void get_object (T*& object, const string& name) const { auto it = find_if (m_prototypes.begin (), m_prototypes.end (), [name] (ObjectBase* obj) { return obj->name == name; }); if (it != m_prototypes.end ()) object = (T*) (*it)->get_copy (); else throw std::exception ("Prototype wasn't found!"); }
void init_prototypes (Prototypes::PrototypeFactory*);
void init_prototypes (Prototypes::PrototypeFactory* factory) { factory->set_object< ConcreteClass > (" ConcreteClass "); }
PrototypeFactory () { init_prototypes (this); }
template <template <typename T, class alloc> class Container, typename Data, typename alloc> void serialize ( Container<Data*, alloc>& container, const string& name, const string& subname ) { Node node = get_node (name); size_t size (container.size ()); node.serialize (size, "size"); if (container.empty ()) container.assign (size, nullptr); size_t count (0); for (auto i = container.begin (); i < container.end (); ++i) node.serialize (*i, subname + std::to_string (count++)); } template <template <typename T, class alloc> class Container, typename Data, typename alloc> void serialize ( Container<Data, alloc>& container, const string& name, const string& subname ) { Node node = get_node (name); size_t size (container.size ()); node.serialize (size, "size"); if (container.empty ()) container.assign (size, Data ()); size_t count (0); for (auto i = container.begin (); i < container.end (); ++i) i->serialize (node.get_node_by_attr (subname + std::to_string (count++))); }
class Serializer { public: Serializer() {} template <class Serializable> void serialize (Serializable* object, const string& filename) { object->serialize (m_document.append_child (L"")); m_document.save_file ((filename+".xml").c_str ()); m_document.reset (); } template <class Serializable> void deserialize (Serializable* object, const string& filename) { if (m_document.load_file ((filename + ".xml").c_str ())) object->serialize (m_document.first_child ()); m_document.reset (); } private: xml_document m_document; PrototypeFactory m_factory; };
class BaseClass : public iSerializable { public: virtual ~BaseClass () {} virtual void serialize (Node node) override { node.set_name ("BaseClass"); node.serialize (m_int, "int"); node.serialize (m_uint, "uint"); } private: int m_int = 10; unsigned int m_uint = 200; }; class MyConcreteClass : public BaseClass { public: virtual void serialize (Node node) override { BaseClass::serialize (node); node.set_name ("MyConcreteClass"); node.serialize (m_float, "float"); node.serialize (m_double, "double"); } private: float m_float = 1.0f; double m_double = 2.0; }; class SomeonesConcreteClass : public BaseClass { public: virtual void serialize (Node node) override { BaseClass::serialize (node); node.set_name ("SomeonesConcreteClass"); node.serialize (m_str, "string"); node.serialize (m_bool, "boolean"); } private: wstring m_str = "ololo"; bool m_bool = true; }; class Container { public: ~Container () { for (BaseClass* ptr : vec_ptr) delete ptr; vec_ptr.clear (); vec_arg.clear (); } void serialize (Node node) { node.set_name ("SomeContainers"); node.serialize (vec_ptr, "containerPtr", "myclass_"); node.serialize (vec_arg, "containerArg", "myclass_"); } private: std::vector<BaseClass*> vec_ptr; std::vector<BaseClass> vec_arg; }; void init_prototypes (Prototypes::PrototypeFactory* factory) { factory->set_object<BaseClass> ("BaseClass"); factory->set_object<MyConcreteClass> ("MyConcreteClass"); factory->set_object<SomeonesConcreteClass> ("SomeonesConcreteClass"); } int main (int argc, char* argv[]) { Serializer* document = new Serializer (); Container* container = new Container (); document->deserialize (container, "document"); document->serialize (container, "doc"); delete container; delete document; return 0; }
Source: https://habr.com/ru/post/245305/
All Articles