#include "serializationmanager.h" #include "serializable.h" #include void ObjectSaver::addObject(Serializable *object) { if(object == nullptr) return; const std::string &type = object->getType(); ObjectType &objectsOfSameType = m_objects[type]; if(objectsOfSameType.count(object) == 0) { int n = objectsOfSameType.size(); objectsOfSameType[object] = n; PropertySet *properties = object->getProperties(); for(AbstractProperty* p : *properties) { if(p->getPropertyType() == AbstractProperty::REFERENCE) addObject(((Property*)p)->getValueRef()); else if(p->getPropertyType() == AbstractProperty::ARRAY && ((AbstractArrayProperty*)p)->getDataType() == AbstractProperty::REFERENCE) { std::vector &vecRef = ((ArrayProperty*)p)->getValueRef(); for(Serializable *ref : vecRef) addObject(ref); } } delete properties; } } std::ostream& ObjectSaver::saveBinary(std::ostream& os) { // loop on serializable types Property(m_objects.size()).saveBinary(os); // amount of types for(const std::pair &type : m_objects) { // serialize type Property(type.first).saveBinary(os); // type name Property(type.second.size()).saveBinary(os); // amount of objects of this type // order the objects std::vector orderedObjects(type.second.size()); for(const std::pair &entry : type.second) orderedObjects[entry.second] = entry.first; // serialize objects of this type for(Serializable* object : orderedObjects) { PropertySet *properties = object->getProperties(); for(AbstractProperty *p : *properties) { if(p->getPropertyType() == AbstractProperty::REFERENCE) { Serializable *ref = ((Property*)p)->getValueRef(); if(ref == nullptr) Property("null").saveBinary(os); else { Property(ref->getType()).saveBinary(os); // type name Property(m_objects[ref->getType()][ref]).saveBinary(os); // id of the object } } else if(p->getPropertyType() == AbstractProperty::ARRAY && ((AbstractArrayProperty*)p)->getDataType() == AbstractProperty::REFERENCE) { std::vector &vecRef = ((ArrayProperty*)p)->getValueRef(); Property(vecRef.size()).saveBinary(os); // amount of references for(Serializable *ref : vecRef) { if(ref == nullptr) Property("null").saveBinary(os); else { Property(ref->getType()).saveBinary(os); // type name Property(m_objects[ref->getType()][ref]).saveBinary(os); // id of the object } } } else p->saveBinary(os); } delete properties; } } return os; } std::ostream& ObjectSaver::saveAscii(std::ostream& os) { os << "{" << std::endl; // loop on serializable types for(const std::pair &type : m_objects) { // serialize type os << "\t\"" << type.first << "\": [" << std::endl; // order the objects std::vector orderedObjects(type.second.size()); for(const std::pair &entry : type.second) orderedObjects[entry.second] = entry.first; // serialize objects of this type for(Serializable* object : orderedObjects) { os << "\t\t{" << std::endl; PropertySet *properties = object->getProperties(); for(AbstractProperty *p : *properties) { os << "\t\t\t"; if(p->getPropertyType() == AbstractProperty::REFERENCE) { Serializable *ref = ((Property*)p)->getValueRef(); if(ref == nullptr) os << "\"null\""; else os << "{\"" << ref->getType() << "\", " << (m_objects[ref->getType()][ref]) << "}"; } else if(p->getPropertyType() == AbstractProperty::ARRAY && ((AbstractArrayProperty*)p)->getDataType() == AbstractProperty::REFERENCE) { std::vector &vecRef = ((ArrayProperty*)p)->getValueRef(); os << "["; int i = vecRef.size(); for(Serializable *ref : vecRef) { if(ref == nullptr) os << "\"null\""; else os << "{\"" << ref->getType() << "\", " << (m_objects[ref->getType()][ref]) << "}"; if(--i) os << ", "; } os << "]"; } else p->saveAscii(os); if(properties->back() == p) os << std::endl; else os << "," << std::endl; } delete properties; os << "\t\t}"; if(orderedObjects.back() == object) os << std::endl; else os << "," << std::endl; } os << "\t]" << std::endl; } return os << "}" << std::endl; } std::istream& ObjectLoader::loadBinary(std::istream& is) { Property nbTypes; nbTypes.loadBinary(is); // get amount of types to read for(int i=0; i typeName; typeName.loadBinary(is); // get the type name Serializable::Instancer instancer = Serializable::getInstancer(typeName.getValueRef()); Property nbObjects; nbObjects.loadBinary(is); // get the amount of objects of that type std::vector &objectsOfThatType = m_objects[typeName.getValueRef()]; for(int j=0; jgetProperties(); for(AbstractProperty* p : *properties) { if(p->getPropertyType() == AbstractProperty::REFERENCE) { Property type; // type name type.loadBinary(is); if(type.getValueRef().compare("null") != 0) { Property id; // id of the object id.loadBinary(is); PendingReference ref; ref.ptr = &(((Property*)p)->getValueRef()); ref.type = type.getValueRef(); ref.id = id.getValueRef(); m_references.push_back(ref); } else ((Property*)p)->getValueRef() = nullptr; } else if(p->getPropertyType() == AbstractProperty::ARRAY && ((AbstractArrayProperty*)p)->getDataType() == AbstractProperty::REFERENCE) { Property nbRef; // amount of references in the array nbRef.loadBinary(is); std::vector &vecRef = ((ArrayProperty*)p)->getValueRef(); vecRef = std::vector(nbRef.getValueRef(), nullptr); for(Serializable* &it : vecRef) { Property type; // type name type.loadBinary(is); if(type.getValueRef().compare("null") != 0) { Property id; // id of the object id.loadBinary(is); PendingReference ref; ref.ptr = ⁢ ref.type = type.getValueRef(); ref.id = id.getValueRef(); m_references.push_back(ref); } } } else p->loadBinary(is); } delete properties; } } buildReferences(); return is; } std::istream& ObjectLoader::loadAscii(std::istream& is) { // get trimmed version of the stream into a stringstream while(is.get() != '{'); // got to first opening brace int nbBraces = 1; bool inString = false; std::stringstream ss; while(nbBraces > 0) // read and trim until we find the corresponding closing brace { int c = is.get(); switch(c) { case '{': ++nbBraces; ss.put(c); break; case '}': --nbBraces; ss.put(c); break; case '\\': if(is.peek() == '"') inString = !inString; ss.put(c); break; case '"': inString = !inString; ss.put(c); break; case ' ': if(inString) ss.put(c); case '\n': case '\t': case '\r': break; default: ss.put(c); } } // begin parsing while(ss.peek() != '}') // loop on serializable types { Property typeName; typeName.loadAscii(ss); Serializable::Instancer instancer = Serializable::getInstancer(typeName.getValueRef()); std::vector &objectsOfThatType = m_objects[typeName.getValueRef()]; ss.ignore(2); // :[ while(ss.peek() != ']') // loop on the objects of that type { ss.ignore(1); // { Serializable* object = instancer(); objectsOfThatType.push_back(object); PropertySet* properties = object->getProperties(); for(AbstractProperty* p : *properties) { if(p->getPropertyType() == AbstractProperty::REFERENCE) { if(ss.peek() == '{') { ss.ignore(1); // { Property type; // type name type.loadAscii(ss); ss.ignore(1); // , Property id; // id of the object id.loadAscii(ss); ss.ignore(1); PendingReference ref; ref.ptr = &(((Property*)p)->getValueRef()); ref.type = type.getValueRef(); ref.id = id.getValueRef(); m_references.push_back(ref); ss.ignore(1); // } } else { ss.ignore(6); // "null" ((Property*)p)->getValueRef() = nullptr; } } else if(p->getPropertyType() == AbstractProperty::ARRAY && ((AbstractArrayProperty*)p)->getDataType() == AbstractProperty::REFERENCE) { std::vector &vecRef = ((ArrayProperty*)p)->getValueRef(); ss.ignore(1); // [ while(ss.peek() != ']') { vecRef.push_back(nullptr); if(ss.peek() == '{') { ss.ignore(1); // { Property type; // type name type.loadAscii(ss); ss.ignore(1); // , Property id; // id of the object id.loadAscii(ss); ss.ignore(1); // } PendingReference ref; ref.ptr = &(vecRef.back()); ref.type = type.getValueRef(); ref.id = id.getValueRef(); m_references.push_back(ref); } else ss.ignore(6); // "null" if(ss.peek() != ',') ss.ignore(1); // , } ss.ignore(1); // ] } else p->loadAscii(ss); if(p != properties->back()) ss.ignore(1); // , } ss.ignore(1); // } } ss.ignore(1); // ] } buildReferences(); return is; } void ObjectLoader::buildReferences() { for(PendingReference &ref : m_references) *(ref.ptr) = m_objects[ref.type][ref.id]; m_references.clear(); }