From 43cb068d539d71a08ebf5b25f045c5f4275ffbaf Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 15 Mar 2013 19:17:40 +0100 Subject: [PATCH 01/18] eoserial:: const correctness for String. --- eo/src/serial/String.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/eo/src/serial/String.h b/eo/src/serial/String.h index 526cab365..2ef1f94f5 100644 --- a/eo/src/serial/String.h +++ b/eo/src/serial/String.h @@ -62,7 +62,7 @@ namespace eoserial * @param value The value in which we're writing. */ template - inline void deserialize( T & value ); + inline void deserialize( T & value ) const; protected: // Copy and reaffectation are forbidden @@ -80,7 +80,7 @@ namespace eoserial * invoking. */ template - inline void String::deserialize( T & value ) + inline void String::deserialize( T & value ) const { std::stringstream ss; ss.precision(std::numeric_limits::digits10 + 1); @@ -93,7 +93,7 @@ namespace eoserial * a stringstream. */ template<> - inline void String::deserialize( std::string & value ) + inline void String::deserialize( std::string & value ) const { value = *this; } From 10148ae00bb5e41a73f156db60c949b04847c019 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 15 Mar 2013 19:26:32 +0100 Subject: [PATCH 02/18] eoserial: renamed String/Object/Array into Serial* to avoid compiler confusion. --- eo/src/serial/CMakeLists.txt | 6 +++--- eo/src/serial/Parser.cpp | 6 +++--- eo/src/serial/Parser.h | 4 ++-- eo/src/serial/{Array.cpp => SerialArray.cpp} | 2 +- eo/src/serial/{Array.h => SerialArray.h} | 2 +- eo/src/serial/{Object.cpp => SerialObject.cpp} | 2 +- eo/src/serial/{Object.h => SerialObject.h} | 0 eo/src/serial/{String.cpp => SerialString.cpp} | 2 +- eo/src/serial/{String.h => SerialString.h} | 0 eo/src/serial/Utils.h | 6 +++--- eo/src/serial/eoSerial.h | 6 +++--- 11 files changed, 18 insertions(+), 18 deletions(-) rename eo/src/serial/{Array.cpp => SerialArray.cpp} (98%) rename eo/src/serial/{Array.h => SerialArray.h} (99%) rename eo/src/serial/{Object.cpp => SerialObject.cpp} (98%) rename eo/src/serial/{Object.h => SerialObject.h} (100%) rename eo/src/serial/{String.cpp => SerialString.cpp} (97%) rename eo/src/serial/{String.h => SerialString.h} (100%) diff --git a/eo/src/serial/CMakeLists.txt b/eo/src/serial/CMakeLists.txt index 43d1ce451..efc9f42e2 100644 --- a/eo/src/serial/CMakeLists.txt +++ b/eo/src/serial/CMakeLists.txt @@ -13,10 +13,10 @@ set(EOSERIAL_LIB_OUTPUT_PATH ${EO_BIN_DIR}/lib) set(LIBRARY_OUTPUT_PATH ${EOSERIAL_LIB_OUTPUT_PATH}) set(EOSERIAL_SOURCES - Array.cpp - Object.cpp + SerialArray.cpp + SerialObject.cpp Parser.cpp - String.cpp + SerialString.cpp ) add_library(eoserial STATIC ${EOSERIAL_SOURCES}) diff --git a/eo/src/serial/Parser.cpp b/eo/src/serial/Parser.cpp index 57b52a0dd..e78b35392 100644 --- a/eo/src/serial/Parser.cpp +++ b/eo/src/serial/Parser.cpp @@ -23,9 +23,9 @@ Authors: # include "Parser.h" -# include "Array.h" -# include "Object.h" -# include "String.h" +# include "SerialArray.h" +# include "SerialObject.h" +# include "SerialString.h" // in debug mode only // # define DEBUG(x) std::cout << x << std::endl; diff --git a/eo/src/serial/Parser.h b/eo/src/serial/Parser.h index 20f6a1bb2..392f25ffa 100644 --- a/eo/src/serial/Parser.h +++ b/eo/src/serial/Parser.h @@ -23,8 +23,8 @@ Authors: # define __EOSERIAL_PARSER_H__ # include "Entity.h" -# include "String.h" -# include "Object.h" +# include "SerialString.h" +# include "SerialObject.h" /** * @file Parser.h diff --git a/eo/src/serial/Array.cpp b/eo/src/serial/SerialArray.cpp similarity index 98% rename from eo/src/serial/Array.cpp rename to eo/src/serial/SerialArray.cpp index 180aad16b..5282370f5 100644 --- a/eo/src/serial/Array.cpp +++ b/eo/src/serial/SerialArray.cpp @@ -19,7 +19,7 @@ Contact: http://eodev.sourceforge.net Authors: Benjamin Bouvier */ -# include "Array.h" +# include "SerialArray.h" namespace eoserial { diff --git a/eo/src/serial/Array.h b/eo/src/serial/SerialArray.h similarity index 99% rename from eo/src/serial/Array.h rename to eo/src/serial/SerialArray.h index d453add99..b349953aa 100644 --- a/eo/src/serial/Array.h +++ b/eo/src/serial/SerialArray.h @@ -26,7 +26,7 @@ Authors: # include "Entity.h" # include "Serializable.h" -# include "Object.h" +# include "SerialObject.h" namespace eoserial { diff --git a/eo/src/serial/Object.cpp b/eo/src/serial/SerialObject.cpp similarity index 98% rename from eo/src/serial/Object.cpp rename to eo/src/serial/SerialObject.cpp index dd859052e..e926e448f 100644 --- a/eo/src/serial/Object.cpp +++ b/eo/src/serial/SerialObject.cpp @@ -19,7 +19,7 @@ Contact: http://eodev.sourceforge.net Authors: Benjamin Bouvier */ -# include "Object.h" +# include "SerialObject.h" using namespace eoserial; diff --git a/eo/src/serial/Object.h b/eo/src/serial/SerialObject.h similarity index 100% rename from eo/src/serial/Object.h rename to eo/src/serial/SerialObject.h diff --git a/eo/src/serial/String.cpp b/eo/src/serial/SerialString.cpp similarity index 97% rename from eo/src/serial/String.cpp rename to eo/src/serial/SerialString.cpp index c50882786..6d49106cc 100644 --- a/eo/src/serial/String.cpp +++ b/eo/src/serial/SerialString.cpp @@ -19,7 +19,7 @@ Contact: http://eodev.sourceforge.net Authors: Benjamin Bouvier */ -# include "String.h" +# include "SerialString.h" namespace eoserial { diff --git a/eo/src/serial/String.h b/eo/src/serial/SerialString.h similarity index 100% rename from eo/src/serial/String.h rename to eo/src/serial/SerialString.h diff --git a/eo/src/serial/Utils.h b/eo/src/serial/Utils.h index 33172a747..13b6877b1 100644 --- a/eo/src/serial/Utils.h +++ b/eo/src/serial/Utils.h @@ -22,9 +22,9 @@ Authors: # ifndef __EOSERIAL_UTILS_H__ # define __EOSERIAL_UTILS_H__ -# include "Array.h" -# include "Object.h" -# include "String.h" +# include "SerialArray.h" +# include "SerialObject.h" +# include "SerialString.h" namespace eoserial { diff --git a/eo/src/serial/eoSerial.h b/eo/src/serial/eoSerial.h index 55a116f0c..8ea3a9764 100644 --- a/eo/src/serial/eoSerial.h +++ b/eo/src/serial/eoSerial.h @@ -22,10 +22,10 @@ Authors: # ifndef __EOSERIAL_HEADERS__ # define __EOSERIAL_HEADERS__ -# include "Object.h" +# include "SerialObject.h" # include "Serializable.h" -# include "Array.h" -# include "Object.h" +# include "SerialArray.h" +# include "SerialObject.h" # include "String.h" # include "Parser.h" # include "Utils.h" From f412139549c3b837ecc70cd29dc8aa9940ed5592 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 15 Mar 2013 20:33:25 +0100 Subject: [PATCH 03/18] eoserial: bugfix: String -> SerialString. --- eo/src/serial/eoSerial.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/eo/src/serial/eoSerial.h b/eo/src/serial/eoSerial.h index 8ea3a9764..fec5fb4dd 100644 --- a/eo/src/serial/eoSerial.h +++ b/eo/src/serial/eoSerial.h @@ -22,11 +22,10 @@ Authors: # ifndef __EOSERIAL_HEADERS__ # define __EOSERIAL_HEADERS__ -# include "SerialObject.h" # include "Serializable.h" # include "SerialArray.h" # include "SerialObject.h" -# include "String.h" +# include "SerialString.h" # include "Parser.h" # include "Utils.h" From eb047ed39c5d1e948b76448cad8429c336af0902 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 15 Mar 2013 20:33:50 +0100 Subject: [PATCH 04/18] eoserial: easy serialization with eoserial::serialize and eoserial::deserialize. --- eo/src/serial/Serialize.h | 245 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 eo/src/serial/Serialize.h diff --git a/eo/src/serial/Serialize.h b/eo/src/serial/Serialize.h new file mode 100644 index 000000000..1a1e99ca1 --- /dev/null +++ b/eo/src/serial/Serialize.h @@ -0,0 +1,245 @@ +/* +(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 snippet example code below. + * + * @code + * # include + * # include + * + * class MyObject: public eoserial::Persistent + * { + * public: + * + * int value; + * MyObject( int v ) : value(v) {} + * + * eoserial::Entity* 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 ); + * return 0; + * } + * @endcode + * + * @todo Encapsulate non 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 // std::runtime_error +# include // std::is_convertible (C++11) + +# include "SerialString.h" +# include "SerialObject.h" +# include "SerialArray.h" +# include "Utils.h" + +namespace eoserial +{ + + template + eoserial::Entity* serialize( const T & arg ); + + template + void deserialize( const eoserial::Entity& json, const std::string& field, T & value ); + + /* ************************* + * PRIVATE FUNCTIONS ******* + * Use at your own risk! *** + **************************/ + + template + eoserial::Entity* makeSimple( const T & arg ) + { + throw std::runtime_error("eoSerial: makeSimple called with an unknown basic type."); + return 0; + } + + template + eoserial::Entity* makeObject( const T & arg ) + { + throw std::runtime_error("eoSerial: makeObject called with an non eoserial::Printable type."); + return 0; + } + + + template + void deserializeSimple( const eoserial::Entity* json, T & value ) + { + std::runtime_error("eoSerial: deserializeSimple called with an unknown basic type."); + } + + template + void deserializeObject( const eoserial::Entity* json, T & value ) + { + std::runtime_error("eoSerial:: deserializeObject called with a non eoserial::Persistent object."); + } + + template<> + eoserial::Entity* makeObject( const eoserial::Printable & arg ) + { + return arg.pack(); + } + + +# 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(std::string) +# undef MKSIMPLE + + +# 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(std::string); +# undef DSSIMPLE + + template<> + void deserializeObject( const eoserial::Entity* json, eoserial::Persistent & value ) + { + value.unpack( static_cast( json ) ); + } + + template + eoserial::Entity* makeSimple( const std::vector & v ) + { + eoserial::Array* array = new eoserial::Array; + for( auto it = v.begin(), end = v.end(); + it != end; + ++it ) + { + array->push_back( eoserial::serialize( *it ) ); + } + return array; + } + + template + void deserializeBase( const eoserial::Entity* json, T & value ); + + template< class T > + void deserializeSimple( const eoserial::Entity* json, std::vector & v ) + { + const eoserial::Array* sArray = static_cast(json); + for( auto it = sArray->begin(), end = sArray->end(); + it != end; + ++it ) + { + T single; + eoserial::deserializeBase( *it, single ); + v.push_back( single ); + } + } + + 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 ); + } + } + + template + eoserial::Entity* serialize( const T & arg ) + { + if( std::is_convertible::value ) + { + return eoserial::makeObject( reinterpret_cast(arg) ); + } else { + return eoserial::makeSimple( arg ); + } + } + + 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 ); + } +} + + From dc0f995ff4f0de4a91163c64d45c056ec84f53ff Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 22 Mar 2013 00:37:25 +0100 Subject: [PATCH 05/18] eoserial: typos (comment + throw exceptions) --- eo/src/serial/Serialize.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/eo/src/serial/Serialize.h b/eo/src/serial/Serialize.h index 1a1e99ca1..f833f427a 100644 --- a/eo/src/serial/Serialize.h +++ b/eo/src/serial/Serialize.h @@ -78,7 +78,7 @@ Authors: * } * @endcode * - * @todo Encapsulate non private functions. As of today (2013-03-19), it is not + * @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). * @@ -129,13 +129,13 @@ namespace eoserial template void deserializeSimple( const eoserial::Entity* json, T & value ) { - std::runtime_error("eoSerial: deserializeSimple called with an unknown basic type."); + throw std::runtime_error("eoSerial: deserializeSimple called with an unknown basic type."); } template void deserializeObject( const eoserial::Entity* json, T & value ) { - std::runtime_error("eoSerial:: deserializeObject called with a non eoserial::Persistent object."); + throw std::runtime_error("eoSerial:: deserializeObject called with a non eoserial::Persistent object."); } template<> From f7e2a6ea7fd75fb86f9186877909e17acc346a4e Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 22 Mar 2013 00:37:59 +0100 Subject: [PATCH 06/18] eoserial: support char + std::list --- eo/src/serial/Serialize.h | 41 ++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/eo/src/serial/Serialize.h b/eo/src/serial/Serialize.h index f833f427a..fe3d21ab8 100644 --- a/eo/src/serial/Serialize.h +++ b/eo/src/serial/Serialize.h @@ -88,6 +88,7 @@ Authors: */ # include +# include # include # include // std::runtime_error # include // std::is_convertible (C++11) @@ -157,6 +158,7 @@ namespace eoserial MKSIMPLE(long) MKSIMPLE(float) MKSIMPLE(double) + MKSIMPLE(char) MKSIMPLE(std::string) # undef MKSIMPLE @@ -173,6 +175,7 @@ namespace eoserial DSSIMPLE(long); DSSIMPLE(float); DSSIMPLE(double); + DSSIMPLE(char); DSSIMPLE(std::string); # undef DSSIMPLE @@ -182,11 +185,11 @@ namespace eoserial value.unpack( static_cast( json ) ); } - template - eoserial::Entity* makeSimple( const std::vector & v ) + template + eoserial::Entity* makeSimpleIterable( const Container & c ) { eoserial::Array* array = new eoserial::Array; - for( auto it = v.begin(), end = v.end(); + for( auto it = c.begin(), end = c.end(); it != end; ++it ) { @@ -195,23 +198,47 @@ namespace eoserial return array; } + template + eoserial::Entity* makeSimple( const std::vector & v ) + { + return makeSimpleIterable( v ); + } + + template + eoserial::Entity* makeSimple( const std::list & l ) + { + return makeSimpleIterable( l ); + } + template void deserializeBase( const eoserial::Entity* json, T & value ); - template< class T > - void deserializeSimple( const eoserial::Entity* json, std::vector & v ) + 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 ) { - T single; + typename Container::value_type single; eoserial::deserializeBase( *it, single ); - v.push_back( 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 ); + } + template void deserializeBase( const eoserial::Entity* json, T & value ) { From 834dcb1bd602078944a4f500828a98af13ba3181 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 22 Mar 2013 01:13:44 +0100 Subject: [PATCH 07/18] eoserial: comments for Serialize. --- eo/src/serial/Serialize.h | 246 +++++++++++++++++++++++++++++--------- 1 file changed, 189 insertions(+), 57 deletions(-) diff --git a/eo/src/serial/Serialize.h b/eo/src/serial/Serialize.h index fe3d21ab8..b3d5c2c1b 100644 --- a/eo/src/serial/Serialize.h +++ b/eo/src/serial/Serialize.h @@ -26,7 +26,7 @@ Authors: * This file contains primitive to make serialization and * deserialization easy. * - * See the snippet example code below. + * See the example code snippet below. * * @code * # include @@ -39,7 +39,7 @@ Authors: * int value; * MyObject( int v ) : value(v) {} * - * eoserial::Entity* pack() const + * eoserial::Object* pack() const * { * eoserial::Object* e = new eoserial::Object; * (*e)["the_value"] = eoserial::serialize( value ); @@ -74,6 +74,13 @@ Authors: * 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 @@ -101,9 +108,42 @@ Authors: 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 ); @@ -112,6 +152,15 @@ namespace eoserial * 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 ) { @@ -119,6 +168,12 @@ namespace eoserial 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 ) { @@ -126,26 +181,10 @@ namespace eoserial return 0; } - - template - void deserializeSimple( const eoserial::Entity* json, T & value ) - { - throw std::runtime_error("eoSerial: deserializeSimple called with an unknown basic type."); - } - - template - void deserializeObject( const eoserial::Entity* json, T & value ) - { - throw std::runtime_error("eoSerial:: deserializeObject called with a non eoserial::Persistent object."); - } - - template<> - eoserial::Entity* makeObject( const eoserial::Printable & arg ) - { - return arg.pack(); - } - - + /* + * 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 ) \ { \ @@ -160,31 +199,14 @@ namespace eoserial MKSIMPLE(double) MKSIMPLE(char) MKSIMPLE(std::string) -# undef MKSIMPLE - - -# 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 - - template<> - void deserializeObject( const eoserial::Entity* json, eoserial::Persistent & value ) - { - value.unpack( static_cast( json ) ); - } +# 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 ) { @@ -210,9 +232,108 @@ namespace eoserial 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 ) { @@ -239,6 +360,23 @@ namespace eoserial 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 ) { @@ -250,17 +388,11 @@ namespace eoserial } } - template - eoserial::Entity* serialize( const T & arg ) - { - if( std::is_convertible::value ) - { - return eoserial::makeObject( reinterpret_cast(arg) ); - } else { - return eoserial::makeSimple( arg ); - } - } - + /* + * 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 ) { From 9ff8c7e499967c0bf23079f3a6362662ab2bf1a6 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 22 Mar 2013 01:14:18 +0100 Subject: [PATCH 08/18] eoserial: added Serialize by default for eoserial. --- eo/src/serial/eoSerial.h | 1 + 1 file changed, 1 insertion(+) diff --git a/eo/src/serial/eoSerial.h b/eo/src/serial/eoSerial.h index fec5fb4dd..ee3a70c78 100644 --- a/eo/src/serial/eoSerial.h +++ b/eo/src/serial/eoSerial.h @@ -28,5 +28,6 @@ Authors: # include "SerialString.h" # include "Parser.h" # include "Utils.h" +# include "Serialize.h" # endif // __EOSERIAL_HEADERS__ From d2680f986baf7a7382e308a0bd98137b02019d92 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 22 Mar 2013 17:01:12 +0100 Subject: [PATCH 09/18] eoserial: traits for knowing whether a class is derived from another one at compile time. Thanks Herb Sutter --- eo/src/serial/Traits.h | 58 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 eo/src/serial/Traits.h diff --git a/eo/src/serial/Traits.h b/eo/src/serial/Traits.h new file mode 100644 index 000000000..7cce0959e --- /dev/null +++ b/eo/src/serial/Traits.h @@ -0,0 +1,58 @@ +/* +(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 +*/ +# ifndef __EOSERIAL_TRAITS_H__ +# define __EOSERIAL_TRAITS_H__ + +/** + * @file Traits.h + * + * Traits used for serialization purposes. + * + * @author Benjamin Bouvier + */ + +namespace eoserial +{ + + /** + * @brief Trait to know whether Derived is derived from Base or not. + * + * To know whether A is derived from B, just test the boolean IsDerivedFrom::value. + * + * @see http://www.gotw.ca/publications/mxc++-item-4.htm + */ + template + class IsDerivedFrom + { + struct no{}; + struct yes{ no _[2]; }; + + static yes Test( Base* something ); + static no Test( ... ); + + public: + enum { value = sizeof( Test( static_cast(0) ) ) == sizeof(yes) }; + }; + +} + +# endif // __EOSERIAL_TRAITS_H__ From a98563b1189ec59921ab64335784c1b788f271e9 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 22 Mar 2013 17:05:19 +0100 Subject: [PATCH 10/18] eoserial: removed Serialize.h (something else coming soon...) --- eo/src/serial/Serialize.h | 404 -------------------------------------- eo/src/serial/eoSerial.h | 1 - 2 files changed, 405 deletions(-) delete mode 100644 eo/src/serial/Serialize.h 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__ From 5ab91c61392cf42f8d96839013cb7aacd09d3700 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 22 Mar 2013 17:05:42 +0100 Subject: [PATCH 11/18] eoserial: merged former Serialize.h with Utils.h: pack / unpack. --- eo/src/serial/Utils.h | 132 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 130 insertions(+), 2 deletions(-) diff --git a/eo/src/serial/Utils.h b/eo/src/serial/Utils.h index 13b6877b1..8046bb557 100644 --- a/eo/src/serial/Utils.h +++ b/eo/src/serial/Utils.h @@ -26,6 +26,22 @@ Authors: # include "SerialObject.h" # include "SerialString.h" +# include "Traits.h" + +# include + +/** + * @file Utils.h + * + * @brief Contains utilities for simple serialization and deserialization. + * + * @todo comment new version. + * + * @todo encapsulate implementations. + * + * @todo provide more composite implementations (map) + */ + namespace eoserial { /* *************************** @@ -42,11 +58,123 @@ namespace eoserial */ template< class T > - inline void unpack( const Object & obj, const std::string & key, T & value ) + inline void unpackBasePushBack( const Entity* obj, T& container ) { - static_cast( obj.find( key )->second )->deserialize( value ); + const Array* arr = static_cast( obj ); + for( auto it = arr->begin(), end = arr->end(); + it != end; + ++it ) + { + typename T::value_type item; + unpackBase( *it, item ); + container.push_back( item ); + } } + template< class T > + inline void unpackBase( const Entity* obj, std::vector& v ) + { + unpackBasePushBack( obj, v ); + } + + template< class T > + inline void unpackBase( const Entity* obj, std::list& l ) + { + unpackBasePushBack( obj, l ); + } + + template + struct UnpackImpl + { + void operator()( const Entity* obj, T& value ) + { + static_cast( obj )->deserialize( value ); + } + }; + + template + struct UnpackImpl + { + void operator()( const Entity* obj, T& value ) + { + value.unpack( static_cast(obj) ); + } + }; + + template + inline void unpackBase( const Entity* obj, T& value ) + { + UnpackImpl< T, IsDerivedFrom< T, Persistent >::value > impl; + impl( obj, value ); + } + + template + inline void unpack( const Object& obj, const std::string& key, T& value ) + { + unpackBase( obj.find(key)->second, value ); + } + + /* ******************* + * SERIALIZATION ***** + ********************/ + + template + struct PackImpl + { + Entity* operator()( const T& value ) + { + std::stringstream ss; + ss.precision(std::numeric_limits::digits10 + 1); + ss << value; + return new String(ss.str()); + } + }; + + template + struct PackImpl + { + Entity* operator()( const T& value ) + { + return value.pack(); + } + }; + + template + inline Entity* pack( const T& value ); + + template + inline Entity* packIterable( const T& container ) + { + Array* arr = new Array; + for( auto it = container.begin(), end = container.end(); + it != end; + ++it ) + { + arr->push_back( pack(*it) ); + } + return arr; + } + + template + inline Entity* pack( const std::vector& v ) + { + return packIterable( v ); + } + + template + inline Entity* pack( const std::list& l ) + { + return packIterable( l ); + } + + template + inline Entity* pack( const T& value ) + { + PackImpl::value> impl; + return impl( value ); + } + + // Kept for compatibility inline void unpackObject( const Object & obj, const std::string & key, Persistent & value ) { static_cast( obj.find( key )->second )->deserialize( value ); From a9bdf2d51b1e262958f7cd760f430d2010f87651 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 22 Mar 2013 17:46:20 +0100 Subject: [PATCH 12/18] eoserial: comments Utils.h --- eo/src/serial/Utils.h | 95 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 80 insertions(+), 15 deletions(-) diff --git a/eo/src/serial/Utils.h b/eo/src/serial/Utils.h index 8046bb557..323283ccf 100644 --- a/eo/src/serial/Utils.h +++ b/eo/src/serial/Utils.h @@ -35,28 +35,24 @@ Authors: * * @brief Contains utilities for simple serialization and deserialization. * - * @todo comment new version. - * * @todo encapsulate implementations. * * @todo provide more composite implementations (map) + * + * @todo provide example + * + * @author Benjamin Bouvier */ namespace eoserial { - /* *************************** - * DESERIALIZATION FUNCTIONS * - ***************************** - These functions are useful for casting eoserial::objects into simple, primitive - variables or into class instance which implement eoserial::Persistent. - - The model is always quite the same : - - the first argument is the containing object (which is a eoserial::Entity, - an object or an array) - - the second argument is the key or index, - - the last argument is the value in which we're writing. - */ + /* ***************** + * DESERIALIZATION * + ******************/ + /** + * @brief Recursively unpack elements of an object which implements push_back. + */ template< class T > inline void unpackBasePushBack( const Entity* obj, T& container ) { @@ -71,18 +67,30 @@ namespace eoserial } } + /** + * @brief Unpack method for std::vector + */ template< class T > inline void unpackBase( const Entity* obj, std::vector& v ) { unpackBasePushBack( obj, v ); } + /** + * @brief Unpack method for std::list + */ template< class T > inline void unpackBase( const Entity* obj, std::list& l ) { unpackBasePushBack( obj, l ); } + /** + * @brief Unpack implementation for non eoserial::Persistent objects. + * + * This implementation is being used for every objects that can be transmitted + * to a std::ostream (i.e. which implements the operator <<) + */ template struct UnpackImpl { @@ -92,6 +100,9 @@ namespace eoserial } }; + /** + * @brief Unpack implementation for eoserial::Persistent objects. + */ template struct UnpackImpl { @@ -101,6 +112,14 @@ namespace eoserial } }; + /** + * @brief Unpack helper for determining which implementation to use. + * + * The trick comes from Herb Sutter: IsDerivedFrom::value is + * true if and only if T inherits from Persistent. In this case, it's equal + * to 1, thus the partial specialization of UnpackImpl is used. In the other + * case, it's equal to 0 and the generic implementation is used. + */ template inline void unpackBase( const Entity* obj, T& value ) { @@ -108,6 +127,13 @@ namespace eoserial impl( obj, value ); } + /** + * @brief Universal unpack method. + * + * @param obj The eoserial::object containing the value to deserialize. + * @param key Name of the field to deserialize + * @param value The object in which we'll store the deserialized value. + */ template inline void unpack( const Object& obj, const std::string& key, T& value ) { @@ -118,6 +144,12 @@ namespace eoserial * SERIALIZATION ***** ********************/ + /** + * @brief Pack implementation for non eoserial::Printable objects. + * + * This implementation is being used for every objects that can be transmitted + * to a std::istream (i.e. which implements the operator >>) + */ template struct PackImpl { @@ -130,6 +162,9 @@ namespace eoserial } }; + /** + * @brief Pack implementation for eoserial::Printable objects. + */ template struct PackImpl { @@ -139,9 +174,13 @@ namespace eoserial } }; + // Pre declaration for being usable in packIterable. template inline Entity* pack( const T& value ); + /** + * @brief Pack method for iterable (begin, end) objects. + */ template inline Entity* packIterable( const T& container ) { @@ -155,18 +194,32 @@ namespace eoserial return arr; } + /** + * @brief Pack method for std::vector + */ template inline Entity* pack( const std::vector& v ) { return packIterable( v ); } + /** + * @brief Pack method for std::list + */ template inline Entity* pack( const std::list& l ) { return packIterable( l ); } + /** + * @brief Universal pack method. + * + * @see unpackBase to understand the trick with the implementation. + * + * @param value Variable to store into an entity. + * @return An entity to store into an object. + */ template inline Entity* pack( const T& value ) { @@ -174,7 +227,19 @@ namespace eoserial return impl( value ); } - // Kept for compatibility + /** ************** + * OLD FUNCTIONS * + **************** + These functions are useful for casting eoserial::objects into simple, primitive + variables or into class instance which implement eoserial::Persistent. + + The model is always quite the same : + - the first argument is the containing object (which is a eoserial::Entity, + an object or an array) + - the second argument is the key or index, + - the last argument is the value in which we're writing. + + */ inline void unpackObject( const Object & obj, const std::string & key, Persistent & value ) { static_cast( obj.find( key )->second )->deserialize( value ); From 6c148f8ae2c7b49ce1e1567f1f89ca213a207547 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 22 Mar 2013 17:53:50 +0100 Subject: [PATCH 13/18] eoserial: example of using the new-new serialization --- eo/src/serial/Utils.h | 91 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/eo/src/serial/Utils.h b/eo/src/serial/Utils.h index 323283ccf..4d943bf63 100644 --- a/eo/src/serial/Utils.h +++ b/eo/src/serial/Utils.h @@ -39,7 +39,96 @@ Authors: * * @todo provide more composite implementations (map) * - * @todo provide example + * Example + * + * @code +# include +# include +# include + +# include "eoSerial.h" + +struct SimpleObject: public eoserial::Persistent +{ + public: + + SimpleObject( int v ) : value(v) + { + // empty + } + + eoserial::Object* pack() const + { + eoserial::Object* obj = new eoserial::Object; + (*obj)["value"] = eoserial::pack( value ); + return obj; + } + + void unpack( const eoserial::Object* json ) + { + eoserial::unpack( *json, "value", value ); + } + + int value; +}; + +int main() +{ + eoserial::Object o; + + std::cout << "packing..." << std::endl; + // directly pack raw types + o["long"] = eoserial::pack(123456L); + o["bool"] = eoserial::pack(true); + o["double"] = eoserial::pack(3.141592653); + o["float"] = eoserial::pack(3.141592653f); + + std::string str = "Hello, world!"; + o["str"] = eoserial::pack( str ); + + // pack objects the same way + SimpleObject obj(42); + o["obj"] = eoserial::pack( obj ); + + // pack vector and list the same way + std::vector vec; + vec.push_back(1); + vec.push_back(3); + vec.push_back(3); + vec.push_back(7); + o["vec"] = eoserial::pack( vec ); + + // print it + o.print( std::cout ); + + std::cout << "unpacking..." << std::endl; + + // unpack as easily raw types + long oneTwoThreeFourFiveSix = 0L; + eoserial::unpack( o, "long", oneTwoThreeFourFiveSix); + std::cout << "the long: " << oneTwoThreeFourFiveSix << std::endl; + + // since vec is encoded as an internal eoserial::Array, it can be + // decoded into a std::vector or a std::list without difference. + std::list lis; + eoserial::unpack( o, "vec", lis ); + + std::cout << "the list: "; + for( auto it = lis.begin(), end = lis.end(); it != end; ++it) + { + std::cout << *it << ';'; + } + std::cout << std::endl; + + obj.value = -1; + // unpack object the same way + eoserial::unpack( o, "obj", obj ); + std::cout << "obj.value = " << obj.value << std::endl; + + return 0; +} + +@endcode * * @author Benjamin Bouvier */ From 95e4dfc625359100aeae219b11d3d751a6642f8f Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 22 Mar 2013 18:03:36 +0100 Subject: [PATCH 14/18] eoserial: packing and unpacking of map --- eo/src/serial/Utils.h | 44 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/eo/src/serial/Utils.h b/eo/src/serial/Utils.h index 4d943bf63..b6ea360b3 100644 --- a/eo/src/serial/Utils.h +++ b/eo/src/serial/Utils.h @@ -29,6 +29,7 @@ Authors: # include "Traits.h" # include +# include /** * @file Utils.h @@ -37,8 +38,6 @@ Authors: * * @todo encapsulate implementations. * - * @todo provide more composite implementations (map) - * * Example * * @code @@ -98,6 +97,12 @@ int main() vec.push_back(7); o["vec"] = eoserial::pack( vec ); + std::map str2int; + str2int["one"] = 1; + str2int["two"] = 2; + str2int["answer"] = 42; + o["map"] = eoserial::pack( str2int ); + // print it o.print( std::cout ); @@ -120,6 +125,10 @@ int main() } std::cout << std::endl; + std::map< std::string, int > readMap; + eoserial::unpack( o, "map", readMap ); + std::cout << "The answer is " << readMap["answer"] << std::endl; + obj.value = -1; // unpack object the same way eoserial::unpack( o, "obj", obj ); @@ -174,6 +183,21 @@ namespace eoserial unpackBasePushBack( obj, l ); } + /** + * @brief Unpack method for std::map< std::string, T > + */ + template< class T > + inline void unpackBase( const Entity* entity, std::map & m ) + { + const Object* obj = static_cast< const Object* >( entity ); + for( auto it = obj->begin(), end = obj->end(); + it != end; + ++it ) + { + unpackBase( it->second, m[ it->first ] ); + } + } + /** * @brief Unpack implementation for non eoserial::Persistent objects. * @@ -301,6 +325,22 @@ namespace eoserial return packIterable( l ); } + /** + * @brief Pack method for std::map< std::string, T > + */ + template + inline Entity* pack( const std::map& map ) + { + Object* obj = new Object; + for( auto it = map.begin(), end = map.end(); + it != end; + ++it ) + { + (*obj)[ it->first ] = pack( it->second ); + } + return obj; + } + /** * @brief Universal pack method. * From c197e6b28669c70fc4c67cda6750c9d070df68fe Mon Sep 17 00:00:00 2001 From: canape Date: Thu, 18 Apr 2013 08:55:00 +0200 Subject: [PATCH 15/18] BUG GNUPLOT: corrected by Titus Cieslewski --- eo/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/eo/CMakeLists.txt b/eo/CMakeLists.txt index 9b6962f2c..9966de557 100644 --- a/eo/CMakeLists.txt +++ b/eo/CMakeLists.txt @@ -21,6 +21,8 @@ endif(ENABLE_OPENMP) if(ENABLE_GNUPLOT) include(FindGnuplot) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DHAVE_GNUPLOT -DGNUPLOT_PROGRAM=\\\"${GNUPLOT_EXECUTABLE}\\\"") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_GNUPLOT -DGNUPLOT_PROGRAM=\\\"${GNUPLOT_EXECUTABLE}\\\"") endif(ENABLE_GNUPLOT) # set a special flag if the environment is windows (should do the same in a config.g file) From 35212ccc906586f68b574947756bbf57aee74dab Mon Sep 17 00:00:00 2001 From: Lionel Parreaux Date: Mon, 6 May 2013 15:27:19 +0200 Subject: [PATCH 16/18] adapted eoLogger for redirecting to ostreams --- eo/src/utils/eoLogger.cpp | 48 +++++++++++++++++++++++++++------------ eo/src/utils/eoLogger.h | 31 ++++++++++++++----------- eo/test/t-eoLogger.cpp | 24 ++++++++++++++++++-- 3 files changed, 73 insertions(+), 30 deletions(-) diff --git a/eo/src/utils/eoLogger.cpp b/eo/src/utils/eoLogger.cpp index 1330c5323..3a9b20098 100644 --- a/eo/src/utils/eoLogger.cpp +++ b/eo/src/utils/eoLogger.cpp @@ -40,6 +40,11 @@ Caner Candan #include "eoLogger.h" +/* TODO? +- changer oprateurs +- virer la structure "file" +*/ + void eoLogger::_init() { _standard_io_streams[&std::cout] = 1; @@ -55,6 +60,8 @@ void eoLogger::_init() addLevel("logging", eo::logging); addLevel("debug", eo::debug); addLevel("xdebug", eo::xdebug); + + //outStream = &std::cout; } eoLogger::eoLogger() : @@ -66,13 +73,12 @@ eoLogger::eoLogger() : _selectedLevel(eo::progress), _contextLevel(eo::quiet), - _fd(2), - _obuf(_fd, _contextLevel, _selectedLevel) + _obuf(_contextLevel, _selectedLevel) { std::ostream::init(&_obuf); _init(); } - +/* eoLogger::eoLogger(eo::file file) : std::ostream(NULL), @@ -88,11 +94,11 @@ eoLogger::eoLogger(eo::file file) : std::ostream::init(&_obuf); _init(); *this << file; -} +}*/ eoLogger::~eoLogger() { - if (_fd > 2) { ::close(_fd); } + //if (_fd > 2) { ::close(_fd); } } void eoLogger::_createParameters( eoParser& parser ) @@ -112,11 +118,14 @@ void eoLogger::_createParameters( eoParser& parser ) //------------------------------------------------------------------ // we're gonna redirect the log to the given filename if -o is used. //------------------------------------------------------------------ - +/* if ( ! _output.value().empty() ) { eo::log << eo::file( _output.value() ); } +*/ +// TODO with a stream + //------------------------------------------------------------------ @@ -162,12 +171,12 @@ eoLogger& operator<<(eoLogger& l, const eo::Levels lvl) l._contextLevel = lvl; return l; } - +/* eoLogger& operator<<(eoLogger& l, eo::file f) { l._fd = ::open(f._f.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0644); return l; -} +}*/ eoLogger& operator<<(eoLogger& l, eo::setlevel v) { @@ -177,26 +186,35 @@ eoLogger& operator<<(eoLogger& l, eo::setlevel v) eoLogger& operator<<(eoLogger& l, std::ostream& os) { +/* if (l._standard_io_streams.find(&os) != l._standard_io_streams.end()) { l._fd = l._standard_io_streams[&os]; } +*/ + l._obuf.outStream = &os; return l; } -eoLogger::outbuf::outbuf(const int& fd, - const eo::Levels& contexlvl, +void eoLogger::redirectTo(std::ostream& os) +{ + _obuf.outStream = &os; +} + + +eoLogger::outbuf::outbuf(const eo::Levels& contexlvl, const eo::Levels& selectedlvl) - : _fd(fd), _contextLevel(contexlvl), _selectedLevel(selectedlvl) + : outStream(&std::cout), /*ownedFileStream(NULL),*/ _contextLevel(contexlvl), _selectedLevel(selectedlvl) {} int eoLogger::outbuf::overflow(int_type c) { if (_selectedLevel >= _contextLevel) { - if (_fd >= 0 && c != EOF) + if (outStream && c != EOF) { - ::write(_fd, &c, 1); + //::write(_fd, &c, 1); + (*outStream) << (char) c; } } return c; @@ -204,9 +222,9 @@ int eoLogger::outbuf::overflow(int_type c) namespace eo { - file::file(const std::string f) + /*file::file(const std::string f) : _f(f) - {} + {}*/ setlevel::setlevel(const std::string v) : _v(v), _lvl((Levels)-1) diff --git a/eo/src/utils/eoLogger.h b/eo/src/utils/eoLogger.h index 9ac1c2115..99bafa001 100644 --- a/eo/src/utils/eoLogger.h +++ b/eo/src/utils/eoLogger.h @@ -91,6 +91,7 @@ Caner Candan #include #include #include +#include #include "eoObject.h" #include "eoParser.h" @@ -113,12 +114,12 @@ namespace eo /** * file * this structure combined with the friend operator<< below is an easy way to select a file as output. - */ + * struct file { explicit file(const std::string f); const std::string _f; - }; + };*/ /** * setlevel @@ -146,7 +147,7 @@ public: eoLogger(); //! overidded ctor in order to instanciate a logger with a file define in parameter - eoLogger(eo::file file); + //eoLogger(eo::file file); //! dtor ~eoLogger(); @@ -189,11 +190,12 @@ private: class outbuf : public std::streambuf { public: - outbuf(const int& fd, const eo::Levels& contexlvl, const eo::Levels& selectedlvl); + outbuf(const eo::Levels& contexlvl, const eo::Levels& selectedlvl); + std::ostream * outStream; protected: virtual int overflow(int_type c); private: - const int& _fd; + //std::ofstream * ownedFileStream; const eo::Levels& _contextLevel; const eo::Levels& _selectedLevel; }; @@ -215,7 +217,7 @@ public: * operator<< used there to set a filename through the class file. */ //! in order to use stream style to define a file to dump instead the standart output - friend eoLogger& operator<<(eoLogger&, eo::file); + //friend eoLogger& operator<<(eoLogger&, eo::file); /** * operator<< used there to set a verbose level through the class setlevel. @@ -224,12 +226,21 @@ public: friend eoLogger& operator<<(eoLogger&, eo::setlevel); /** + * DEPRECATED: Use instead the redirectTo method * operator<< used there to be able to use std::cout to say that we wish to redirect back the buffer to a standard output. */ //! in order to use stream style to go back to a standart output defined by STL //! and to get retro-compatibility +#warning deprecated friend eoLogger& operator<<(eoLogger&, std::ostream&); + /** + * Redirects the logger to a given output stream. Closing the stream and returning its memory is at the charge of the caller, + * but should not be done while the log is still redirected to it. + */ + void redirectTo(std::ostream&); + + private: friend void make_verbose(eoParser&); @@ -244,13 +255,7 @@ private: eo::Levels _contextLevel; /** - * _fd in storing the file descriptor at this place we can disable easily the buffer in - * changing the value at -1. It is used by operator <<. - */ - int _fd; - - /** - * _obuf std::ostream mandates to use a buffer. _obuf is a outbuf inheriting of std::streambuf. + * _obuf std::ostream mandates to use a buffer. _obuf is a outbuf inheriting from std::streambuf. */ outbuf _obuf; diff --git a/eo/test/t-eoLogger.cpp b/eo/test/t-eoLogger.cpp index 198a88720..65f9df603 100644 --- a/eo/test/t-eoLogger.cpp +++ b/eo/test/t-eoLogger.cpp @@ -3,6 +3,10 @@ //----------------------------------------------------------------------------- #include +//#include +#include +#include +#include //----------------------------------------------------------------------------- @@ -25,8 +29,24 @@ int main(int ac, char** av) eo::log << "We are writing on the default output stream" << std::endl; - eo::log << eo::file("test.txt") << "In FILE" << std::endl; - eo::log << std::cout << "on COUT" << std::endl; + //eo::log << eo::file("test.txt") << "In FILE" << std::endl; + + std::ofstream ofs("test.txt"); + //eo::log << ofs << "In FILE" << std::endl; + eo::log.redirectTo(ofs); + eo::log << "In FILE" << std::endl; + + std::ostringstream oss; + //eo::log << oss << "In STRINGSTREAM"; + eo::log.redirectTo(oss); + eo::log << oss << "In STRINGSTREAM"; + + //ofs << oss; + std::cout << "Content of ostringstream: " << oss.str() << std::endl; + + //eo::log << std::cout << "on COUT" << std::endl; + eo::log.redirectTo(std::cout); + eo::log << "on COUT" << std::endl; eo::log << eo::setlevel("errors"); eo::log << eo::setlevel(eo::errors); From 002e4a196469f301e0dbb7fa0215ca85f9da88a5 Mon Sep 17 00:00:00 2001 From: Lionel Parreaux Date: Mon, 6 May 2013 17:33:36 +0200 Subject: [PATCH 17/18] added possibility to open files and close them automatically --- eo/src/utils/eoLogger.cpp | 87 ++++++++++++++++----------------------- eo/src/utils/eoLogger.h | 18 ++++---- eo/test/t-eoLogger.cpp | 11 +++-- 3 files changed, 52 insertions(+), 64 deletions(-) diff --git a/eo/src/utils/eoLogger.cpp b/eo/src/utils/eoLogger.cpp index 3a9b20098..79813137c 100644 --- a/eo/src/utils/eoLogger.cpp +++ b/eo/src/utils/eoLogger.cpp @@ -47,9 +47,6 @@ Caner Candan void eoLogger::_init() { - _standard_io_streams[&std::cout] = 1; - _standard_io_streams[&std::clog] = 2; - _standard_io_streams[&std::cerr] = 2; // /!\ If you want to add a level dont forget to add it at the header file in the enumerator Levels @@ -61,7 +58,6 @@ void eoLogger::_init() addLevel("debug", eo::debug); addLevel("xdebug", eo::xdebug); - //outStream = &std::cout; } eoLogger::eoLogger() : @@ -78,27 +74,13 @@ eoLogger::eoLogger() : std::ostream::init(&_obuf); _init(); } -/* -eoLogger::eoLogger(eo::file file) : - std::ostream(NULL), - - _verbose("quiet", "verbose", "Set the verbose level", 'v'), - _printVerboseLevels(false, "print-verbose-levels", "Print verbose levels", 'l'), - _output("", "output", "Redirect a standard output to a file", 'o'), - - _selectedLevel(eo::progress), - _contextLevel(eo::quiet), - _fd(2), - _obuf(_fd, _contextLevel, _selectedLevel) -{ - std::ostream::init(&_obuf); - _init(); - *this << file; -}*/ eoLogger::~eoLogger() { - //if (_fd > 2) { ::close(_fd); } + //redirect(NULL); + if (_obuf._ownedFileStream != NULL) { + delete _obuf._ownedFileStream; + } } void eoLogger::_createParameters( eoParser& parser ) @@ -116,22 +98,21 @@ void eoLogger::_createParameters( eoParser& parser ) //------------------------------------------------------------------ - // we're gonna redirect the log to the given filename if -o is used. + // we redirect the log to the given filename if -o is used. //------------------------------------------------------------------ -/* + if ( ! _output.value().empty() ) { - eo::log << eo::file( _output.value() ); + redirect(_output.value()); } -*/ -// TODO with a stream + //------------------------------------------------------------------ //------------------------------------------------------------------ - // we're gonna print the list of levels if -l parameter is used. + // we print the list of levels if -l parameter is used. //------------------------------------------------------------------ if ( _printVerboseLevels.value() ) @@ -171,12 +152,6 @@ eoLogger& operator<<(eoLogger& l, const eo::Levels lvl) l._contextLevel = lvl; return l; } -/* -eoLogger& operator<<(eoLogger& l, eo::file f) -{ - l._fd = ::open(f._f.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0644); - return l; -}*/ eoLogger& operator<<(eoLogger& l, eo::setlevel v) { @@ -186,35 +161,49 @@ eoLogger& operator<<(eoLogger& l, eo::setlevel v) eoLogger& operator<<(eoLogger& l, std::ostream& os) { -/* - if (l._standard_io_streams.find(&os) != l._standard_io_streams.end()) - { - l._fd = l._standard_io_streams[&os]; - } -*/ - l._obuf.outStream = &os; + l._obuf._outStream = &os; return l; } -void eoLogger::redirectTo(std::ostream& os) +void eoLogger::redirect(std::ostream& os) { - _obuf.outStream = &os; + if (_obuf._ownedFileStream != NULL) { + delete _obuf._ownedFileStream; + _obuf._ownedFileStream = NULL; + } + _obuf._outStream = &os; +} + +void eoLogger::redirect(const char * filename) +{ + std::ofstream * os; + if (filename == NULL) { + os = NULL; + } else { + os = new std::ofstream(filename); + } + redirect(*os); + _obuf._ownedFileStream = os; +} + +void eoLogger::redirect(const std::string& filename) +{ + redirect(filename.c_str()); } eoLogger::outbuf::outbuf(const eo::Levels& contexlvl, const eo::Levels& selectedlvl) - : outStream(&std::cout), /*ownedFileStream(NULL),*/ _contextLevel(contexlvl), _selectedLevel(selectedlvl) + : _outStream(&std::cout), _ownedFileStream(NULL), _contextLevel(contexlvl), _selectedLevel(selectedlvl) {} int eoLogger::outbuf::overflow(int_type c) { if (_selectedLevel >= _contextLevel) { - if (outStream && c != EOF) + if (_outStream && c != EOF) { - //::write(_fd, &c, 1); - (*outStream) << (char) c; + (*_outStream) << (char) c; } } return c; @@ -222,10 +211,6 @@ int eoLogger::outbuf::overflow(int_type c) namespace eo { - /*file::file(const std::string f) - : _f(f) - {}*/ - setlevel::setlevel(const std::string v) : _v(v), _lvl((Levels)-1) {} diff --git a/eo/src/utils/eoLogger.h b/eo/src/utils/eoLogger.h index 99bafa001..e655848c7 100644 --- a/eo/src/utils/eoLogger.h +++ b/eo/src/utils/eoLogger.h @@ -191,11 +191,11 @@ private: { public: outbuf(const eo::Levels& contexlvl, const eo::Levels& selectedlvl); - std::ostream * outStream; + std::ostream * _outStream; + std::ofstream * _ownedFileStream; protected: virtual int overflow(int_type c); private: - //std::ofstream * ownedFileStream; const eo::Levels& _contextLevel; const eo::Levels& _selectedLevel; }; @@ -213,12 +213,6 @@ public: //! in order to use stream style to define the context verbose level where the following logs will be saved friend eoLogger& operator<<(eoLogger&, const eo::Levels); - /** - * operator<< used there to set a filename through the class file. - */ - //! in order to use stream style to define a file to dump instead the standart output - //friend eoLogger& operator<<(eoLogger&, eo::file); - /** * operator<< used there to set a verbose level through the class setlevel. */ @@ -238,8 +232,14 @@ public: * Redirects the logger to a given output stream. Closing the stream and returning its memory is at the charge of the caller, * but should not be done while the log is still redirected to it. */ - void redirectTo(std::ostream&); + void redirect(std::ostream&); + /** + * Redirects the logger to a file using a filename. + * Closing the file will be done automatically when the logger is redirected again or destroyed. + */ + void redirect(const char * filename); + void redirect(const std::string& filename); private: friend void make_verbose(eoParser&); diff --git a/eo/test/t-eoLogger.cpp b/eo/test/t-eoLogger.cpp index 65f9df603..a1ea4b60c 100644 --- a/eo/test/t-eoLogger.cpp +++ b/eo/test/t-eoLogger.cpp @@ -31,21 +31,24 @@ int main(int ac, char** av) //eo::log << eo::file("test.txt") << "In FILE" << std::endl; - std::ofstream ofs("test.txt"); + std::ofstream ofs("logtest.txt"); //eo::log << ofs << "In FILE" << std::endl; - eo::log.redirectTo(ofs); + eo::log.redirect(ofs); eo::log << "In FILE" << std::endl; + + eo::log.redirect("logtest2.txt"); + eo::log << "In FILE 2" << std::endl; std::ostringstream oss; //eo::log << oss << "In STRINGSTREAM"; - eo::log.redirectTo(oss); + eo::log.redirect(oss); eo::log << oss << "In STRINGSTREAM"; //ofs << oss; std::cout << "Content of ostringstream: " << oss.str() << std::endl; //eo::log << std::cout << "on COUT" << std::endl; - eo::log.redirectTo(std::cout); + eo::log.redirect(std::cout); eo::log << "on COUT" << std::endl; eo::log << eo::setlevel("errors"); From 1c8ff46848dd9856eab6c43419a885ec3404c188 Mon Sep 17 00:00:00 2001 From: LPTK Date: Wed, 5 Jun 2013 15:46:33 +0200 Subject: [PATCH 18/18] cooling schedule changes --- mo/src/coolingSchedule/moCoolingSchedule.h | 3 +- .../moDynSpanCoolingSchedule.h | 39 ++++++++++--------- .../coolingSchedule/moSimpleCoolingSchedule.h | 6 ++- mo/src/explorer/moSAexplorer.h | 2 +- mo/test/t-moDynSpanCoolingSchedule.cpp | 18 ++++----- mo/test/t-moSimpleCoolingSchedule.cpp | 18 ++++----- 6 files changed, 45 insertions(+), 41 deletions(-) diff --git a/mo/src/coolingSchedule/moCoolingSchedule.h b/mo/src/coolingSchedule/moCoolingSchedule.h index 9b65cf1b5..b9863b02f 100644 --- a/mo/src/coolingSchedule/moCoolingSchedule.h +++ b/mo/src/coolingSchedule/moCoolingSchedule.h @@ -55,8 +55,9 @@ public: * update the temperature * @param _temp current temperature to update * @param _acceptedMove true when the move is accepted, false otherwise + * @param _currentSolution the current solution */ - virtual void update(double& _temp, bool _acceptedMove) = 0; + virtual void update(double& _temp, bool _acceptedMove, EOT & _currentSolution) = 0; }; diff --git a/mo/src/coolingSchedule/moDynSpanCoolingSchedule.h b/mo/src/coolingSchedule/moDynSpanCoolingSchedule.h index 34b386312..4e6216ad5 100644 --- a/mo/src/coolingSchedule/moDynSpanCoolingSchedule.h +++ b/mo/src/coolingSchedule/moDynSpanCoolingSchedule.h @@ -80,26 +80,27 @@ public: * update the temperature by a factor * @param _temp current temperature to update * @param _acceptedMove true when the move is accepted, false otherwise + * @param _currentSolution the current solution */ - virtual void update(double& _temp, bool _acceptedMove) { - spanTries++; - - if (_acceptedMove) - spanMove++; - - if (spanTries >= spanTriesMax || spanMove >= spanMoveMax) { - _temp *= alpha; - - if (spanMove == 0) // no move during this span ? - nbSpan++; - else - nbSpan = 0; - - spanTries = 0; - spanMove = 0; - } - } - + virtual void update(double& _temp, bool _acceptedMove, EOT & _currentSolution) { + spanTries++; + + if (_acceptedMove) + spanMove++; + + if (spanTries >= spanTriesMax || spanMove >= spanMoveMax) { + _temp *= alpha; + + if (spanMove == 0) // no move during this span ? + nbSpan++; + else + nbSpan = 0; + + spanTries = 0; + spanMove = 0; + } + } + /** * compare the number of span with no move * @param _temp current temperature diff --git a/mo/src/coolingSchedule/moSimpleCoolingSchedule.h b/mo/src/coolingSchedule/moSimpleCoolingSchedule.h index 5ff4f4920..aa8f1138f 100644 --- a/mo/src/coolingSchedule/moSimpleCoolingSchedule.h +++ b/mo/src/coolingSchedule/moSimpleCoolingSchedule.h @@ -52,7 +52,8 @@ public: * @param _span number of iteration with equal temperature * @param _finalT final temperature, threshold of the stopping criteria */ - moSimpleCoolingSchedule(double _initT, double _alpha, unsigned _span, double _finalT) : initT(_initT), alpha(_alpha), span(_span), finalT(_finalT) {} + moSimpleCoolingSchedule(double _initT, double _alpha, unsigned _span, double _finalT) + : initT(_initT), alpha(_alpha), span(_span), finalT(_finalT) {} /** * Getter on the initial temperature @@ -70,8 +71,9 @@ public: * update the temperature by a factor * @param _temp current temperature to update * @param _acceptedMove true when the move is accepted, false otherwise + * @param _currentSolution the current solution */ - virtual void update(double& _temp, bool _acceptedMove) { + virtual void update(double& _temp, bool _acceptedMove, EOT & _currentSolution) { if (step >= span) { _temp *= alpha; step = 0; diff --git a/mo/src/explorer/moSAexplorer.h b/mo/src/explorer/moSAexplorer.h index 3d9f477ee..37fa57955 100644 --- a/mo/src/explorer/moSAexplorer.h +++ b/mo/src/explorer/moSAexplorer.h @@ -96,7 +96,7 @@ public: * @param _solution unused solution */ virtual void updateParam(EOT & _solution) { - coolingSchedule.update(temperature, this->moveApplied()); + coolingSchedule.update(temperature, this->moveApplied(), _solution); }; /** diff --git a/mo/test/t-moDynSpanCoolingSchedule.cpp b/mo/test/t-moDynSpanCoolingSchedule.cpp index 7bef4ad59..da67008ea 100755 --- a/mo/test/t-moDynSpanCoolingSchedule.cpp +++ b/mo/test/t-moDynSpanCoolingSchedule.cpp @@ -48,38 +48,38 @@ int main() { assert(temperature == 100); //temperature must not changed 2* - test.update(temperature, 0); + test.update(temperature, 0, sol); assert(temperature == 100); assert(test(temperature)); - test.update(temperature, 0); + test.update(temperature, 0, sol); assert(temperature == 100); assert(test(temperature)); //then temperature must be /10 - test.update(temperature, 0); + test.update(temperature, 0, sol); assert(temperature == 10); assert(test(temperature)); - test.update(temperature, 0); + test.update(temperature, 0, sol); assert(temperature == 10); assert(test(temperature)); - test.update(temperature, 0); + test.update(temperature, 0, sol); assert(temperature == 10); assert(test(temperature)); - test.update(temperature, 0); + test.update(temperature, 0, sol); assert(temperature == 1); std::cout << "\n"; assert(test(temperature)); - test.update(temperature, 0); + test.update(temperature, 0, sol); std::cout << "\n"; assert(temperature == 1); assert(test(temperature)); - test.update(temperature, 0); + test.update(temperature, 0, sol); std::cout << "\n"; assert(temperature == 1); assert(test(temperature)); - test.update(temperature, 0); + test.update(temperature, 0, sol); assert(temperature == 0.1); assert(!test(temperature)); diff --git a/mo/test/t-moSimpleCoolingSchedule.cpp b/mo/test/t-moSimpleCoolingSchedule.cpp index b2f8cca17..dc78c6870 100644 --- a/mo/test/t-moSimpleCoolingSchedule.cpp +++ b/mo/test/t-moSimpleCoolingSchedule.cpp @@ -48,38 +48,38 @@ int main() { assert(temperature==100); //temperature must not changed 2* - test.update(temperature,0); + test.update(temperature,0,sol); assert(temperature==100); assert(test(temperature)); - test.update(temperature,0); + test.update(temperature,0,sol); assert(temperature==100); assert(test(temperature)); //then temperature must be /10 - test.update(temperature,0); + test.update(temperature,0,sol); assert(temperature==10); assert(test(temperature)); - test.update(temperature,0); + test.update(temperature,0,sol); assert(temperature==10); assert(test(temperature)); - test.update(temperature,0); + test.update(temperature,0,sol); assert(temperature==10); assert(test(temperature)); - test.update(temperature,0); + test.update(temperature,0,sol); assert(temperature == 1); std::cout<< "\n"; assert(test(temperature)); - test.update(temperature,0); + test.update(temperature,0,sol); std::cout<< "\n"; assert(temperature==1); assert(test(temperature)); - test.update(temperature,0); + test.update(temperature,0,sol); std::cout<< "\n"; assert(temperature==1); assert(test(temperature)); - test.update(temperature,0); + test.update(temperature,0,sol); assert(temperature==0.1); assert(!test(temperature));