SparrowSerializer/src/serializationmanager.cpp
2017-01-19 12:43:51 +01:00

349 lines
13 KiB
C++

#include "serializationmanager.h"
#include "serializable.h"
#include <sstream>
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<Serializable*>*)p)->getValueRef());
else if(p->getPropertyType() == AbstractProperty::ARRAY && ((AbstractArrayProperty*)p)->getDataType() == AbstractProperty::REFERENCE)
{
std::vector<Serializable*> &vecRef = ((ArrayProperty<Serializable*>*)p)->getValueRef();
for(Serializable *ref : vecRef)
addObject(ref);
}
}
delete properties;
}
}
std::ostream& ObjectSaver::saveBinary(std::ostream& os)
{
// loop on serializable types
Property<int>(m_objects.size()).saveBinary(os); // amount of types
for(const std::pair<std::string, ObjectType> &type : m_objects)
{
// serialize type
Property<std::string>(type.first).saveBinary(os); // type name
Property<int>(type.second.size()).saveBinary(os); // amount of objects of this type
// order the objects
std::vector<Serializable*> orderedObjects(type.second.size());
for(const std::pair<Serializable*, int> &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<Serializable*>*)p)->getValueRef();
if(ref == nullptr)
Property<std::string>("null").saveBinary(os);
else
{
Property<std::string>(ref->getType()).saveBinary(os); // type name
Property<int>(m_objects[ref->getType()][ref]).saveBinary(os); // id of the object
}
}
else if(p->getPropertyType() == AbstractProperty::ARRAY && ((AbstractArrayProperty*)p)->getDataType() == AbstractProperty::REFERENCE)
{
std::vector<Serializable*> &vecRef = ((ArrayProperty<Serializable*>*)p)->getValueRef();
Property<int>(vecRef.size()).saveBinary(os); // amount of references
for(Serializable *ref : vecRef)
{
if(ref == nullptr)
Property<std::string>("null").saveBinary(os);
else
{
Property<std::string>(ref->getType()).saveBinary(os); // type name
Property<int>(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<std::string, ObjectType> &type : m_objects)
{
// serialize type
os << "\t\"" << type.first << "\": [" << std::endl;
// order the objects
std::vector<Serializable*> orderedObjects(type.second.size());
for(const std::pair<Serializable*, int> &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<Serializable*>*)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<Serializable*> &vecRef = ((ArrayProperty<Serializable*>*)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<int> nbTypes;
nbTypes.loadBinary(is); // get amount of types to read
for(int i=0; i<nbTypes.getValueRef(); ++i) // loop on these types
{
Property<std::string> typeName;
typeName.loadBinary(is); // get the type name
Serializable::Instancer instancer = Serializable::getInstancer(typeName.getValueRef());
Property<int> nbObjects;
nbObjects.loadBinary(is); // get the amount of objects of that type
std::vector<Serializable*> &objectsOfThatType = m_objects[typeName.getValueRef()];
for(int j=0; j<nbObjects.getValueRef(); ++j) // loop on these objects
{
Serializable* object = instancer();
objectsOfThatType.push_back(object);
PropertySet* properties = object->getProperties();
for(AbstractProperty* p : *properties)
{
if(p->getPropertyType() == AbstractProperty::REFERENCE)
{
Property<std::string> type; // type name
type.loadBinary(is);
if(type.getValueRef().compare("null") != 0)
{
Property<int> id; // id of the object
id.loadBinary(is);
PendingReference ref;
ref.ptr = &(((Property<Serializable*>*)p)->getValueRef());
ref.type = type.getValueRef();
ref.id = id.getValueRef();
m_references.push_back(ref);
}
else
((Property<Serializable*>*)p)->getValueRef() = nullptr;
}
else if(p->getPropertyType() == AbstractProperty::ARRAY && ((AbstractArrayProperty*)p)->getDataType() == AbstractProperty::REFERENCE)
{
Property<int> nbRef; // amount of references in the array
nbRef.loadBinary(is);
std::vector<Serializable*> &vecRef = ((ArrayProperty<Serializable*>*)p)->getValueRef();
vecRef = std::vector<Serializable*>(nbRef.getValueRef(), nullptr);
for(Serializable* &it : vecRef)
{
Property<std::string> type; // type name
type.loadBinary(is);
if(type.getValueRef().compare("null") != 0)
{
Property<int> id; // id of the object
id.loadBinary(is);
PendingReference ref;
ref.ptr = &it;
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<std::string> typeName;
typeName.loadAscii(ss);
Serializable::Instancer instancer = Serializable::getInstancer(typeName.getValueRef());
std::vector<Serializable*> &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<std::string> type; // type name
type.loadAscii(ss);
ss.ignore(1); // ,
Property<int> id; // id of the object
id.loadAscii(ss);
ss.ignore(1);
PendingReference ref;
ref.ptr = &(((Property<Serializable*>*)p)->getValueRef());
ref.type = type.getValueRef();
ref.id = id.getValueRef();
m_references.push_back(ref);
ss.ignore(1); // }
}
else
{
ss.ignore(6); // "null"
((Property<Serializable*>*)p)->getValueRef() = nullptr;
}
}
else if(p->getPropertyType() == AbstractProperty::ARRAY && ((AbstractArrayProperty*)p)->getDataType() == AbstractProperty::REFERENCE)
{
std::vector<Serializable*> &vecRef = ((ArrayProperty<Serializable*>*)p)->getValueRef();
ss.ignore(1); // [
while(ss.peek() != ']')
{
vecRef.push_back(nullptr);
if(ss.peek() == '{')
{
ss.ignore(1); // {
Property<std::string> type; // type name
type.loadAscii(ss);
ss.ignore(1); // ,
Property<int> 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();
}