#ifndef PROPERTY_H #define PROPERTY_H #include #include #include // PROPERTIES MACROS (used by Serializable class) #define PROPERTY(type, var)\ Property 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 var##Property;\ type*& var = (type*&)(var##Property.getValueRef());\ #define VECTOR_PROPERTY(type, var)\ ArrayProperty var##Property;\ std::vector &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 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 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 class Property : 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 class ArrayProperty : public AbstractArrayProperty { std::vector value; public: ArrayProperty(const std::vector &val) : value(val) {} ArrayProperty() {} ~ArrayProperty() {} std::ostream& saveBinary(std::ostream& os) { Property size(value.size()); size.saveBinary(os); for(T &it : value) Property(it).saveBinary(os); return os; } std::ostream& saveAscii(std::ostream& os) { os << "["; int i = value.size(); for(T &it : value) { Property(it).saveAscii(os); if(--i) os << ", "; } return os << "]"; } std::istream& loadBinary(std::istream& is) { Property size; size.loadBinary(is); value.resize(size.getValueRef()); Property p; for(int i=0; i 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::getStaticPropertyType(); } std::vector &getValueRef() { return value; } unsigned int getArraySize() { return value.size(); } }; #endif // PROPERTY_H