SparrowSerializer/src/property.h

229 lines
6.1 KiB
C++

#ifndef PROPERTY_H
#define PROPERTY_H
#include <vector>
#include <iostream>
#include <glm/ext.hpp>
// PROPERTIES MACROS (used by Serializable class)
#define PROPERTY(type, var)\
Property<type> var##Property;\
type &var = var##Property.getValueRef();\
#define INT(var) PROPERTY(int, var)
#define UINT(var) PROPERTY(unsigned int, var)
#define LONG(var) PROPERTY(long, var)
#define SHORT(var) PROPERTY(short, var)
#define BYTE(var) PROPERTY(char, var)
#define DOUBLE(var) PROPERTY(double, var)
#define FLOAT(var) PROPERTY(float, var)
#define BOOL(var) PROPERTY(bool, var)
#define VEC2(var) PROPERTY(glm::vec2, var)
#define VEC3(var) PROPERTY(glm::vec3, var)
#define MAT4(var) PROPERTY(glm::mat4, var)
#define STRING(var) PROPERTY(std::string, var)
// the provided type must be a class inheriting Serializable
#define REFERENCE(type, var)\
Property<Serializable*> var##Property;\
type*& var = (type*&)(var##Property.getValueRef());\
#define VECTOR_PROPERTY(type, var)\
ArrayProperty<type> var##Property;\
std::vector<type> &var = var##Property.getValueRef();\
#define VECTOR_INT(var) VECTOR_PROPERTY(int, var)
#define VECTOR_UINT(var) VECTOR_PROPERTY(unsigned int, var)
#define VECTOR_FLOAT(var) VECTOR_PROPERTY(float, var)
#define VECTOR_BOOL(var) VECTOR_PROPERTY(bool, var)
#define VECTOR_SHORT(var) VECTOR_PROPERTY(short, var)
#define VECTOR_BYTE(var) VECTOR_PROPERTY(char, var)
#define VECTOR_LONG(var) VECTOR_PROPERTY(long, var)
#define VECTOR_DOUBLE(var) VECTOR_PROPERTY(double, var)
#define VECTOR_VEC2(var) VECTOR_PROPERTY(glm::vec2, var)
#define VECTOR_VEC3(var) VECTOR_PROPERTY(glm::vec3, var)
#define VECTOR_MAT4(var) VECTOR_PROPERTY(glm::mat4, var)
#define VECTOR_STRING(var) VECTOR_PROPERTY(std::string, var)
#define VECTOR_REFERENCE(type, var) VECTOR_PROPERTY(type*, var)
#define CAST(var) (AbstractProperty*)&var##Property
// FORWARD DECLARATIONS AND TYPES
class AbstractProperty;
class Serializable;
typedef std::vector<AbstractProperty*> PropertySet;
// PROPERTY INTERFACE
class AbstractProperty
{
public:
enum PropertyType
{
UNDEFINED,
INTEGER,
SHORT,
LONG,
BYTE,
UNSIGNED_INTEGER,
FLOAT,
DOUBLE,
BOOLEAN,
VEC2,
VEC3,
MAT4,
STRING,
REFERENCE,
ARRAY, // this is a bit special, an array must also have one of the other types
// keep last
NB_PROPERTY_TYPES
};
virtual ~AbstractProperty() {}
virtual std::ostream& saveBinary(std::ostream& os) = 0;
virtual std::ostream& saveAscii(std::ostream& os) = 0;
virtual std::istream& loadBinary(std::istream& is) = 0;
virtual std::istream& loadAscii(std::istream& is) = 0;
virtual PropertyType getPropertyType() = 0;
friend PropertySet& operator << (PropertySet &properties, AbstractProperty& p)
{ properties.push_back(&p); return properties; }
};
// GENERIC PROPERTY
template <typename T>
class Property : public AbstractProperty
{
T value;
public:
Property(T val) : value(val) {}
Property() {}
~Property() {}
std::ostream& saveBinary(std::ostream& os);
std::ostream& saveAscii(std::ostream& os);
std::istream& loadBinary(std::istream& is);
std::istream& loadAscii(std::istream& is);
PropertyType getPropertyType() { return getStaticPropertyType(); }
static PropertyType getStaticPropertyType();
T &getValueRef() { return value; }
};
/**
* Reference properties are implemented through partial specialization of Property,
* it can compile with any pointer,
* but will only work will pointers to a class that inherits Serializable
*/
template <typename T>
class Property<T*> : public AbstractProperty
{
T* value;
public:
Property(T* val) : value(val) {}
Property() {}
~Property() {}
// will not be used, serialization of references is entirely done by the serialization manager
std::ostream& saveBinary(std::ostream& os) { return os; }
std::ostream& saveAscii(std::ostream& os) { return os; }
std::istream& loadBinary(std::istream& is) { return is; }
std::istream& loadAscii(std::istream& is) { return is; }
PropertyType getPropertyType() { return getStaticPropertyType(); }
static PropertyType getStaticPropertyType() { return REFERENCE; }
T*& getValueRef() { return value; }
};
// GENERIC VECTOR PROPERTY
class AbstractArrayProperty : public AbstractProperty
{
public:
PropertyType getPropertyType() { return ARRAY; }
virtual PropertyType getDataType() { return UNDEFINED; }
};
template <typename T>
class ArrayProperty : public AbstractArrayProperty
{
std::vector<T> value;
public:
ArrayProperty(const std::vector<T> &val) : value(val) {}
ArrayProperty() {}
~ArrayProperty() {}
std::ostream& saveBinary(std::ostream& os)
{
Property<int> size(value.size());
size.saveBinary(os);
for(T &it : value)
Property<T>(it).saveBinary(os);
return os;
}
std::ostream& saveAscii(std::ostream& os)
{
os << "[";
int i = value.size();
for(T &it : value)
{
Property<T>(it).saveAscii(os);
if(--i) os << ", ";
}
return os << "]";
}
std::istream& loadBinary(std::istream& is)
{
Property<int> size;
size.loadBinary(is);
value.resize(size.getValueRef());
Property<T> p;
for(int i=0; i<size.getValueRef(); ++i)
{
p.loadBinary(is);
value[i] = p.getValueRef();
}
return is;
}
std::istream& loadAscii(std::istream& is)
{
value.clear();
is.ignore(1); // [
Property<T> p;
while(is.peek() != ']')
{
p.loadAscii(is);
value.push_back(p.getValueRef());
if(is.peek() == ',')
is.ignore(1); // ,
}
return is.ignore(1);
}
// array specific methods
PropertyType getDataType() { return Property<T>::getStaticPropertyType(); }
std::vector<T> &getValueRef() { return value; }
unsigned int getArraySize() { return value.size(); }
};
#endif // PROPERTY_H