diff --git a/eo/src/serial/Serialize.h b/eo/src/serial/Serialize.h deleted file mode 100644 index b3d5c2c1b..000000000 --- a/eo/src/serial/Serialize.h +++ /dev/null @@ -1,404 +0,0 @@ -/* -(c) Benjamin Bouvier, 2013 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; - version 2 of the License. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Contact: http://eodev.sourceforge.net - -Authors: - Benjamin Bouvier -*/ - -/** - * @file Serialize.h - * - * This file contains primitive to make serialization and - * deserialization easy. - * - * See the example code snippet below. - * - * @code - * # include - * # include - * - * class MyObject: public eoserial::Persistent - * { - * public: - * - * int value; - * MyObject( int v ) : value(v) {} - * - * eoserial::Object* pack() const - * { - * eoserial::Object* e = new eoserial::Object; - * (*e)["the_value"] = eoserial::serialize( value ); - * return e; - * } - * - * void unpack( const eoserial::Object* o ) - * { - * eoserial::deserialize( *o, "the_value", value ); - * } - * }; - * - * int main() - * { - * eoserial::Object o; - * o["long"] = eoserial::serialize(123456L); - * o["bool"] = eoserial::serialize(true); - * o["double"] = eoserial::serialize(3.141592653); - * o["float"] = eoserial::serialize(3.141592653f); - * - * std::string str = "Hello, world!"; - * o["str"] = eoserial::serialize( str ); - * - * MyObject obj(42); - * o["obj"] = eoserial::serialize( obj ); - * - * std::vector vec; - * vec.push_back(1); - * vec.push_back(3); - * vec.push_back(3); - * vec.push_back(7); - * o["vec"] = eoserial::serialize( vec ); - * - * o.print( std::cout ); - * - * std::list lis; - * eoserial::deserialize( o, "vec", lis ); - * - * long oneTwoThreeFourFiveSix; - * eoserial::deserialize( o, "long", oneTwoThreeFourFiveSix); - * - * return 0; - * } - * @endcode - * - * @todo Encapsulate private functions. As of today (2013-03-19), it is not - * possible as GCC and Clang refuse to have std::vector specializations of template methods (while it works with - * functions). - * - * @todo Comments coming soon. - * - * @author Benjamin Bouvier - */ - -# include -# include -# include -# include // std::runtime_error -# include // std::is_convertible (C++11) - -# include "SerialString.h" -# include "SerialObject.h" -# include "SerialArray.h" -# include "Utils.h" - -namespace eoserial -{ - - /** - * @brief Tries to serialize the given argument into an Entity. - * - * This function can be called with any argument of the following kinds: - * - basic types (int, bool, float, double, char, short, long) - * - standard STL types (std::string, std::list, std::vector). In - * this case, the serialization is automatically called on the - * contained objects. - * - objects which implement eoserial::Printable - * - * @param arg The argument to serialize. - * @return an Entity to be used with the serialization module. - * - * @throws std::runtime_exception when the type T is not known or - * not convertible to a known type. - */ - template - eoserial::Entity* serialize( const T & arg ); - - /** - * @brief Tries to deserialize the given argument from the given field in the entity and loads it into the in-out - * given value. - * - * This function is the reverse operator of the serialize function: - * - basic types are supported - * - standard STL types (std::string, std::list, std::vector) - * - objects which implement eoserial::Persistent - * @see serialize - * - * @param json The entity containing the variable to deserialize - * @param field The name of the field used in the original object - * @param value The in-out value in which we want to store the result of the deserialization. - * - * @throws std::runtime_exception when the type T is not known or - * not convertible to a known type. - */ - template - void deserialize( const eoserial::Entity& json, const std::string& field, T & value ); - - /* ************************* - * PRIVATE FUNCTIONS ******* - * Use at your own risk! *** - **************************/ - - /* ************************* - * SERIALIZATION *********** - **************************/ - - /** - * @brief Function to be called for non eoserial::Printable objects. - * - * The default behaviour is to throw a runtime exception. The function is then specialized for known types. - */ - template - eoserial::Entity* makeSimple( const T & arg ) - { - throw std::runtime_error("eoSerial: makeSimple called with an unknown basic type."); - return 0; - } - - /** - * @brief Function to be called for eoserial::Printable objects and only these ones. - * - * The default behaviour is to throw a runtime exception. The function is specialized only for eoserial::Printable - * object. - */ - template - eoserial::Entity* makeObject( const T & arg ) - { - throw std::runtime_error("eoSerial: makeObject called with an non eoserial::Printable type."); - return 0; - } - - /* - * Specializations of makeSimple for basic types. - * Macro MKSIMPLE can be used to register any type that can be printed into a std::ostream. - */ -# define MKSIMPLE(A) template<>\ - eoserial::Entity* makeSimple( const A& arg ) \ - { \ - return eoserial::make(arg); \ - } \ - - MKSIMPLE(bool) - MKSIMPLE(int) - MKSIMPLE(short) - MKSIMPLE(long) - MKSIMPLE(float) - MKSIMPLE(double) - MKSIMPLE(char) - MKSIMPLE(std::string) -# undef MKSIMPLE // avoids undebuggable surprises - - /** - * @brief Base specialization for objects iterable thanks to - * begin(), end() and basic iterators. - * - * This specialization is used for std::list and std::vector. - */ - template - eoserial::Entity* makeSimpleIterable( const Container & c ) - { - eoserial::Array* array = new eoserial::Array; - for( auto it = c.begin(), end = c.end(); - it != end; - ++it ) - { - array->push_back( eoserial::serialize( *it ) ); - } - return array; - } - - template - eoserial::Entity* makeSimple( const std::vector & v ) - { - return makeSimpleIterable( v ); - } - - template - eoserial::Entity* makeSimple( const std::list & l ) - { - return makeSimpleIterable( l ); - } - - /** - * @brief Specialization of makeObject for eoserial::Printable. - * - * For these objects, we can directly use their pack method. - */ - template<> - eoserial::Entity* makeObject( const eoserial::Printable & arg ) - { - return arg.pack(); - } - - /* - * @brief Implementation of Serialize function. - * - * The idea is the following: - * - either the object implements eoserial::Printable and can be serialized directly with makeObject - * - or it's not, and thus we have to try the registered types. - * - * The difficulty of this function is to be callable with any kind of argument, whatever the type. For that purpose, - * templating is frequently used with default behaviours being erroneous. This way, the compiler can try all - * branches of the conditional and find an implementation of the function that works for the given type. - * This trick is used as the templates functions (and methods) are invariant in C++: if A inherits B, the specialization - * f() is not used when calling with the parameter A. - */ - template - eoserial::Entity* serialize( const T & arg ) - { - // static check (introduced by C++11) - // - avoids the invariant template issue - if( std::is_convertible::value ) - { - // at this point, we are sure that we can cast the argument into an eoserial::Printable. - // reinterpret_cast has to be used, otherwise static_cast and dynamic_cast will fail at compile time for - // basic types. - return eoserial::makeObject( reinterpret_cast(arg) ); - } else { - // not an eoserial::Printable, try registered types - return eoserial::makeSimple( arg ); - } - } - - - /* ***************** - * DESERIALIZATION * - ******************/ - - /** - * @brief Function to be called for non eoserial::Persistent objects. - * - * The default behaviour is to throw a runtime exception. The function is then specialized for known types. - */ - template - void deserializeSimple( const eoserial::Entity* json, T & value ) - { - throw std::runtime_error("eoSerial: deserializeSimple called with an unknown basic type."); - } - - /** - * @brief Function to be called for eoserial::Persistent objects and only these ones. - * - * The default behaviour is to throw a runtime exception. The function is specialized only for eoserial::Persistent - * object. - */ - template - void deserializeObject( const eoserial::Entity* json, T & value ) - { - throw std::runtime_error("eoSerial:: deserializeObject called with a non eoserial::Persistent object."); - } - - /* - * Specializations of deserializeSimple for basic types. - * Macro DSSIMPLE can be used to register any type that can be read from a std::istream. - */ -# define DSSIMPLE(A) template<> \ - void deserializeSimple( const eoserial::Entity* json, A & value ) \ - { \ - static_cast(json)->deserialize( value ); \ - } - - DSSIMPLE(bool); - DSSIMPLE(int); - DSSIMPLE(short); - DSSIMPLE(long); - DSSIMPLE(float); - DSSIMPLE(double); - DSSIMPLE(char); - DSSIMPLE(std::string); -# undef DSSIMPLE // avoids undebuggable surprises - - /** - * @brief Deserialize function with two arguments. - * - * Used by list and vector containers. - */ - template - void deserializeBase( const eoserial::Entity* json, T & value ); - - /** - * @brief Base specialization for objects that implement push_back. - * - * This specialization is used for std::list and std::vector. - */ - template< class Container > - void deserializeSimplePushBack( const eoserial::Entity* json, Container & c ) - { - const eoserial::Array* sArray = static_cast(json); - for( auto it = sArray->begin(), end = sArray->end(); - it != end; - ++it ) - { - typename Container::value_type single; - eoserial::deserializeBase( *it, single ); - c.push_back( single ); - } - } - - template< class T > - void deserializeSimple( const eoserial::Entity* json, std::vector & v ) - { - deserializeSimplePushBack( json, v ); - } - - template< class T > - void deserializeSimple( const eoserial::Entity* json, std::list & v ) - { - deserializeSimplePushBack( json, v ); - } - - /** - * @brief Specialization of deserializeObject for eoserial::Persistent. - * - * For these objects, we can directly use their unpack method. - */ - template<> - void deserializeObject( const eoserial::Entity* json, eoserial::Persistent & value ) - { - value.unpack( static_cast( json ) ); - } - - /* - * Implementation of deserializeBase. - * - * For technical comments, @see makeSimple. The followed scheme - * is exactly the same. - */ - template - void deserializeBase( const eoserial::Entity* json, T & value ) - { - if( std::is_convertible< T*, eoserial::Persistent*>::value ) - { - eoserial::deserializeObject( json, reinterpret_cast( value ) ); - } else { - eoserial::deserializeSimple( json, value ); - } - } - - /* - * Implementation of deserialize. - * - * Simply calls the deserializeBase function with the corresponding Entity. - */ - template - void deserialize( const eoserial::Entity& json, const std::string& field, T & value ) - { - const eoserial::Entity* jField = static_cast(json).find(field)->second; - eoserial::deserializeBase( jField, value ); - } -} - - diff --git a/eo/src/serial/eoSerial.h b/eo/src/serial/eoSerial.h index ee3a70c78..fec5fb4dd 100644 --- a/eo/src/serial/eoSerial.h +++ b/eo/src/serial/eoSerial.h @@ -28,6 +28,5 @@ Authors: # include "SerialString.h" # include "Parser.h" # include "Utils.h" -# include "Serialize.h" # endif // __EOSERIAL_HEADERS__