1 /** 2 A simple interface for reading and writing objects to files, has support for both json and binary. 3 Basic types, enums and vectors are supported by default, other class and struct types need to 4 implement the "void serialize(FileInterface * file)" function. 5 The interface is symmetric, meaning that there is only a single function for both saving and loading. 6 7 class ExampleClass { 8 private: 9 Uint32 MyNumber; 10 String MyString; 11 public: 12 void serialize(FileInterface * file) { 13 file->property("MyNumber", MyNumber); 14 file->property("MyString", MyString); 15 } 16 }; 17 */ 18 19 #pragma once 20 21 #include <functional> 22 #include <assert.h> 23 24 enum class EFileFormat { 25 Json, 26 Binary 27 }; 28 29 class FileInterface { 30 public: ~FileInterface()31 virtual ~FileInterface() {} 32 33 // @return true if this interface is reading data from a file, false if it is writing 34 virtual bool isReading() const = 0; 35 36 // Signals the beginning of an object in the file 37 virtual void beginObject() = 0; 38 // Signals the end of an object in the file 39 virtual void endObject() = 0; 40 41 // Signals the beginning of an array in the file 42 // @param size number of items in the array 43 virtual void beginArray(Uint32 & size) = 0; 44 // Signals the end of an array in the file 45 virtual void endArray() = 0; 46 47 // Serializes the name of a property 48 // @param name name of the property 49 virtual void propertyName(const char * name) = 0; 50 51 // @param v the value to serialize 52 virtual void value(Uint32& v) = 0; 53 // @param v the value to serialize 54 virtual void value(Sint32& v) = 0; 55 // @param v the value to serialize 56 virtual void value(float& v) = 0; 57 // @param v the value to serialize 58 virtual void value(double& v) = 0; 59 // @param v the value to serialize 60 virtual void value(bool& v) = 0; 61 // @param v the value to serialize 62 // @param maxLength maximum length of the string allowed, 0 is no limit 63 virtual void value(std::string& v, Uint32 maxLength = 0) = 0; 64 65 // Serialize a vector with a max length 66 // @param v the value to serialize 67 // @param maxLength maximum number of items, 0 is no limit 68 template<typename T, typename... Args> value(std::vector<T> & v,Uint32 maxLength=0,Args...args)69 void value(std::vector<T>& v, Uint32 maxLength = 0, Args ... args) { 70 Uint32 size = (Uint32)v.size(); 71 beginArray(size); 72 assert(maxLength == 0 || size <= maxLength); 73 v.resize(size); 74 for (Uint32 index = 0; index < size; ++index) { 75 value(v[index], args...); 76 } 77 endArray(); 78 } 79 80 // Serialize a pointer by dereferencing it 81 // @param v the pointer to dereference and serialize 82 template<typename T> value(T * & v)83 void value (T*& v) { 84 if (isReading()) { 85 v = new T(); 86 } 87 value(*v); 88 } 89 90 // Serializes an enum value as its underlying type to the file 91 // @param t the enum value to serialize 92 template<typename T> 93 typename std::enable_if<std::is_enum<T>::value, void>::type value(T & v)94 value(T& v) { 95 typename std::underlying_type<T>::type temp = v; 96 value(temp); 97 v = (T)temp; 98 } 99 100 // Serializes a class or struct to the file using it's ::serialize(FileInterface*) function 101 // @param v the object to serialize 102 template<typename T> 103 typename std::enable_if<std::is_class<T>::value, void>::type value(T & v)104 value(T& v) { 105 beginObject(); 106 v.serialize(this); 107 endObject(); 108 } 109 110 // Serializes a fixed-size native array 111 // @param v array to serialize 112 template<typename T, Uint32 Size, typename... Args> value(T (& v)[Size],Args...args)113 void value(T (&v)[Size], Args ... args) { 114 Uint32 size = Size; 115 beginArray(size); 116 assert(size == Size); 117 for (Uint32 index = 0; index < size; ++index) { 118 value(v[index], args...); 119 } 120 endArray(); 121 } 122 123 // Helper function to serialize a property name and value at the same time 124 // @param name name of the property 125 // @param v value to serialize 126 // @param args additional args to pass into the value() function 127 template<typename T, typename... Args> property(const char * name,T & v,Args...args)128 void property(const char * name, T& v, Args ... args) { 129 propertyName(name); 130 value(v, args...); 131 } 132 133 }; 134 135 class FileHelper { 136 public: 137 // Write an object's data to a file 138 // @param filename the name of the file to write 139 // @param v the object to write 140 template<typename T> writeObject(const char * filename,EFileFormat format,T & v)141 static bool writeObject(const char * filename, EFileFormat format, T & v) { 142 using std::placeholders::_1; 143 SerializationFunc serialize = std::bind(&T::serialize, &v, _1); 144 return writeObjectInternal(filename, format, serialize); 145 } 146 147 // Read an object's data from a file 148 // @param filename the name of the file to read 149 // @param v the object to populate with data 150 template<typename T> readObject(const char * filename,T & v)151 static bool readObject(const char * filename, T & v) { 152 using std::placeholders::_1; 153 SerializationFunc serialize = std::bind(&T::serialize, &v, _1); 154 return readObjectInternal(filename, serialize); 155 } 156 157 typedef std::function<void(FileInterface*)> SerializationFunc; 158 159 private: 160 161 static bool writeObjectInternal(const char * filename, EFileFormat format, const SerializationFunc& serialize); 162 static bool readObjectInternal(const char * filename, const SerializationFunc& serialize); 163 }; 164