From 3a3deb245c282f18299be2dc64de9831d5feafc1 Mon Sep 17 00:00:00 2001
From: Mansard <nmansard@laas.fr>
Date: Wed, 2 Feb 2011 16:28:27 +0100
Subject: [PATCH] IVIGIT: transfert some code and automatic-code-generation
 macros from sot-core to dg.

---
 include/CMakeLists.txt                     |   1 +
 include/dynamic-graph/signal-cast-helper.h | 215 +++++++++++++++++++++
 src/CMakeLists.txt                         |   1 +
 src/signal/signal-cast-helper.cpp          |  79 ++++++++
 4 files changed, 296 insertions(+)
 create mode 100644 include/dynamic-graph/signal-cast-helper.h
 create mode 100644 src/signal/signal-cast-helper.cpp

diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
index a0d06c43..585472f7 100644
--- a/include/CMakeLists.txt
+++ b/include/CMakeLists.txt
@@ -57,6 +57,7 @@ signal.t.cpp
 time-dependency.h
 time-dependency.t.cpp
 signal-caster.h
+signal-cast-helper.h
 all-signals.h
 
 tracer.h
diff --git a/include/dynamic-graph/signal-cast-helper.h b/include/dynamic-graph/signal-cast-helper.h
new file mode 100644
index 00000000..20cc25e0
--- /dev/null
+++ b/include/dynamic-graph/signal-cast-helper.h
@@ -0,0 +1,215 @@
+// -*- c++-mode -*-
+// Copyright 2010 François Bleibel Thomas Moulard, Olivier Stasse, Nicolas Mansard
+//
+// This file is part of dynamic-graph.
+// dynamic-graph 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, either version 3 of the License, or
+// (at your option) any later version.
+//
+// dynamic-graph 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 dynamic-graph.  If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef DYNAMIC_GRAPH_SIGNAL_CASTER_HELPER_HH
+# define DYNAMIC_GRAPH_SIGNAL_CASTER_HELPER_HH
+# include <map>
+# include <typeinfo>
+# include <iostream>
+# include <vector>
+
+# include <boost/any.hpp>
+# include <boost/format.hpp>
+# include <boost/function/function1.hpp>
+# include <boost/function/function2.hpp>
+# include <boost/lexical_cast.hpp>
+# include <boost/tuple/tuple.hpp>
+
+# include <dynamic-graph/dynamic-graph-api.h>
+# include "dynamic-graph/exception-signal.h"
+
+namespace dynamicgraph
+{
+
+  /* --- NON GENERIC CASTER ------------------------------------------------- */
+
+  /// This class can be used to register default casts, i.e. casts
+  /// already supported by the object to an std::iostream through the
+  /// operators >> and << .
+  template<typename T>
+  class DefaultCastRegisterer : public SignalCastRegisterer
+  {
+  public:
+    DefaultCastRegisterer ()
+      : SignalCastRegisterer (typeid(T), disp, cast, trace)
+    {}
+
+    DYNAMIC_GRAPH_DLLEXPORT
+      static boost::any cast (std::istringstream& iss);
+
+    DYNAMIC_GRAPH_DLLEXPORT
+      static void disp (const boost::any& object, std::ostream& os)
+    {
+      os << boost::any_cast<T> (object) << std::endl;
+    }
+
+    DYNAMIC_GRAPH_DLLEXPORT
+      static void trace (const boost::any& object, std::ostream& os)
+    {
+      disp(object,os);
+    }
+  };
+
+  /// A default version of the caster, to serialize directly from
+  /// std::in.
+  template <typename T>
+  boost::any
+  DefaultCastRegisterer<T>::cast (std::istringstream& iss)
+    {
+      T inst;
+      iss >> inst;
+      if (iss.fail ())
+	{
+	  boost::format fmt ("failed to serialize %s ");
+	  fmt % iss.str ();
+	  throw ExceptionSignal(ExceptionSignal::GENERIC, fmt.str ());
+	}
+      return inst;
+    }
+
+
+  /* --- GENERIC CASTER ----------------------------------------------------- */
+  /*!
+   * This class is only used to group together static functions who differ by
+   * a template parameter. It is never actually instanced (the private constructor
+   * makes sure of that).
+   * Typical use of this class is to add the caster in the dg graph:
+   *   dynamicgraph::SignalCastRegisterer sotCastRegisterer_TYPE
+   *         (typeid(TYPE),
+   *          SignalCast<TYPE>::disp_,
+   *          SignalCast<TYPE>::cast_,
+   *          SignalCast<TYPE>::trace_);
+   */
+  template< class T >
+    class SignalCast
+    {
+    public:
+      static T cast( std::istringstream& stringValue ) { throw 1;}
+      static void disp( const T& t,std::ostream& os )  { throw 1;  }
+      static void trace( const T& t,std::ostream& os ) { disp(t,os); }
+    public:
+      // adapter functions for SignalCast
+      static boost::any cast_( std::istringstream& stringValue ) {
+	return boost::any_cast<T>(cast(stringValue));
+      }
+      static void disp_( const boost::any& t,std::ostream& os )  {
+	disp(boost::any_cast<T>(t), os);
+      }
+      static void trace_( const boost::any& t,std::ostream& os ) {
+	trace(boost::any_cast<T>(t),os);
+      }
+    private:
+      SignalCast() {}
+    };
+
+} // namespace dynamicgraph
+
+/* -------------------------------------------------------------------------- */
+/* --- MACROS --------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+/* Declaration macro: one instance of each class needs to be present in
+ * order for casts to be registered.
+ */
+
+#define DG_SIGNAL_CAST_DECLARATION(TYPE) \
+  ::dynamicgraph::SignalCastRegisterer sotCastRegisterer_##TYPE	\
+    (typeid(TYPE),						\
+     SignalCast<TYPE>::disp_,					\
+     SignalCast<TYPE>::cast_,					\
+     SignalCast<TYPE>::trace_)
+
+#define DG_SIGNAL_CAST_DECLARATION_NAMED(TYPE,NAME)			\
+  ::dynamicgraph::SignalCastRegisterer sotCastRegisterer_##NAME		\
+    (typeid(TYPE),							\
+     SignalCast<TYPE>::disp_,						\
+     SignalCast<TYPE>::cast_,						\
+     SignalCast<TYPE>::trace_)
+
+/* Standard definition macros: the three functions can be specified
+ * in the macros. To define then in the cpp, just put ';' in the args.
+ */
+#define DG_SIGNAL_CAST_FULL_DEFINITION(TYPE,CAST,DISP,TRACE)                                    \
+template<>                                                                                      \
+ class SignalCast<TYPE>					                                        \
+{                                                                                               \
+public:                                                                                         \
+        static TYPE cast( std::istringstream& iss )         CAST                                \
+	static void disp( TYPE const& t,std::ostream& os )  DISP	                        \
+	static void trace( TYPE const& t,std::ostream& os ) TRACE                               \
+public:            		                                                                \
+       DYNAMIC_GRAPH_DLLEXPORT                                                                  \
+	static boost::any cast_( std::istringstream& stringValue ) {           	                \
+ 		  return boost::any_cast<TYPE>(cast(stringValue));           	                \
+	}                                                                                       \
+       DYNAMIC_GRAPH_DLLEXPORT                                                                  \
+	static void disp_( const boost::any& t,std::ostream& os )  {       	                \
+	  disp(boost::any_cast<TYPE>(t), os);         				                \
+	}            										\
+       DYNAMIC_GRAPH_DLLEXPORT                                                                  \
+	static void trace_( const boost::any& t,std::ostream& os ) {      			\
+		  trace(boost::any_cast<TYPE>(t),os);      					\
+	}          										\
+}
+
+/* Standard definition macros: the functions <cast> and <disp> have
+ * to be implemented in the cpp files. The function <trace> is
+ * implemented as a proxy on <disp>.
+ */
+#define DG_SIGNAL_CAST_DEFINITION_HPP(TYPE)                              \
+ DG_SIGNAL_CAST_FULL_DEFINITION(TYPE,;,;,{ disp(t,os); })
+
+/* Lazy definition: <cast> and <disp> are to proxys on the standard
+ * std input (>>) and output (<<). The function <trace> has to be
+ * implemented in the cpp.
+ */
+#define DG_SIGNAL_CAST_DEFINITION_TRACE_HPP(TYPE,TRACE)                  \
+ DG_SIGNAL_CAST_FULL_DEFINITION(TYPE,                                    \
+ {TYPE res; iss >> res; return res; },                                   \
+ { os << t <<std::endl; },                                               \
+ TRACE )
+
+/* Lazy lazy definition: the three functions are implemented as
+ * proxys on std::io operation.
+ */
+#define DG_SIGNAL_CAST_DEFINITION(TYPE)                                  \
+ DG_SIGNAL_CAST_FULL_DEFINITION(TYPE,                                    \
+ {TYPE res; iss >> res; return res; },                                   \
+ { os << t <<std::endl; },                                               \
+ { disp(t,os); })
+
+/* Lazy definition of <cast> and <disp> with implementation of
+ * <trace> in the cpp.
+ */
+#define DG_SIGNAL_CAST_DEFINITION_TRACE(TYPE)                            \
+ DG_SIGNAL_CAST_FULL_DEFINITION(TYPE,                                    \
+ {TYPE res; iss >> res; return res; },                                   \
+ { os << t <<std::endl; },                                               \
+ ;)
+
+/* Macro to add the define SignalCast in the dg graph. Typical use is:
+ *     DG_ADD_CASTER( Matrix,matrix )
+ */
+#define DG_ADD_CASTER(TYPE,ID)                                            \
+  ::dynamicgraph::SignalCastRegisterer sotCastRegisterer_##ID		  \
+    (typeid(TYPE),                                                        \
+     SignalCast<TYPE>::disp_,                                             \
+     SignalCast<TYPE>::cast_,                                             \
+     SignalCast<TYPE>::trace_)
+
+
+
+#endif  // #ifndef DYNAMIC_GRAPH_SIGNAL_CASTER_HELPER_HH
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0eb37916..edd38bce 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -41,6 +41,7 @@ ADD_LIBRARY(${LIBRARY_NAME}
 
   signal/signal-array.cpp
   signal/signal-caster.cpp
+  signal/signal-cast-helper.cpp
 
   command/value.cpp
   command/command.cpp
diff --git a/src/signal/signal-cast-helper.cpp b/src/signal/signal-cast-helper.cpp
new file mode 100644
index 00000000..8f409c65
--- /dev/null
+++ b/src/signal/signal-cast-helper.cpp
@@ -0,0 +1,79 @@
+// -*- c++-mode -*-
+// Copyright 2010 François Bleibel Thomas Moulard, Olivier Stasse, Nicolas Mansard
+//
+// This file is part of dynamic-graph.
+// dynamic-graph 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, either version 3 of the License, or
+// (at your option) any later version.
+//
+// dynamic-graph 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 dynamic-graph.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <dynamic-graph/signal-caster.h>
+#include <dynamic-graph/signal-cast-helper.h>
+#include <dynamic-graph/dynamic-graph-api.h>
+#include <exception>
+#include <boost/lambda/bind.hpp>
+#include <string>
+#include <sstream>
+#include <algorithm>
+#include <dynamic-graph/exception-signal.h>
+
+#include <dynamic-graph/linear-algebra.h>
+
+namespace dynamicgraph
+{
+
+  // Define a custom implementation of the DefaultCastRegisterer
+  // to workaround the limitations of the stream based approach.
+  // When dealing with double: displaying a double on a stream
+  // is *NOT* the opposite of reading a double from a stream.
+  //
+  // In practice, it means that there is no way to read
+  // a NaN, +inf, -inf from a stream!
+  //
+  // To workaround this problem, parse special values manually
+  // (the strings used are the one produces by displaying special
+  // values on a stream).
+  template <>
+  inline boost::any
+  DefaultCastRegisterer<double>::cast (std::istringstream& iss)
+    {
+      std::string tmp;
+      iss >> tmp;
+
+      if (tmp == "nan")
+	return std::numeric_limits<double>::quiet_NaN ();
+      else if (tmp == "inf" || tmp == "+inf")
+	return std::numeric_limits<double>::infinity ();
+      else if (tmp == "-inf")
+	return -1. * std::numeric_limits<double>::infinity ();
+
+      try
+	{
+	  return boost::lexical_cast<double> (tmp);
+	}
+      catch (boost::bad_lexical_cast&)
+	{
+	  boost::format fmt ("failed to serialize %s (to double)");
+	  fmt % tmp;
+	  throw ExceptionSignal(ExceptionSignal::GENERIC, fmt.str ());
+	}
+    }
+
+  /// Registers useful casts
+  namespace
+  {
+    DefaultCastRegisterer<double> double_reg;
+    DefaultCastRegisterer<int> int_reg;
+    DefaultCastRegisterer<unsigned int> uint_reg;
+    DefaultCastRegisterer<dynamicgraph::Vector> vectorCastRegisterer;
+    DefaultCastRegisterer<dynamicgraph::Matrix> matrixCastRegisterer;
+  } // end of anonymous namespace.
+
+} // namespace dynamicgraph
-- 
GitLab