From fda270a922983fcd31fbc377a7e4d957a7e062b5 Mon Sep 17 00:00:00 2001
From: florent <florent@laas.fr>
Date: Fri, 5 Nov 2010 20:56:43 +0100
Subject: [PATCH] Support more type for command parameters

	* include/dynamic-graph/command-setter.h,
	* include/dynamic-graph/command-setter.t.cpp,
	* include/dynamic-graph/value.h,
	* src/command/value.cpp: support bool, unsigned and float.
---
 include/dynamic-graph/command-setter.h     |   1 -
 include/dynamic-graph/command-setter.t.cpp | 225 +++++++++++++++++++--
 include/dynamic-graph/value.h              |  14 +-
 src/command/value.cpp                      | 107 ++++++++--
 4 files changed, 309 insertions(+), 38 deletions(-)

diff --git a/include/dynamic-graph/command-setter.h b/include/dynamic-graph/command-setter.h
index 070b063..3d04e26 100644
--- a/include/dynamic-graph/command-setter.h
+++ b/include/dynamic-graph/command-setter.h
@@ -64,7 +64,6 @@ namespace dynamicgraph {
       virtual Value doExecute();
 
     private:
-      static const std::vector<Value::Type> typeVector();
       SetterMethod setterMethod_;
     };
   } // namespace command
diff --git a/include/dynamic-graph/command-setter.t.cpp b/include/dynamic-graph/command-setter.t.cpp
index 9abd495..962dd8e 100644
--- a/include/dynamic-graph/command-setter.t.cpp
+++ b/include/dynamic-graph/command-setter.t.cpp
@@ -19,47 +19,228 @@
 #define DYNAMIC_GRAPH_COMMAND_SETTER_T_CPP
 
 #include <sstream>
+#include <boost/assign/list_of.hpp>
 
 namespace dynamicgraph {
   class Entity;
   namespace command {
 
-    template <class E, typename T>
-    const std::vector<Value::Type>  Setter<E, T>::typeVector()
+    // 
+    // Template specialization: bool
+    //
+    template <class E>
+    class Setter<E, bool> : public Command {
+    public:
+      /// Pointer to method that sets paramter of type bool
+      typedef void (E::*SetterMethod) (const bool&);
+      /// Constructor
+      Setter(E& entity, SetterMethod);
+
+    protected:
+      virtual Value doExecute();
+
+    private:
+      SetterMethod setterMethod_;
+    }; // Class Setter
+
+    template <class E>
+    Setter<E, bool>::Setter(E& entity, SetterMethod setterMethod) :
+      Command(entity, boost::assign::list_of(Value::BOOL)),
+      setterMethod_(setterMethod)
+    {
+    }
+
+    template <class E>
+    Value Setter<E, bool>::doExecute()
+    {
+      const std::vector<Value>& values = getParameterValues();
+      // Get parameter
+      bool value = values[0].value();
+      E& entity = static_cast<E&>(owner());
+      (entity.*setterMethod_)(value);
+      return Value();
+    }
+
+    // 
+    // Template specialization: unsigned
+    //
+    template <class E>
+    class Setter<E, unsigned> : public Command {
+    public:
+      /// Pointer to method that sets paramter of type unsigned
+      typedef void (E::*SetterMethod) (const unsigned&);
+      /// Constructor
+      Setter(E& entity, SetterMethod);
+
+    protected:
+      virtual Value doExecute();
+
+    private:
+      SetterMethod setterMethod_;
+    }; // Class Setter
+
+    template <class E>
+    Setter<E, unsigned>::Setter(E& entity, SetterMethod setterMethod) :
+      Command(entity, boost::assign::list_of(Value::UNSIGNED)),
+      setterMethod_(setterMethod)
+    {
+    }
+
+    template <class E>
+    Value Setter<E, unsigned>::doExecute()
+    {
+      const std::vector<Value>& values = getParameterValues();
+      // Get parameter
+      unsigned value = values[0].value();
+      E& entity = static_cast<E&>(owner());
+      (entity.*setterMethod_)(value);
+      return Value();
+    }
+
+    // 
+    // Template specialization: int
+    //
+    template <class E>
+    class Setter<E, int> : public Command {
+    public:
+      /// Pointer to method that sets paramter of type int
+      typedef void (E::*SetterMethod) (const int&);
+      /// Constructor
+      Setter(E& entity, SetterMethod);
+
+    protected:
+      virtual Value doExecute();
+
+    private:
+      SetterMethod setterMethod_;
+    }; // Class Setter
+
+    template <class E>
+    Setter<E, int>::Setter(E& entity, SetterMethod setterMethod) :
+      Command(entity, boost::assign::list_of(Value::INT)),
+      setterMethod_(setterMethod)
+    {
+    }
+
+    template <class E>
+    Value Setter<E, int>::doExecute()
+    {
+      const std::vector<Value>& values = getParameterValues();
+      // Get parameter
+      int value = values[0].value();
+      E& entity = static_cast<E&>(owner());
+      (entity.*setterMethod_)(value);
+      return Value();
+    }
+
+    // 
+    // Template specialization: float
+    //
+    template <class E>
+    class Setter<E, float> : public Command {
+    public:
+      /// Pointer to method that sets paramter of type float
+      typedef void (E::*SetterMethod) (const float&);
+      /// Constructor
+      Setter(E& entity, SetterMethod);
+
+    protected:
+      virtual Value doExecute();
+
+    private:
+      SetterMethod setterMethod_;
+    }; // Class Setter
+
+    template <class E>
+    Setter<E, float>::Setter(E& entity, SetterMethod setterMethod) :
+      Command(entity, boost::assign::list_of(Value::FLOAT)),
+      setterMethod_(setterMethod)
+    {
+    }
+
+    template <class E>
+    Value Setter<E, float>::doExecute()
+    {
+      const std::vector<Value>& values = getParameterValues();
+      // Get parameter
+      float value = values[0].value();
+      E& entity = static_cast<E&>(owner());
+      (entity.*setterMethod_)(value);
+      return Value();
+    }
+
+    // 
+    // Template specialization: double
+    //
+    template <class E>
+    class Setter<E, double> : public Command {
+    public:
+      /// Pointer to method that sets paramter of type double
+      typedef void (E::*SetterMethod) (const double&);
+      /// Constructor
+      Setter(E& entity, SetterMethod);
+
+    protected:
+      virtual Value doExecute();
+
+    private:
+      SetterMethod setterMethod_;
+    }; // Class Setter
+
+    template <class E>
+    Setter<E, double>::Setter(E& entity, SetterMethod setterMethod) :
+      Command(entity, boost::assign::list_of(Value::DOUBLE)),
+      setterMethod_(setterMethod)
     {
-      std::vector<Value::Type> result;
-      if (typeid(T) == typeid(int)) {
-	result.push_back(Value::INT);
-      } else if (typeid(T) == typeid(double)) {
-	result.push_back(Value::DOUBLE);
-      } else if (typeid(T) == typeid(std::string)) {
-	result.push_back(Value::STRING);
-      } else {
-	std::stringstream ss;
-	ss << "Type " << typeid(T).name() << " not supported.";
-	throw ExceptionAbstract(ExceptionAbstract::TOOLS,
-				ss.str());
-      }
-      return result;
     }
 
-    template <class E, typename T>
-    Setter<E, T>::Setter(E& entity, SetterMethod setterMethod) :
-      Command(entity, typeVector()),
+    template <class E>
+    Value Setter<E, double>::doExecute()
+    {
+      const std::vector<Value>& values = getParameterValues();
+      // Get parameter
+      double value = values[0].value();
+      E& entity = static_cast<E&>(owner());
+      (entity.*setterMethod_)(value);
+      return Value();
+    }
+
+    // 
+    // Template specialization: std::string
+    //
+    template <class E>
+    class Setter<E, std::string> : public Command {
+    public:
+      /// Pointer to method that sets paramter of type std::string
+      typedef void (E::*SetterMethod) (const std::string&);
+      /// Constructor
+      Setter(E& entity, SetterMethod);
+
+    protected:
+      virtual Value doExecute();
+
+    private:
+      SetterMethod setterMethod_;
+    }; // Class Setter
+
+    template <class E>
+    Setter<E, std::string>::Setter(E& entity, SetterMethod setterMethod) :
+      Command(entity, boost::assign::list_of(Value::STRING)),
       setterMethod_(setterMethod)
     {
     }
 
-    template <class E, typename T>
-    Value Setter<E, T>::doExecute()
+    template <class E>
+    Value Setter<E, std::string>::doExecute()
     {
       const std::vector<Value>& values = getParameterValues();
       // Get parameter
-      T value = values[0].value();
+      std::string value = values[0].value();
       E& entity = static_cast<E&>(owner());
       (entity.*setterMethod_)(value);
       return Value();
     }
+
   } // namespace command
 } // namespace dynamicgraph
 
diff --git a/include/dynamic-graph/value.h b/include/dynamic-graph/value.h
index d21e948..4846800 100644
--- a/include/dynamic-graph/value.h
+++ b/include/dynamic-graph/value.h
@@ -31,7 +31,10 @@ namespace dynamicgraph {
     public:
       EitherType(const Value& value);
       ~EitherType();
+      operator bool () const;
+      operator unsigned () const;
       operator int () const;
+      operator float () const;
       operator double () const;
       operator std::string () const;
     private:
@@ -42,13 +45,19 @@ namespace dynamicgraph {
     public:
       enum Type {
 	NONE,
+	BOOL,
+	UNSIGNED,
 	INT,
+	FLOAT,
 	DOUBLE,
 	STRING,
 	NB_TYPES
       };
       ~Value();
+      Value(const bool& value);
+      Value(const unsigned& value);
       Value(const int& value);
+      Value(const float& value);
       Value(const double& value);
       Value(const std::string& value);
       /// Copy constructor
@@ -77,8 +86,11 @@ namespace dynamicgraph {
       friend std::ostream& operator<<(std::ostream& os, const Value& value);
     private:
       friend class EitherType;
-      const double doubleValue() const;
+      const bool boolValue() const;
+      const unsigned unsignedValue() const;
       const int intValue() const;
+      const float floatValue() const;
+      const double doubleValue() const;
       const std::string stringValue() const;
       Type type_;
       const void* value_;
diff --git a/src/command/value.cpp b/src/command/value.cpp
index 7a74a27..af1bd10 100644
--- a/src/command/value.cpp
+++ b/src/command/value.cpp
@@ -30,10 +30,22 @@ namespace dynamicgraph {
       delete value_;
     }
 
+    EitherType::operator bool () const
+    {
+      return value_->boolValue();
+    }
+    EitherType::operator unsigned () const
+    {
+      return value_->unsignedValue();
+    }
     EitherType::operator int () const
     {
       return value_->intValue();
     }
+    EitherType::operator float () const
+    {
+      return value_->floatValue();
+    }
     EitherType::operator double () const
     {
       return value_->doubleValue();
@@ -46,9 +58,18 @@ namespace dynamicgraph {
     Value::~Value()
     {
       switch(type_) {
+      case BOOL:
+	delete (bool*)value_;
+	break;
+      case UNSIGNED:
+	delete (unsigned*)value_;
+	break;
       case INT:
 	delete (int*)value_;
 	break;
+      case FLOAT:
+	delete (float*)value_;
+	break;
       case DOUBLE:
 	delete (double*)value_;
 	break;
@@ -58,21 +79,33 @@ namespace dynamicgraph {
       }
     }
 
+    Value::Value(const bool& value)
+    {
+      value_ = new bool(value);
+      type_ = BOOL;
+    }
+    Value::Value(const unsigned& value)
+    {
+      value_ = new unsigned(value);
+      type_ = UNSIGNED;
+    }
     Value::Value(const int& value)
     {
-      std::cout << "Constructor of int value" << std::endl;
       value_ = new int(value);
       type_ = INT;
     }
+    Value::Value(const float& value)
+    {
+      value_ = new float(value);
+      type_ = FLOAT;
+    }
     Value::Value(const double& value)
     {
-      std::cout << "Constructor of double value" << std::endl;
       value_ = new double(value);
       type_ = DOUBLE;
     }
     Value::Value(const std::string& value)
     {
-      std::cout << "Constructor of string value" << std::endl;
       value_ = new std::string(value);
       type_ = STRING;
     }
@@ -81,16 +114,22 @@ namespace dynamicgraph {
     Value::Value(const Value& value) : type_(value.type_)
     {
       switch(value.type_) {
+      case BOOL:
+	value_ = new bool(value.intValue());
+	break;
+      case UNSIGNED:
+	value_ = new unsigned(value.intValue());
+	break;
       case INT:
-	std::cout << "Value copy constructor: int" << std::endl;
 	value_ = new int(value.intValue());
 	break;
+      case FLOAT:
+	value_ = new float(value.intValue());
+	break;
       case DOUBLE:
-	std::cout << "Value copy constructor: double" << std::endl;
 	value_ = new double(value.doubleValue());
 	break;
       case STRING:
-	std::cout << "Value copy constructor: string" << std::endl;
 	value_ = new std::string(value.stringValue());
 	break;
       default:
@@ -101,7 +140,6 @@ namespace dynamicgraph {
 
     Value::Value() : type_(NONE), value_(NULL)
     {
-      std::cout << "Value empty constructor" << std::endl;
     }
 
     const EitherType Value::value() const
@@ -114,14 +152,20 @@ namespace dynamicgraph {
       return type_;
     }
 
-    const double Value::doubleValue () const
+    const bool Value::boolValue () const
     {
-      double result;
-      if (type_ == DOUBLE)
-	result = *((double*)value_);
-      return result;
+      if (type_ == BOOL)
+	return *((bool*)value_);
       throw ExceptionAbstract(ExceptionAbstract::TOOLS,
-			      "value is not a double");
+			      "value is not an bool");
+    }
+
+    const unsigned Value::unsignedValue () const
+    {
+      if (type_ == UNSIGNED)
+	return *((unsigned*)value_);
+      throw ExceptionAbstract(ExceptionAbstract::TOOLS,
+			      "value is not an unsigned int");
     }
 
     const int Value::intValue () const
@@ -129,7 +173,27 @@ namespace dynamicgraph {
       if (type_ == INT)
 	return *((int*)value_);
       throw ExceptionAbstract(ExceptionAbstract::TOOLS,
-			      "value is not an int");
+			      "value is not an int int");
+    }
+
+    const float Value::floatValue () const
+    {
+      float result;
+      if (type_ == FLOAT)
+	result = *((float*)value_);
+      return result;
+      throw ExceptionAbstract(ExceptionAbstract::TOOLS,
+			      "value is not a float");
+    }
+
+    const double Value::doubleValue () const
+    {
+      double result;
+      if (type_ == DOUBLE)
+	result = *((double*)value_);
+      return result;
+      throw ExceptionAbstract(ExceptionAbstract::TOOLS,
+			      "value is not a double");
     }
 
     const std::string Value::stringValue () const
@@ -143,8 +207,14 @@ namespace dynamicgraph {
     std::string Value::typeName(Type type)
     {
       switch (type) {
+      case BOOL:
+	return std::string("bool");
+      case UNSIGNED:
+	return std::string("unsigned int");
       case INT:
 	return std::string("int");
+      case FLOAT:
+	return std::string("float");
       case DOUBLE:
 	return std::string("double");
       case STRING:
@@ -158,12 +228,21 @@ namespace dynamicgraph {
       os << "Type=" << Value::typeName(value.type_)
 	 << ", value=";
       switch (value.type_) {
+      case Value::BOOL:
+	os << value.boolValue();
+	break;
+      case Value::UNSIGNED:
+	os << value.unsignedValue();
+	break;
       case Value::INT:
 	os << value.intValue();
 	break;
       case Value::DOUBLE:
 	os << value.doubleValue();
 	break;
+      case Value::FLOAT:
+	os << value.floatValue();
+	break;
       case Value::STRING:
 	os << value.stringValue();
 	break;
-- 
GitLab