#pragma once /* * This module is included as a part of libSprawl * * Copyright (C) 2013 Jaedyn K. Draper * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #include "../string/String.hpp" #include "../memory/PoolAllocator.hpp" #include "../memory/StlWrapper.hpp" #include "../common/errors.hpp" namespace mongo { class OID; class BSONObj; struct Date_t; } namespace sprawl { namespace serialization { class SerializationDataTypeDetector {}; template class SerializationData : public SerializationDataTypeDetector { public: explicit SerializationData(T& a, sprawl::String const& b = "noname", bool c=true) : val(a), name(b), PersistToDB(c) {} explicit SerializationData(T&& a, sprawl::String const& b = "noname", bool c=true) : val(a), name(b), PersistToDB(c) {} T& operator*(){ return val; } T& val; sprawl::String name; bool PersistToDB; private: SerializationData operator=(SerializationData& other); }; class BinaryData { public: explicit BinaryData(char* data, uint32_t dataLength, sprawl::String const& b = "noname", bool c=true) : val(data) , name(b) , size(dataLength) , PersistToDB(c) {} const char* operator*(){ return val; } char* val; sprawl::String name; uint32_t size; bool PersistToDB; private: BinaryData operator=(BinaryData& other); }; inline BinaryData prepare_data(char* val, uint32_t dataLength, sprawl::String const& name = "noname", bool persist=true) { return BinaryData(val, dataLength, name, persist); } template inline SerializationData prepare_data(T& val, sprawl::String const& name = "noname", bool persist=true, typename std::enable_if::value>::type* = 0) { return SerializationData(val, name, persist); } template inline SerializationData prepare_data(T&& val, sprawl::String const& name = "noname", bool persist=true, typename std::enable_if::value>::type* = 0, typename std::enable_if::value>::type* = 0) { return SerializationData(val, name, persist); } template::value> struct UnderlyingTypeHelper { typedef T type; }; template struct UnderlyingTypeHelper { typedef typename std::underlying_type::type type; }; template inline SerializationData::type> prepare_data(T& val, sprawl::String const& name = "noname", bool persist=true, typename std::enable_if::value>::type* = 0) { return SerializationData::type>((typename std::underlying_type::type&)(val), name, persist); } template inline SerializationData::type> prepare_data(T&& val, sprawl::String const& name = "noname", bool persist=true, typename std::enable_if::value>::type* = 0, typename std::enable_if::value>::type* = 0) { return SerializationData::type>((typename std::underlying_type::type&&)(val), name, persist); } #define NAME_PROPERTY(var) sprawl::serialization::prepare_data(var, sprawl::StringLiteral(#var)) #define TRANSIENT_NAME_PROPERTY(var) sprawl::serialization::prepare_data(var, sprawl::StringLiteral(#var), false) #define BINARY_NAME_PROPERTY(var, length) sprawl::serialization::prepare_data(var, length, sprawl::StringLiteral(#var), true) #define TRANSIENT_BINARY_NAME_PROPERTY(var, length) sprawl::serialization::prepare_data(var, length, sprawl::StringLiteral(#var), false) class SerializerBase { public: typedef std::unordered_set, std::equal_to, sprawl::memory::StlWrapper> StringSet; virtual bool IsLoading() = 0; bool IsSaving() { return !IsLoading(); } virtual bool IsBinary() { return false; } virtual bool IsReplicable() { return false; } virtual bool IsMongoStream() { return false; } virtual uint32_t GetVersion() = 0; virtual void SetVersion(uint32_t i) = 0; virtual ErrorState Reset() { return ErrorState(); } virtual bool IsValid() = 0; virtual bool Error() = 0; virtual size_t Size() = 0; SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var); SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var); SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var); SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var); SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var); SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData::reference>&& var); SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var); SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var); SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var); SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var); SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var); SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var); SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var); SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var); SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var); SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var); SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var); virtual SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(BinaryData&& var); template< std::size_t N > SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { SPRAWL_RETHROW(serialize(var.val, sizeof(var.val), var.name, var.PersistToDB)); return *this; } template< std::size_t N > SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { SPRAWL_RETHROW(serialize(var.val, sizeof(var.val), var.name, var.PersistToDB)); return *this; } template< std::size_t N > SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { SPRAWL_RETHROW(serialize(var.val, sizeof(var.val), var.name, var.PersistToDB)); return *this; } template< std::size_t N > SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { SPRAWL_RETHROW(serialize(var.val, sizeof(var.val), var.name, var.PersistToDB)); return *this; } template< std::size_t N > SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { SPRAWL_RETHROW(serialize(var.val, sizeof(var.val), var.name, var.PersistToDB)); return *this; } template< std::size_t N > SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { SPRAWL_RETHROW(serialize(var.val, sizeof(var.val), var.name, var.PersistToDB)); return *this; } template< std::size_t N > SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { SPRAWL_RETHROW(serialize(var.val, sizeof(var.val), var.name, var.PersistToDB)); return *this; } template< std::size_t N > SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { SPRAWL_RETHROW(serialize(var.val, sizeof(var.val), var.name, var.PersistToDB)); return *this; } template< std::size_t N > SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { SPRAWL_RETHROW(serialize(var.val, sizeof(var.val), var.name, var.PersistToDB)); return *this; } template< std::size_t N > SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { SPRAWL_RETHROW(serialize(var.val, sizeof(var.val), var.name, var.PersistToDB)); return *this; } template< std::size_t N > SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { SPRAWL_RETHROW(serialize(var.val, sizeof(var.val), var.name, var.PersistToDB)); return *this; } template< std::size_t N > SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { SPRAWL_RETHROW(serialize(var.val, sizeof(var.val), var.name, var.PersistToDB)); return *this; } template< typename T, std::size_t N, std::size_t M> SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { uint32_t size; StartArray(var.name, size, var.PersistToDB); for(int i = 0; i < N; i++) { SPRAWL_RETHROW(*this % prepare_data(var.val[i], var.name, var.PersistToDB)); } EndArray(); return *this; } template< typename T, std::size_t N, std::size_t M, std::size_t O> SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { uint32_t size; StartArray(var.name, size, var.PersistToDB); for(int i = 0; i < N; i++) { SPRAWL_RETHROW(*this % prepare_data(var.val[i], var.name, var.PersistToDB)); } EndArray(); return *this; } template< typename T, std::size_t N, std::size_t M, std::size_t O, std::size_t P> SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { uint32_t size; StartArray(var.name, size, var.PersistToDB); for(int i = 0; i < N; i++) { SPRAWL_RETHROW(*this % prepare_data(var.val[i], var.name, var.PersistToDB)); } EndArray(); return *this; } SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var); SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var); private: //Optimized vector implementations for simple types template SPRAWL_WARN_UNUSED_RESULT ErrorState VectorSerialize(SerializationData>& var, std::true_type) { uint32_t size = (uint32_t)var.val.size(); if(IsBinary()) { SPRAWL_RETHROW(*this % prepare_data(size, var.name, false)); } StartArray(var.name, size, var.PersistToDB); if(IsLoading()) { var.val.resize(size); } if(IsBinary()) { SPRAWL_RETHROW(serialize(&var.val[0], size * sizeof(T), var.name, var.PersistToDB)); } else { for(uint32_t i=0; i(); } template SPRAWL_WARN_UNUSED_RESULT ErrorState VectorSerialize(SerializationData>& var, std::false_type) { uint32_t size = (uint32_t)var.val.size(); if(IsBinary()) { SPRAWL_RETHROW(*this % prepare_data(size, var.name, false)); } StartArray(var.name, size, var.PersistToDB); if(IsLoading()) { var.val.resize(size); } for(uint32_t i=0; i(); } //Except that bool has its own weird behaviors... so it has to be treated like the other kind. SPRAWL_WARN_UNUSED_RESULT ErrorState VectorSerialize(SerializationData>& var, std::true_type) { uint32_t size = (uint32_t)var.val.size(); if(IsBinary()) { SPRAWL_RETHROW(*this % prepare_data(size, var.name, false)); } StartArray(var.name, size, var.PersistToDB); if(IsLoading()) { var.val.resize(size); } for(uint32_t i=0; i(); } public: template SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData>&& var) { SPRAWL_RETHROW(VectorSerialize(var, std::is_integral())); return *this; } template SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData>&& var) { if(IsLoading()) { if(IsReplicable()) { StringSet deleted_keys = GetDeletedKeys(var.name); for(auto& key : deleted_keys) { key_type k; SPRAWL_RETHROW(this->OneOff(const_cast(key), k)); var.val.erase(k); } } else { var.val.clear(); } } uint32_t size = (uint32_t)var.val.size(); if(IsBinary()) { SPRAWL_RETHROW((*this) % prepare_data(size, var.name, false)); } uint32_t calcedSize = StartMap(var.name, var.PersistToDB); if(IsLoading()) { if(!IsBinary()) { size = calcedSize; } for(uint32_t i=0; iOneOff(key, k)); SPRAWL_RETHROW((*this) % prepare_data(v, key, var.PersistToDB)); var.val[k] = v; } } } else { for(auto& kvp : var.val) { if(IsBinary()) { key_type name = kvp.first; SPRAWL_RETHROW((*this) % prepare_data(name, var.name, var.PersistToDB)); SPRAWL_RETHROW((*this) % prepare_data(kvp.second, var.name, var.PersistToDB)); } else { sprawl::String s; key_type k = kvp.first; SPRAWL_RETHROW(this->OneOff(s, k)); SPRAWL_RETHROW((*this) % prepare_data(kvp.second, s, var.PersistToDB)); } } } EndMap(); return *this; } template SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData>&& var) { if(IsLoading()) { if(IsReplicable()) { StringSet deleted_keys = GetDeletedKeys(var.name); for(auto& key : deleted_keys) { key_type k; SPRAWL_RETHROW(this->OneOff(const_cast(key), k)); var.val.erase(k); } } else { var.val.clear(); } } uint32_t size = (uint32_t)var.val.size(); if(IsBinary()) { SPRAWL_RETHROW((*this) % prepare_data(size, var.name, false)); } uint32_t calcedSize = StartMap(var.name, var.PersistToDB); if(IsLoading()) { if(!IsBinary()) { size = calcedSize; } for(uint32_t i=0; iOneOff(key, k)); SPRAWL_RETHROW((*this) % prepare_data(v, key, var.PersistToDB)); var.val[k] = v; } } } else { for(auto& kvp : var.val) { if(IsBinary()) { key_type name = kvp.first; SPRAWL_RETHROW((*this) % prepare_data(name, var.name, var.PersistToDB)); SPRAWL_RETHROW((*this) % prepare_data(kvp.second, var.name, var.PersistToDB)); } else { sprawl::String s; key_type k = kvp.first; SPRAWL_RETHROW(this->OneOff(s, k)); SPRAWL_RETHROW((*this) % prepare_data(kvp.second, s, var.PersistToDB)); } } } EndMap(); return *this; } template SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData>&& var) { if(IsLoading()) { key_type k; val_type v; if(IsBinary()) { SPRAWL_RETHROW((*this) % prepare_data(k, var.name, var.PersistToDB)) SPRAWL_RETHROW((*this) % prepare_data(v, var.name, var.PersistToDB)); var.val = std::make_pair(k, v); } else { sprawl::String key = GetNextKey(); this->OneOff(key, k); SPRAWL_RETHROW((*this) % prepare_data(v, key, var.PersistToDB)); var.val = std::make_pair(k, v); } } else { if(IsBinary()) { key_type name = var.val.first; SPRAWL_RETHROW((*this) % prepare_data(name, var.name, var.PersistToDB)) SPRAWL_RETHROW((*this) % prepare_data(var.val.second, var.name, var.PersistToDB)); } else { sprawl::String s; key_type k = var.val.first; this->OneOff(s, k); SPRAWL_RETHROW((*this) % prepare_data(var.val.second, s, var.PersistToDB)); } } return *this; } template SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData>&& var) { if(IsLoading()) { if(IsReplicable()) { StringSet deleted_keys = GetDeletedKeys(var.name); for(auto& key : deleted_keys) { var.val.erase(key.toStdString()); } } else { var.val.clear(); } } uint32_t size = (uint32_t)var.val.size(); if(IsBinary()) { SPRAWL_RETHROW((*this) % prepare_data(size, var.name, false)); } uint32_t calcedSize = StartMap(var.name, var.PersistToDB); if(IsLoading()) { if(!IsBinary()) { size = calcedSize; } for(uint32_t i=0; i SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData>&& var) { if(IsLoading()) { if(IsReplicable()) { StringSet deleted_keys = GetDeletedKeys(var.name); for(auto& key : deleted_keys) { var.val.erase(key.toStdString()); } } else { var.val.clear(); } } uint32_t size = (uint32_t)var.val.size(); if(IsBinary()) { SPRAWL_RETHROW((*this) % prepare_data(size, var.name, false)); } uint32_t calcedSize = StartMap(var.name, var.PersistToDB); if(IsLoading()) { if(!IsBinary()) { size = calcedSize; } for(uint32_t i=0; i SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData>&& var) { if(IsLoading()) { if(IsReplicable()) { StringSet deleted_keys = GetDeletedKeys(var.name); for(auto& key : deleted_keys) { var.val.erase(key.toStdString()); } } else { var.val.clear(); } } uint32_t size = (uint32_t)var.val.size(); if(IsBinary()) { SPRAWL_RETHROW((*this) % prepare_data(size, var.name, false)); } uint32_t calcedSize = StartMap(var.name, var.PersistToDB); if(IsLoading()) { if(!IsBinary()) { size = calcedSize; } for(uint32_t i=0; i SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData>&& var) { if(IsLoading()) { if(IsReplicable()) { StringSet deleted_keys = GetDeletedKeys(var.name); for(auto& key : deleted_keys) { var.val.erase(key.toStdString()); } } else { var.val.clear(); } } uint32_t size = (uint32_t)var.val.size(); if(IsBinary()) { SPRAWL_RETHROW((*this) % prepare_data(size, var.name, false)); } uint32_t calcedSize = StartMap(var.name, var.PersistToDB); if(IsLoading()) { if(!IsBinary()) { size = calcedSize; } for(uint32_t i=0; i SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData>&& var) { if(IsLoading()) { std::string k; val_type v; if(IsBinary()) { SPRAWL_RETHROW((*this) % prepare_data(k, var.name, var.PersistToDB)); SPRAWL_RETHROW((*this) % prepare_data(v, var.name, var.PersistToDB)); var.val = std::make_pair(k, v); } else { sprawl::String key = GetNextKey(); SPRAWL_RETHROW((*this) % prepare_data(v, key, var.PersistToDB)); var.val = std::make_pair(k, v); } } else { if(IsBinary()) { std::string name = var.val.first; SPRAWL_RETHROW((*this) % prepare_data(name, var.name, var.PersistToDB)); SPRAWL_RETHROW((*this) % prepare_data(var.val.second, var.name, var.PersistToDB)); } else { SPRAWL_RETHROW((*this) % prepare_data(var.val.second, var.val.first, var.PersistToDB)); } } return *this; } template SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData>&& var) { if(IsLoading()) { sprawl::String k; val_type v; if(IsBinary()) { SPRAWL_RETHROW((*this) % prepare_data(k, var.name, var.PersistToDB)); SPRAWL_RETHROW((*this) % prepare_data(v, var.name, var.PersistToDB)); var.val = std::make_pair(k, v); } else { sprawl::String key = GetNextKey(); SPRAWL_RETHROW((*this) % prepare_data(v, key, var.PersistToDB)); var.val = std::make_pair(k, v); } } else { if(IsBinary()) { sprawl::String name = var.val.first; SPRAWL_RETHROW((*this) % prepare_data(name, var.name, var.PersistToDB)); SPRAWL_RETHROW((*this) % prepare_data(var.val.second, var.name, var.PersistToDB)); } else { SPRAWL_RETHROW((*this) % prepare_data(var.val.second, var.val.first, var.PersistToDB)); } } return *this; } template SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData>&& var) { uint32_t size = (uint32_t)var.val.size(); if(IsBinary()) { SPRAWL_RETHROW(*this % prepare_data(size, var.name, false)); } StartArray(var.name, size, var.PersistToDB); if(IsLoading()) { for(uint32_t i=0; i SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData>&& var) { uint32_t size = (uint32_t)var.val.size(); if(IsBinary()) { SPRAWL_RETHROW(*this % prepare_data(size, var.name, false)); } StartArray(var.name, size, var.PersistToDB); if(IsLoading()) { for(uint32_t i=0; i operator%(SerializationData &&); virtual SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData &&); virtual SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData &&); virtual SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData &&); virtual SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData &&); virtual SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData &&); virtual SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData &&); virtual SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData &&); virtual SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData &&); virtual SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData &&); virtual void StartArray(sprawl::String const& , uint32_t&, bool = true); virtual void EndArray(); virtual uint32_t StartObject(sprawl::String const& , bool = true); virtual void EndObject(); virtual uint32_t StartMap(sprawl::String const& s, bool b = true); virtual void EndMap(); virtual sprawl::String GetNextKey(); virtual StringSet GetDeletedKeys(sprawl::String const&); virtual SPRAWL_WARN_UNUSED_RESULT ErrorState serialize(int* var, const uint32_t bytes, sprawl::String const& name, bool PersistToDB) = 0; virtual SPRAWL_WARN_UNUSED_RESULT ErrorState serialize(long int* var, const uint32_t bytes, sprawl::String const& name, bool PersistToDB) = 0; virtual SPRAWL_WARN_UNUSED_RESULT ErrorState serialize(long long int* var, const uint32_t bytes, sprawl::String const& name, bool PersistToDB) = 0; virtual SPRAWL_WARN_UNUSED_RESULT ErrorState serialize(short int* var, const uint32_t bytes, sprawl::String const& name, bool PersistToDB) = 0; virtual SPRAWL_WARN_UNUSED_RESULT ErrorState serialize(char* var, const uint32_t bytes, sprawl::String const& name, bool PersistToDB) = 0; virtual SPRAWL_WARN_UNUSED_RESULT ErrorState serialize(float* var, const uint32_t bytes, sprawl::String const& name, bool PersistToDB) = 0; virtual SPRAWL_WARN_UNUSED_RESULT ErrorState serialize(double* var, const uint32_t bytes, sprawl::String const& name, bool PersistToDB) = 0; virtual SPRAWL_WARN_UNUSED_RESULT ErrorState serialize(long double* var, const uint32_t bytes, sprawl::String const& name, bool PersistToDB) = 0; virtual SPRAWL_WARN_UNUSED_RESULT ErrorState serialize(bool* var, const uint32_t bytes, sprawl::String const& name, bool PersistToDB) = 0; virtual SPRAWL_WARN_UNUSED_RESULT ErrorState serialize(unsigned int* var, const uint32_t bytes, sprawl::String const& name, bool PersistToDB) = 0; virtual SPRAWL_WARN_UNUSED_RESULT ErrorState serialize(unsigned long int* var, const uint32_t bytes, sprawl::String const& name, bool PersistToDB) = 0; virtual SPRAWL_WARN_UNUSED_RESULT ErrorState serialize(unsigned long long int* var, const uint32_t bytes, sprawl::String const& name, bool PersistToDB) = 0; virtual SPRAWL_WARN_UNUSED_RESULT ErrorState serialize(unsigned short int* var, const uint32_t bytes, sprawl::String const& name, bool PersistToDB) = 0; virtual SPRAWL_WARN_UNUSED_RESULT ErrorState serialize(unsigned char* var, const uint32_t bytes, sprawl::String const& name, bool PersistToDB) = 0; virtual SPRAWL_WARN_UNUSED_RESULT ErrorState serialize(std::string* var, const uint32_t bytes, sprawl::String const& name, bool PersistToDB) = 0; virtual SPRAWL_WARN_UNUSED_RESULT ErrorState serialize(sprawl::String* var, const uint32_t bytes, sprawl::String const& name, bool PersistToDB) = 0; protected: virtual SPRAWL_WARN_UNUSED_RESULT ErrorState GetAnother(sprawl::String const& /*data*/); virtual SPRAWL_WARN_UNUSED_RESULT ErrorState GetAnother(); #ifdef _WIN32 #pragma warning(pop) #endif template SPRAWL_WARN_UNUSED_RESULT ErrorState to_string( T& val, std::true_type) { sprawl::StringBuilder b; b << val; return b.Str(); } template SPRAWL_WARN_UNUSED_RESULT ErrorState to_string( T& val, std::false_type) { SerializerBase* s = this->GetAnother(); SPRAWL_RETHROW(*s % prepare_data( val, "key", false )); sprawl::String data = s->Str(); delete s; return std::move(data); } template SPRAWL_WARN_UNUSED_RESULT ErrorState get_from_string( sprawl::String const& data, T& val, std::false_type ) { SerializerBase* d = this->GetAnother(data); SPRAWL_RETHROW(*d % prepare_data( val, "key", false )); delete d; return ErrorState(); } template SPRAWL_WARN_UNUSED_RESULT ErrorState get_from_string( sprawl::String const& data, T& val, std::true_type ) { ///TODO: Get rid of std::stringstream here std::stringstream s(data.toStdString()); s >> val; return ErrorState(); } template SPRAWL_WARN_UNUSED_RESULT ErrorState OneOff( sprawl::String& data, T& val ) { if(IsLoading()) { if(IsBinary()) { SPRAWL_RETHROW(get_from_string(data, val, std::false_type())); } else { SPRAWL_RETHROW(get_from_string(data, val, typename std::is_arithmetic::type())); } } else { if(IsBinary()) { SPRAWL_RETHROW_OR_GET(to_string(val, std::false_type()), data); } else { SPRAWL_RETHROW_OR_GET(to_string(val, typename std::is_arithmetic::type()), data); } } return ErrorState(); } public: template::value >::type > SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(T&& var) { return *this % prepare_data(var, "noname", false); } #if !SPRAWL_EXCEPTIONS_ENABLED template< typename T, typename = typename std::enable_if< std::is_base_of().Serialize(std::declval()))>::value >::type > SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { StartObject(var.name, var.PersistToDB); SPRAWL_RETHROW(var.val.Serialize(*this)); EndObject(); return *this; } template< typename T, typename = typename std::enable_if< std::is_base_of().Serialize(std::declval()))>::value >::type > SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { StartObject(var.name, var.PersistToDB); SPRAWL_RETHROW(var.val->Serialize(*this)); EndObject(); return *this; } #endif template< typename T #if !SPRAWL_EXCEPTIONS_ENABLED , typename = typename std::enable_if< !std::is_base_of().Serialize(std::declval()))>::value >::type, typename = typename std::enable_if< !std::is_base_of().Serialize(std::declval()))>::value >::type #endif > SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { StartObject(var.name, var.PersistToDB); var.val.Serialize(*this); EndObject(); return *this; } template< typename T #if !SPRAWL_EXCEPTIONS_ENABLED , typename = typename std::enable_if< !std::is_base_of().Serialize(std::declval()))>::value >::type, typename = typename std::enable_if< !std::is_base_of().Serialize(std::declval()))>::value >::type #endif > SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { StartObject(var.name, var.PersistToDB); var.val->Serialize(*this); EndObject(); return *this; } template SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData>&& var) { bool hasValue = (var.val != nullptr); SPRAWL_RETHROW(*this % prepare_data(hasValue, var.name+"_exists", var.PersistToDB)); if(hasValue) { if(IsLoading() && !var.val) { var.val.reset( new T() ); } SPRAWL_RETHROW(*this % prepare_data(*var.val, var.name, var.PersistToDB)); } else if(IsLoading()) { var.val.reset(); } return *this; } virtual const char* Data() = 0; virtual SPRAWL_WARN_UNUSED_RESULT ErrorState Data(sprawl::String const&){ return ErrorState(); } virtual sprawl::String Str() = 0; virtual ~SerializerBase(){} protected: template SPRAWL_WARN_UNUSED_RESULT ErrorState serialize(T& var, const uint32_t bytes, sprawl::String const& name, bool PersistToDB) { SPRAWL_RETHROW(serialize(&var, bytes, name, PersistToDB)); return ErrorState(); } //Usually does nothing, but has to be here for mongo serializer to work properly with OIDs. friend ErrorState operator%(SerializerBase& s, SerializationData&& var); friend ErrorState operator%(SerializerBase& s, SerializationData&& var); friend ErrorState operator%(SerializerBase& s, SerializationData&& var); virtual SPRAWL_WARN_UNUSED_RESULT ErrorState serialize(mongo::OID* /*var*/, sprawl::String const& /*name*/, bool /*PersistToDB*/) { return ErrorState(); } virtual SPRAWL_WARN_UNUSED_RESULT ErrorState serialize(mongo::BSONObj* /*var*/, sprawl::String const& /*name*/, bool /*PersistToDB*/) { return ErrorState(); } virtual SPRAWL_WARN_UNUSED_RESULT ErrorState serialize(mongo::Date_t* /*var*/, sprawl::String const& /*name*/, bool /*PersistToDB*/) { return ErrorState(); } SerializerBase() {} private: SerializerBase(SerializerBase const&); SerializerBase& operator=(SerializerBase const&); }; class Serializer : virtual public SerializerBase { public: using SerializerBase::operator%; template::value >::type > SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { T cVar = var.val; return *this % prepare_data(cVar, var.name, var.PersistToDB); } #ifndef _WIN32 template SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(T&& var) { return *this % prepare_data(var, "noname", true); } #if !SPRAWL_EXCEPTIONS_ENABLED template< typename T, typename = typename std::enable_if< std::is_base_of().Serialize(std::declval()))>::value >::type > SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { StartObject(var.name, var.PersistToDB); SPRAWL_RETHROW(var.val.Serialize(*this)); EndObject(); return *this; } #endif template< typename T #if !SPRAWL_EXCEPTIONS_ENABLED , typename = typename std::enable_if< !std::is_base_of().Serialize(std::declval()))>::value >::type, typename = typename std::enable_if< !std::is_base_of().Serialize(std::declval()))>::value >::type #endif > SPRAWL_WARN_UNUSED_RESULT ErrorState operator%(SerializationData&& var) { StartObject(var.name, var.PersistToDB); var.val.Serialize(*this); EndObject(); return *this; } #endif virtual ~Serializer(); virtual bool IsLoading() override; protected: Serializer(); }; class Deserializer : virtual public SerializerBase { public: using SerializerBase::operator%; using SerializerBase::Data; virtual SPRAWL_WARN_UNUSED_RESULT ErrorState Data(sprawl::String const& str) = 0; virtual SPRAWL_WARN_UNUSED_RESULT ErrorState Data(const char* data, size_t length) = 0; virtual ~Deserializer(); virtual bool IsLoading() override; protected: Deserializer(); }; } }