Commit 7a687378 authored by Joseph Mirabel's avatar Joseph Mirabel
Browse files

Remove SignalCaster and related class.

parent 7041c7d6
......@@ -74,6 +74,7 @@ SET(${PROJECT_NAME}_HEADERS
include/${CUSTOM_HEADER_DIR}/signal.t.cpp
include/${CUSTOM_HEADER_DIR}/time-dependency.h
include/${CUSTOM_HEADER_DIR}/time-dependency.t.cpp
# Kept for a brittle backward compatiblity.
include/${CUSTOM_HEADER_DIR}/signal-caster.h
include/${CUSTOM_HEADER_DIR}/signal-cast-helper.h
include/${CUSTOM_HEADER_DIR}/all-signals.h
......@@ -117,8 +118,6 @@ SET(${PROJECT_NAME}_SOURCES
src/mt/process-list.cpp
src/signal/signal-array.cpp
src/signal/signal-caster.cpp
src/signal/signal-cast-helper.cpp
src/command/value.cpp
src/command/command.cpp
......
......@@ -23,14 +23,9 @@ class OutStringStream;
class PluginLoader;
class PoolStorage;
class SignalCaster;
class SignalCastRegisterer;
class Tracer;
class TracerRealTime;
template <typename T> class DefaultCastRegisterer;
template <typename T, typename Time> class Signal;
template <typename Time> class SignalArray;
......
......@@ -5,175 +5,7 @@
#ifndef DYNAMIC_GRAPH_SIGNAL_CASTER_HELPER_HH
#define DYNAMIC_GRAPH_SIGNAL_CASTER_HELPER_HH
#include <map>
#include <typeinfo>
#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/eigen-io.h>
#include "dynamic-graph/exception-signal.h"
#include "dynamic-graph/signal-caster.h"
#include <dynamic-graph/dynamic-graph-api.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), cast) {}
static boost::any cast(std::istringstream &iss);
};
/// 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_);
* NMSD: I don't really understand the use of this additional class. IMHO
* (comme on dit), it should be possible to rewrite the same-spec macros
* using specialization of the template class DefaultCastRegisterer. No?
*/
template <class T> class SignalCast {
public:
static T cast(std::istringstream &) { throw 1; }
public:
// adapter functions for SignalCast
static boost::any cast_(std::istringstream &stringValue) {
return boost::any_cast<T>(cast(stringValue));
}
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 \
: static boost::any cast_(std::istringstream &stringValue) { \
return boost::any_cast<TYPE>(cast(stringValue)); \
} \
static void disp_(const boost::any &t, std::ostream &os) { \
disp(boost::any_cast<TYPE>(t), os); \
} \
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_)
#pragma warning "This file is now useless"
#endif // #ifndef DYNAMIC_GRAPH_SIGNAL_CASTER_HELPER_HH
......@@ -5,15 +5,10 @@
#ifndef DYNAMIC_GRAPH_SIGNAL_CASTER_HH
#define DYNAMIC_GRAPH_SIGNAL_CASTER_HH
#include <map>
#include <typeinfo>
#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/exception-signal.h"
#include <dynamic-graph/dynamic-graph-api.h>
......@@ -21,74 +16,6 @@
#include <dynamic-graph/eigen-io.h>
namespace dynamicgraph {
/// This singleton class allows serialization of a number of objects into
/// (disp) and from (cast) std i/o streams.
///
/// The transformation is done at run-time, i.e. SignalCaster
/// doesn't know about the type of objects it casts to.
///
/// It also allows registering of user-defined casts. A cast is
/// identified by the compiler. The mapping from a type to a
/// serialization function is dynamic, hence it is more complex than
/// a typical template-based compile-time resolve. So disp, cast and
/// trace are costly functions and should be used as such.
class DYNAMIC_GRAPH_DLLAPI SignalCaster {
public:
virtual ~SignalCaster();
/// Destroy the unique instance.
static void destroy();
/// Typedef of displayer functions that take an encapsulated 'any'
/// object and displays, cast, or trace it on an output stream
/// (serialization).
typedef boost::function1<boost::any, std::istringstream &> caster_type;
/// Get a reference to the unique object of the class.
static SignalCaster *getInstance(void);
/// Casts an object using a registered cast function.
boost::any cast(const std::type_info &, std::istringstream &iss);
/// Registers a cast.
void registerCast(const std::type_info &type,
caster_type caster);
/// Unregister a cast.
void unregisterCast(const std::type_info &type);
/// Checks if there is a displayer registered with type_name.
bool existsCast(const std::type_info &type) const;
/// Return the list of type names registered.
std::vector<std::string> listTypenames() const;
private:
/// Container for the three cast functions.
typedef boost::tuple<caster_type>
cast_functions_type;
/// \brief Retrieve cast structure from its name.
cast_functions_type &getCast(const std::string &type_name);
/// This map associates the typename of objects and the corresponding
/// using boost::function with 'compatible' syntax
std::map<std::string, cast_functions_type> functions_;
std::map<std::string, const std::type_info *> type_info_;
private:
explicit SignalCaster();
/// Pointer to the unique instance of the class.
static SignalCaster *instance_;
};
/// The SignalCast registerer class. Can be used to automatically
/// register a cast when instanced somewhere in a cpp file. Pass the
/// typeid () of the type you want to register a cast to as the first
/// argument. The code is provided here so the class does not need
/// to be exported.
class DYNAMIC_GRAPH_DLLAPI SignalCastRegisterer {
public:
inline SignalCastRegisterer(const std::type_info &type,
SignalCaster::caster_type caster) {
SignalCaster::getInstance()->registerCast(type, caster);
}
};
/// Template class used to serialize a signal value.
template <typename T> struct signal_disp {
inline static void run (const T &value, std::ostream &os) { os << value << '\n'; }
......
// -*- c++-mode -*-
// Copyright 2010 François Bleibel
// Thomas Moulard,
// Olivier Stasse,
// Nicolas Mansard
//
#include <algorithm>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/lambda/bind.hpp>
#include <dynamic-graph/dynamic-graph-api.h>
#include <dynamic-graph/exception-signal.h>
#include <dynamic-graph/linear-algebra.h>
#include <dynamic-graph/signal-cast-helper.h>
#include <dynamic-graph/signal-caster.h>
#include <exception>
#include <sstream>
#include <string>
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());
}
}
// for std::string, do not check failure. If input stream contains an
// empty string, iss.fail() returns true and an exception is thrown
template <>
inline boost::any
DefaultCastRegisterer<std::string>::cast(std::istringstream &iss) {
std::string inst(iss.str());
return inst;
}
/// Registers useful casts
namespace {
DefaultCastRegisterer<double> double_reg;
DefaultCastRegisterer<int> int_reg;
DefaultCastRegisterer<unsigned int> uint_reg;
DefaultCastRegisterer<bool> bool_reg;
DefaultCastRegisterer<dynamicgraph::Vector> vectorCastRegisterer;
DefaultCastRegisterer<dynamicgraph::Matrix> matrixCastRegisterer;
DefaultCastRegisterer<boost::posix_time::ptime> ptimeCastRegisterer;
DefaultCastRegisterer<std::string> stringCastRegisterer;
} // end of anonymous namespace.
} // namespace dynamicgraph
// -*- c++-mode -*-
// Copyright 2010 François Bleibel
// Thomas Moulard,
// Olivier Stasse
//
#include <algorithm>
#include <boost/lambda/bind.hpp>
#include <dynamic-graph/dynamic-graph-api.h>
#include <dynamic-graph/exception-signal.h>
#include <dynamic-graph/signal-caster.h>
#include <exception>
#include <sstream>
#include <string>
#include <dynamic-graph/linear-algebra.h>
namespace dynamicgraph {
SignalCaster::SignalCaster() {}
SignalCaster::~SignalCaster() {}
void SignalCaster::destroy() {
delete instance_;
instance_ = 0;
}
void SignalCaster::registerCast(const std::type_info &type,
SignalCaster::caster_type caster) {
if (existsCast(type)) {
// If type name has already been registered for same type, do not throw.
if (type_info_[type.name()] != &type) {
std::string typeName(type.name());
std::ostringstream os;
os << "cast already registered for typename " << typeName << "\n"
<< "and types differ: " << &type << " != " << type_info_[type.name()]
<< ".\n"
<< "A possible reason is that the dynamic"
<< " library defining this type\n"
<< "has been loaded several times, defining different symbols"
<< " for the same type.";
throw ExceptionSignal(ExceptionSignal::GENERIC, os.str());
}
}
functions_[type.name()] = cast_functions_type(caster);
type_info_[type.name()] = &type;
}
void SignalCaster::unregisterCast(const std::type_info &type) {
size_t n = functions_.erase(type.name());
if (0 == n) // erase did not find element
// TODO: throw Cast not registered exception
throw ExceptionSignal(ExceptionSignal::GENERIC);
}
bool SignalCaster::existsCast(const std::type_info &type) const {
return functions_.find(type.name()) != functions_.end();
}
SignalCaster::cast_functions_type &
SignalCaster::getCast(const std::string &type_name) {
std::map<std::string, cast_functions_type>::iterator it =
functions_.find(type_name);
if (it == functions_.end())
// TODO: throw "cast not registered" exception
throw ExceptionSignal(ExceptionSignal::BAD_CAST, "Cast not registered");
return it->second;
}
std::vector<std::string> SignalCaster::listTypenames() const {
std::vector<std::string> typeList;
for (std::map<std::string, cast_functions_type>::const_iterator iter =
functions_.begin();
iter != functions_.end(); ++iter)
typeList.push_back(iter->first);
return typeList;
}
boost::any SignalCaster::cast(const std::type_info &type,
std::istringstream &iss) {
return getCast(type.name()).get<0>()(iss);
}
/// Singleton on the library-wide instance of SignalCaster
SignalCaster *SignalCaster::getInstance(void) {
if (instance_ == 0) {
instance_ = new SignalCaster;
}
return instance_;
}
SignalCaster *SignalCaster::instance_ = 0;
} // namespace dynamicgraph
......@@ -7,7 +7,7 @@
#include <dynamic-graph/debug.h>
#include <dynamic-graph/factory.h>
#include <dynamic-graph/signal-array.h>
#include <dynamic-graph/signal-cast-helper.h>
#include <dynamic-graph/signal-caster.h>
#include <dynamic-graph/tracer.h>
#include <assert.h>
......@@ -140,21 +140,15 @@ BOOST_AUTO_TEST_CASE(test_base) {
}
BOOST_AUTO_TEST_CASE(test_cast_helper) {
DefaultCastRegisterer<int> defaultCR;
std::istringstream iss;
iss.str("1");
defaultCR.cast(iss);
signal_cast<int>::run(iss);
bool res = false;
try {
{
std::istringstream iss_fail;
iss.str("test");
defaultCR.cast(iss_fail);
} catch (ExceptionSignal &e) {
// Take int, not string
res = true;
BOOST_CHECK_THROW(signal_cast<int>::run(iss_fail), ExceptionSignal);
}
BOOST_CHECK(res);
/// Test cast register with Vector
output_test_stream output;
......@@ -164,15 +158,7 @@ BOOST_AUTO_TEST_CASE(test_cast_helper) {
avec[1] = 2.0;
avec[2] = 3.0;
avec[3] = 4.0;
res = true;
try {
signal_trace<Vector>::run(avec, output);
} catch (ExceptionSignal &e) {
/// Exception in case of wrong cast.
/// This should not happen.
res = false;
}
BOOST_CHECK(res);
BOOST_CHECK_NO_THROW(signal_trace<Vector>::run(avec, output));
/// Test cast register with Matrix
dynamicgraph::Matrix amatrix;
......@@ -181,53 +167,8 @@ BOOST_AUTO_TEST_CASE(test_cast_helper) {
amatrix(0, 1) = 1.0;
amatrix(1, 0) = 2.0;
amatrix(1, 1) = 3.0;
res = true;
try {
signal_trace<Matrix>::run(amatrix, output);
} catch (ExceptionSignal &e) {
/// Exception in case of wrong cast.
/// This should happen
res = false;
}
BOOST_CHECK(res);
BOOST_CHECK_NO_THROW(signal_trace<Matrix>::run(amatrix, output));
std::istringstream aiss("test");
DefaultCastRegisterer<std::string> defaultSR;
boost::any aTest = defaultSR.cast(aiss);
}
BOOST_AUTO_TEST_CASE(signal_caster_basics) {
/// Get the singleton on registered types.
SignalCaster *asig_caster = SignalCaster::getInstance();
/// List the registered types.
std::vector<std::string> amap = asig_caster->listTypenames();
for (std::vector<std::string>::iterator it = amap.begin(); it != amap.end();
++it)
std::cout << "signal_caster:listTypename: " << *it << std::endl;
/// Unregister a type
asig_caster->unregisterCast(typeid(double));
/// Unregister the type a second time to generate exception
bool res = false;
try {
asig_caster->unregisterCast(typeid(double));
} catch (ExceptionSignal &aes) {
res = (aes.getCode() == ExceptionSignal::GENERIC);
}
BOOST_CHECK(res);
/// Get the type cast to generate exception
res = false;
double ad = 2.0;
output_test_stream output;
try {
signal_disp<double>::run(ad, output);
} catch (ExceptionSignal &aes) {
res = (aes.getCode() == ExceptionSignal::BAD_CAST);
}
BOOST_CHECK(res);
asig_caster->destroy();
BOOST_CHECK(true);
signal_cast<std::string>::run(aiss);
}
......@@ -13,8 +13,6 @@
#include <dynamic-graph/factory.h>
#include <dynamic-graph/linear-algebra.h>
#include <dynamic-graph/pool.h>
#include <dynamic-graph/signal-cast-helper.h>
#include <dynamic-graph/signal-caster.h>
#include <dynamic-graph/signal.h>
#include "signal-cast-registerer-libA.hh"
......@@ -31,40 +29,6 @@ using boost::test_tools::output_test_stream;
typedef Eigen::VectorXd Vector;
typedef Eigen::MatrixXd Matrix;
struct EigenCastRegisterer_V : public dynamicgraph::SignalCastRegisterer {
typedef Vector bnuVector;
EigenCastRegisterer_V()
: SignalCastRegisterer(typeid(bnuVector), castVector) {}
static boost::any castVector(std::istringstream &iss) {
bnuVector res;
iss >> res;
return res;
}
};
template <typename Derived>
struct EigenCastRegisterer_M : public dynamicgraph::SignalCastRegisterer {
typedef Matrix bnuMatrix;
EigenCastRegisterer_M()
: SignalCastRegisterer(typeid(bnuMatrix), castMatrix) {}
static boost::any castMatrix(std::istringstream &iss) {
bnuMatrix res;
iss >> res;