tested Serializable inheritance, fixed a bug in JSON deserialization

This commit is contained in:
Anselme 2017-01-22 14:44:06 +01:00
parent d1873c9de4
commit 8646073ae4
4 changed files with 114 additions and 32 deletions

View File

@ -6,67 +6,116 @@
#include <sstream> #include <sstream>
#include <fstream> #include <fstream>
class Foo : public Serializable /**
* @brief Plop = Serializable mother class (incomplete)
*/
class Plop : public Serializable
{
public:
P_REFERENCE (Plop, myPlop)
};
/**
* @brief Bar = Serializable class Inheriting Plop
*/
class Bar : public Plop
{
public:
P_STRING (myTruc)
SERIALIZABLE(Bar,
CAST(myTruc),
CAST(myPlop))
Bar()
{
myTruc = "Je suis un Bar";
myPlop = this;
}
};
/**
* @brief Bar = Other Serializable class Inheriting Plop, referencing an instance of the Bar class
*/
class Foo : public Plop
{ {
public: public:
P_INT (myInt) P_INT (myInt)
P_STRING (myString) P_STRING (myString)
P_VECTOR_FLOAT(myFloatArray) P_VECTOR_FLOAT(myFloatArray)
P_VEC3 (myVec3) P_VEC3 (myVec3)
P_REFERENCE (Foo, myFoo)
SERIALIZABLE(Foo, SERIALIZABLE(Foo,
CAST(myInt), CAST(myInt),
CAST(myString), CAST(myString),
CAST(myFloatArray), CAST(myFloatArray),
CAST(myVec3), CAST(myVec3),
CAST(myFoo)) CAST(myPlop))
Foo() Foo()
{ {
myInt = 3; myInt = 3;
myString = "plop"; myString = "Je suis un Foo";
myFloatArray.push_back(1.5); myFloatArray.push_back(1.5);
myFloatArray.push_back(1.3); myFloatArray.push_back(1.3);
myFloatArray.push_back(2.5); myFloatArray.push_back(2.5);
myFloatArray.push_back(6.2); myFloatArray.push_back(6.2);
myVec3 = glm::vec3(0.1, 0, 5.4); myVec3 = glm::vec3(0.1, 0, 5.4);
myFoo = this; Bar* bar = new Bar();
bar->myPlop = nullptr;
myPlop = bar;
} }
}; };
INIT_SERIALIZABLE(Bar)
INIT_SERIALIZABLE(Foo) INIT_SERIALIZABLE(Foo)
int main() int main()
{ {
// init // testing polymorphism on Serializables
Foo* f1 = new Foo(); Foo* foo = new Foo();
f1->myString = "Hello, i am foo 1";
Foo* f2 = new Foo(); // print before
f2->myString = "How's it goin', my name is \"Foo 2\""; std::cout << "Before :" << std::endl;
f1->myFloatArray.clear(); ObjectSaver printer;
f2->myVec3 = glm::vec3(1, 2, 3); printer.addObject(foo);
f1->myFoo = f2; printer.saveAscii(std::cout);
f2->myFoo = nullptr;
// saving as binary // saving as binary
ObjectSaver saver; ObjectSaver saverBinary;
saver.addObject(f1); saverBinary.addObject(foo);
std::fstream outFile; std::fstream outFileBinary;
outFile.open("test.bin", std::ios_base::out); outFileBinary.open("test.bin", std::ios_base::out);
saver.saveBinary(outFile); saverBinary.saveBinary(outFileBinary);
outFile.close(); outFileBinary.close();
// loading as binary // loading as binary
ObjectLoader loader; ObjectLoader loaderBinary;
std::fstream inFile; std::fstream inFileBinary;
inFile.open("test.bin", std::ios_base::in); inFileBinary.open("test.bin", std::ios_base::in);
loader.loadBinary(inFile); loaderBinary.loadBinary(inFileBinary);
inFile.close(); inFileBinary.close();
// print result // saving as json
ObjectSaver printer; ObjectSaver saverAscii;
for(Foo* f : loader.getObjects<Foo>()) for(Foo* f : loaderBinary.getObjects<Foo>())
saverAscii.addObject(f);
std::fstream outFileAscii;
outFileAscii.open("test.txt", std::ios_base::out);
saverAscii.saveAscii(outFileAscii);
outFileAscii.close();
// loading as json
ObjectLoader loaderAscii;
std::fstream inFileAscii;
inFileAscii.open("test.txt", std::ios_base::in);
loaderAscii.loadAscii(inFileAscii);
inFileAscii.close();
// print after
std::cout << "After :" << std::endl;
printer.clearObjects();
for(Foo* f : loaderAscii.getObjects<Foo>())
printer.addObject(f); printer.addObject(f);
printer.saveAscii(std::cout); printer.saveAscii(std::cout);

View File

@ -110,6 +110,7 @@ public:
template <typename T> template <typename T>
class Property : public AbstractProperty class Property : public AbstractProperty
{ {
protected:
T m_value; T m_value;
public: public:
Property(T val) : m_value(val) {} Property(T val) : m_value(val) {}
@ -136,6 +137,7 @@ public:
template <typename T> template <typename T>
class Property<T*> : public AbstractProperty class Property<T*> : public AbstractProperty
{ {
protected:
T* m_value; T* m_value;
public: public:
Property(T* val) : m_value(val) {} Property(T* val) : m_value(val) {}
@ -166,6 +168,7 @@ public:
template <typename T> template <typename T>
class ArrayProperty : public AbstractArrayProperty class ArrayProperty : public AbstractArrayProperty
{ {
protected:
std::vector<T> m_value; std::vector<T> m_value;
public: public:
ArrayProperty(const std::vector<T> &val) : m_value(val) {} ArrayProperty(const std::vector<T> &val) : m_value(val) {}

View File

@ -28,6 +28,17 @@ void ObjectSaver::addObject(Serializable *object)
} }
} }
void ObjectSaver::removeObject(Serializable *object)
{
if(object == nullptr)
return;
const std::string &type = object->getType();
ObjectType &objectsOfSameType = m_objects[type];
objectsOfSameType.erase(object);
if(objectsOfSameType.size() == 0)
m_objects.erase(type);
}
std::ostream& ObjectSaver::saveBinary(std::ostream& os) std::ostream& ObjectSaver::saveBinary(std::ostream& os)
{ {
// loop on serializable types // loop on serializable types
@ -87,9 +98,13 @@ std::ostream& ObjectSaver::saveBinary(std::ostream& os)
std::ostream& ObjectSaver::saveAscii(std::ostream& os) std::ostream& ObjectSaver::saveAscii(std::ostream& os)
{ {
os << "{" << std::endl; os << "{" << std::endl;
int nbTypes = m_objects.size();
int currentType = 0;
// loop on serializable types // loop on serializable types
for(const std::pair<std::string, ObjectType> &type : m_objects) for(const std::pair<std::string, ObjectType> &type : m_objects)
{ {
++currentType;
// serialize type // serialize type
os << "\t\"" << type.first << "\": [" << std::endl; os << "\t\"" << type.first << "\": [" << std::endl;
@ -144,7 +159,10 @@ std::ostream& ObjectSaver::saveAscii(std::ostream& os)
else else
os << "," << std::endl; os << "," << std::endl;
} }
if(nbTypes == currentType)
os << "\t]" << std::endl; os << "\t]" << std::endl;
else
os << "\t]," << std::endl;
} }
return os << "}" << std::endl; return os << "}" << std::endl;
} }
@ -272,7 +290,7 @@ std::istream& ObjectLoader::loadAscii(std::istream& is)
Serializable* object = instancer(); Serializable* object = instancer();
objectsOfThatType.push_back(object); objectsOfThatType.push_back(object);
PropertySet* properties = object->getProperties(); PropertySet* properties = object->getProperties();
for(AbstractProperty* p : *properties) for(AbstractProperty* p : *properties) // loop on the properties of this object
{ {
if(p->getPropertyType() == AbstractProperty::REFERENCE) if(p->getPropertyType() == AbstractProperty::REFERENCE)
{ {
@ -284,7 +302,6 @@ std::istream& ObjectLoader::loadAscii(std::istream& is)
ss.ignore(1); // , ss.ignore(1); // ,
Property<int> id; // id of the object Property<int> id; // id of the object
id.loadAscii(ss); id.loadAscii(ss);
ss.ignore(1);
PendingReference ref; PendingReference ref;
ref.ptr = &(((Property<Serializable*>*)p)->getValueRef()); ref.ptr = &(((Property<Serializable*>*)p)->getValueRef());
ref.type = type.getValueRef(); ref.type = type.getValueRef();
@ -322,19 +339,26 @@ std::istream& ObjectLoader::loadAscii(std::istream& is)
} }
else else
ss.ignore(6); // "null" ss.ignore(6); // "null"
if(ss.peek() != ',') if(ss.peek() == ',')
ss.ignore(1); // , ss.ignore(1); // ,
} }
ss.ignore(1); // ] ss.ignore(1); // ]
} }
else else
p->loadAscii(ss); p->loadAscii(ss);
// loop on the properties of this object
if(p != properties->back()) if(p != properties->back())
ss.ignore(1); // , ss.ignore(1); // ,
} }
// loop on the objects of that type
ss.ignore(1); // } ss.ignore(1); // }
if(ss.peek() == ',')
ss.ignore(1); // ,
} }
// loop on serializable types
ss.ignore(1); // ] ss.ignore(1); // ]
if(ss.peek() == ',')
ss.ignore(1); // ,
} }
buildReferences(); buildReferences();
return is; return is;

View File

@ -15,6 +15,12 @@ public:
template <typename T> template <typename T>
void addObject(T *object) { addObject((Serializable*)object); } void addObject(T *object) { addObject((Serializable*)object); }
void removeObject(Serializable *object);
template <typename T>
void removeObject(T *object) { removeObject((Serializable*)object); }
void clearObjects() { m_objects.clear(); }
std::ostream& saveBinary(std::ostream& os); std::ostream& saveBinary(std::ostream& os);
std::ostream& saveAscii(std::ostream& os); std::ostream& saveAscii(std::ostream& os);
}; };