mrDIMAS

Serializer 2.0

Jan 17th, 2017
247
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.60 KB | None | 0 0
  1. // Supports only zero-args constructors for simplicity
  2. class Serializer {
  3. private:
  4.     static map<string, std::function<shared_ptr<void>()>> mConstructors;
  5.     map<uint32_t, shared_ptr<void>> mSharedPointers;
  6.     fstream mFile;
  7.     bool mWrite;
  8. public:
  9.     // Use this method to register type and it's constructor
  10.     template<typename T>
  11.     static void AddType() {
  12.         mConstructors[typeid(T).name()] = [] { return make_shared<T>(); };
  13.     }
  14.  
  15.     Serializer(const string & filename, bool write) : mWrite(write) {
  16.         mFile.open(filename, ios_base::binary | (write ? ios_base::out : ios_base::in));
  17.     }
  18.  
  19.     ~Serializer() {}
  20.     bool IsLoading() const { return !mWrite; }
  21.     bool IsSaving() const { return mWrite; }
  22.  
  23.     // Serialize generic type
  24.     template<typename T>
  25.     void operator & (T & value) {
  26.         if(mWrite) {
  27.             mFile.write((const char*)&value, sizeof(value));
  28.         } else {
  29.             mFile.read((char*)&value, sizeof(value));
  30.         }
  31.     }
  32.  
  33.     // Serialize UTF8 string
  34.     void operator & (string & str) {
  35.         static char zeroByte = '\0';
  36.         if(mWrite) {
  37.             for(auto symbol : str) {
  38.                 *this & symbol;
  39.             }
  40.             *this & zeroByte;
  41.         } else {
  42.             str.clear();
  43.             while(!mFile.eof()) {
  44.                 char symbol;
  45.                 *this & symbol;
  46.                 if(symbol == zeroByte) {
  47.                     break;
  48.                 } else {
  49.                     str.push_back(symbol);
  50.                 }
  51.             }
  52.         }
  53.     }
  54.  
  55.     // Serialize UTF32 string
  56.     void operator & (sf::String & str) {
  57.         static sf::Uint32 zero = (sf::Uint32)'\0';
  58.         if(mWrite) {
  59.             for(auto symbol : str) {
  60.                 *this & symbol;
  61.             }
  62.             *this & zero;
  63.         } else {
  64.             str.clear();
  65.             while(!mFile.eof()) {
  66.                 char32_t symbol;
  67.                 *this & symbol;
  68.                 if(symbol == zero) {
  69.                     break;
  70.                 } else {
  71.                     str += (sf::Uint32)symbol;
  72.                 }
  73.             }
  74.         }
  75.     }
  76.  
  77.  
  78.     // Serialize shared pointer
  79.     template<typename T>
  80.     void operator & (shared_ptr<T> & ptr) {
  81.         string typeName;
  82.         if(IsSaving()) {
  83.             if(ptr.get() == nullptr) {
  84.                 // place-holder type name
  85.                 typeName = typeid(T).name();
  86.             } else {
  87.                 // real type name
  88.                 typeName = typeid(*ptr.get()).name();
  89.             }
  90.         }
  91.  
  92.         // serialize type name first
  93.         *this & typeName;
  94.  
  95.         if(mWrite) {
  96.             // write pointer
  97.             uint32_t intPtr = (uint32_t)ptr.get();
  98.             mFile.write((const char *)&intPtr, sizeof(intPtr));
  99.         } else {
  100.             // read pointer
  101.             uint32_t intPtr;
  102.             mFile.read((char*)&intPtr, sizeof(intPtr));
  103.             if(intPtr != 0) {
  104.                 // find already created object
  105.                 auto existing = mSharedPointers.find(intPtr);
  106.                 if(existing != mSharedPointers.end()) {
  107.                     // found, return it
  108.                     ptr = static_pointer_cast<T>(existing->second);
  109.                 } else {
  110.                     // not found, try to call constructor from mConstructors map
  111.                     try {
  112.                         ptr = static_pointer_cast<T>(mConstructors[typeName]());
  113.                         mSharedPointers[intPtr] = ptr;
  114.                     } catch(std::bad_function_call) {
  115.                         // fail
  116.                         throw runtime_error(StringBuilder("Unable to create object from unregistered type '") << typeName << "'!");
  117.                     }
  118.                 }
  119.             }
  120.         }
  121.     }
  122.  
  123.     // Serialize weak pointer
  124.     template<typename T>
  125.     void operator & (weak_ptr<T> & ptr) {
  126.         if(mWrite) {
  127.             shared_ptr<T> locked = ptr.lock();
  128.             *this & locked;
  129.         } else {
  130.             shared_ptr<T> lockedWeak;
  131.             *this & lockedWeak;
  132.             ptr = lockedWeak;
  133.         }
  134.     }
  135.  
  136.     // Serialize vector
  137.     template<typename T>
  138.     void operator & (vector<T> & v) {
  139.         auto size = v.size();
  140.         *this & size;
  141.         if(IsLoading()) v.resize(size);
  142.         for(size_t i = 0; i < size; ++i) {
  143.             *this & v[i];
  144.         }
  145.     }
  146.  
  147.     // Serialize binary data
  148.     template<typename T>
  149.     void SerializeBinary(T * v, size_t size) {
  150.         *this & size;
  151.         if(mWrite) {
  152.             mFile.write((const char*)v, size);
  153.         } else {
  154.             mFile.read((char*)v, size);
  155.         }
  156.     }
  157. };
Advertisement
Add Comment
Please, Sign In to add comment