Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Supports only zero-args constructors for simplicity
- class Serializer {
- private:
- static map<string, std::function<shared_ptr<void>()>> mConstructors;
- map<uint32_t, shared_ptr<void>> mSharedPointers;
- fstream mFile;
- bool mWrite;
- public:
- // Use this method to register type and it's constructor
- template<typename T>
- static void AddType() {
- mConstructors[typeid(T).name()] = [] { return make_shared<T>(); };
- }
- Serializer(const string & filename, bool write) : mWrite(write) {
- mFile.open(filename, ios_base::binary | (write ? ios_base::out : ios_base::in));
- }
- ~Serializer() {}
- bool IsLoading() const { return !mWrite; }
- bool IsSaving() const { return mWrite; }
- // Serialize generic type
- template<typename T>
- void operator & (T & value) {
- if(mWrite) {
- mFile.write((const char*)&value, sizeof(value));
- } else {
- mFile.read((char*)&value, sizeof(value));
- }
- }
- // Serialize UTF8 string
- void operator & (string & str) {
- static char zeroByte = '\0';
- if(mWrite) {
- for(auto symbol : str) {
- *this & symbol;
- }
- *this & zeroByte;
- } else {
- str.clear();
- while(!mFile.eof()) {
- char symbol;
- *this & symbol;
- if(symbol == zeroByte) {
- break;
- } else {
- str.push_back(symbol);
- }
- }
- }
- }
- // Serialize UTF32 string
- void operator & (sf::String & str) {
- static sf::Uint32 zero = (sf::Uint32)'\0';
- if(mWrite) {
- for(auto symbol : str) {
- *this & symbol;
- }
- *this & zero;
- } else {
- str.clear();
- while(!mFile.eof()) {
- char32_t symbol;
- *this & symbol;
- if(symbol == zero) {
- break;
- } else {
- str += (sf::Uint32)symbol;
- }
- }
- }
- }
- // Serialize shared pointer
- template<typename T>
- void operator & (shared_ptr<T> & ptr) {
- string typeName;
- if(IsSaving()) {
- if(ptr.get() == nullptr) {
- // place-holder type name
- typeName = typeid(T).name();
- } else {
- // real type name
- typeName = typeid(*ptr.get()).name();
- }
- }
- // serialize type name first
- *this & typeName;
- if(mWrite) {
- // write pointer
- uint32_t intPtr = (uint32_t)ptr.get();
- mFile.write((const char *)&intPtr, sizeof(intPtr));
- } else {
- // read pointer
- uint32_t intPtr;
- mFile.read((char*)&intPtr, sizeof(intPtr));
- if(intPtr != 0) {
- // find already created object
- auto existing = mSharedPointers.find(intPtr);
- if(existing != mSharedPointers.end()) {
- // found, return it
- ptr = static_pointer_cast<T>(existing->second);
- } else {
- // not found, try to call constructor from mConstructors map
- try {
- ptr = static_pointer_cast<T>(mConstructors[typeName]());
- mSharedPointers[intPtr] = ptr;
- } catch(std::bad_function_call) {
- // fail
- throw runtime_error(StringBuilder("Unable to create object from unregistered type '") << typeName << "'!");
- }
- }
- }
- }
- }
- // Serialize weak pointer
- template<typename T>
- void operator & (weak_ptr<T> & ptr) {
- if(mWrite) {
- shared_ptr<T> locked = ptr.lock();
- *this & locked;
- } else {
- shared_ptr<T> lockedWeak;
- *this & lockedWeak;
- ptr = lockedWeak;
- }
- }
- // Serialize vector
- template<typename T>
- void operator & (vector<T> & v) {
- auto size = v.size();
- *this & size;
- if(IsLoading()) v.resize(size);
- for(size_t i = 0; i < size; ++i) {
- *this & v[i];
- }
- }
- // Serialize binary data
- template<typename T>
- void SerializeBinary(T * v, size_t size) {
- *this & size;
- if(mWrite) {
- mFile.write((const char*)v, size);
- } else {
- mFile.read((char*)v, size);
- }
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment