From 4b49e5348d08aa990b9fcd7fb764ed920963a9fa Mon Sep 17 00:00:00 2001
From: Joseph Mirabel <jmirabel@laas.fr>
Date: Thu, 16 Jan 2020 17:56:22 +0100
Subject: [PATCH] Add vector of value as value type.

---
 include/dynamic-graph/value.h |  8 ++++++++
 src/command/value.cpp         | 35 +++++++++++++++++++++++++++++++++++
 tests/value.cpp               | 21 +++++++++++++++++++++
 3 files changed, 64 insertions(+)

diff --git a/include/dynamic-graph/value.h b/include/dynamic-graph/value.h
index 240dc50..5d3569d 100644
--- a/include/dynamic-graph/value.h
+++ b/include/dynamic-graph/value.h
@@ -12,10 +12,13 @@
 #include <dynamic-graph/linear-algebra.h>
 #include <string>
 #include <typeinfo>
+#include <vector>
 
 namespace dynamicgraph {
 namespace command {
 class Value;
+typedef std::vector<Value> Values;
+
 class DYNAMIC_GRAPH_DLLAPI EitherType {
 public:
   EitherType(const Value &value);
@@ -29,6 +32,7 @@ public:
   operator Vector() const;
   operator Eigen::MatrixXd() const;
   operator Eigen::Matrix4d() const;
+  operator Values() const;
 
 private:
   const Value *value_;
@@ -47,6 +51,7 @@ public:
     VECTOR,
     MATRIX,
     MATRIX4D,
+    VALUES,
     NB_TYPES
   };
   ~Value();
@@ -60,6 +65,7 @@ public:
   explicit Value(const Vector &value);
   explicit Value(const Eigen::MatrixXd &value);
   explicit Value(const Eigen::Matrix4d &value);
+  explicit Value(const Values &value);
   /// Copy constructor
   Value(const Value &value);
   // Construct an empty value (None)
@@ -99,6 +105,8 @@ public:
   Vector vectorValue() const;
   Eigen::MatrixXd matrixXdValue() const;
   Eigen::Matrix4d matrix4dValue() const;
+  Values valuesValue () const;
+  const Values &constValuesValue () const;
   Type type_;
   const void *const value_;
 };
diff --git a/src/command/value.cpp b/src/command/value.cpp
index f9464ab..a64957b 100644
--- a/src/command/value.cpp
+++ b/src/command/value.cpp
@@ -29,6 +29,7 @@ EitherType::operator Vector() const { return value_->vectorValue(); }
 EitherType::operator Eigen::MatrixXd() const { return value_->matrixXdValue(); }
 
 EitherType::operator Eigen::Matrix4d() const { return value_->matrix4dValue(); }
+EitherType::operator Values() const { return value_->valuesValue(); }
 
 void Value::deleteValue() {
   switch (type_) {
@@ -59,6 +60,9 @@ void Value::deleteValue() {
   case MATRIX4D:
     delete (const Eigen::Matrix4d *)value_;
     break;
+  case VALUES:
+    delete (const Values *)value_;
+    break;
   default:;
   }
 }
@@ -78,6 +82,8 @@ Value::Value(const Eigen::MatrixXd &value)
     : type_(MATRIX), value_(new Eigen::MatrixXd(value)) {}
 Value::Value(const Eigen::Matrix4d &value)
     : type_(MATRIX4D), value_(new Eigen::Matrix4d(value)) {}
+Value::Value(const Values &value)
+    : type_(VALUES), value_(new Values(value)) {}
 
 Value::Value(const Value &value)
     : type_(value.type_), value_(copyValue(value)) {}
@@ -116,6 +122,9 @@ void *copyValue(const Value &value) {
   case Value::MATRIX4D:
     copy = new Eigen::Matrix4d(value.matrix4dValue());
     break;
+  case Value::VALUES:
+    copy = new Values(value.valuesValue());
+    break;
   default:
     abort();
   }
@@ -200,6 +209,20 @@ Eigen::Matrix4d Value::matrix4dValue() const {
                           "value is not a Eigen matrix4d");
 }
 
+Values Value::valuesValue() const {
+  if (type_ == VALUES)
+    return *((const Values *)value_);
+  throw ExceptionAbstract(ExceptionAbstract::TOOLS,
+                          "value is not a vector of Value");
+}
+
+const Values &Value::constValuesValue() const {
+  if (type_ == VALUES)
+    return *((const Values *)value_);
+  throw ExceptionAbstract(ExceptionAbstract::TOOLS,
+                          "value is not a vector of Value");
+}
+
 std::string Value::typeName(Type type) {
   switch (type) {
   case BOOL:
@@ -220,6 +243,8 @@ std::string Value::typeName(Type type) {
     return std::string("matrixXd");
   case MATRIX4D:
     return std::string("matrix4d");
+  case VALUES:
+    return std::string("values");
   default:
     return std::string("unknown");
   }
@@ -255,6 +280,15 @@ std::ostream &operator<<(std::ostream &os, const Value &value) {
   case Value::MATRIX4D:
     os << value.matrix4dValue();
     break;
+  case Value::VALUES:
+    {
+      const std::vector<Value>& vals = value.constValuesValue();
+      os << "[ ";
+      for (std::size_t i = 0; i < vals.size(); ++i)
+        os << "Value(" << vals[i] << "), ";
+      os << "]";
+    }
+    break;
   default:
     return os;
   }
@@ -272,6 +306,7 @@ template <>
 const Value::Type ValueHelper<Eigen::MatrixXd>::TypeID = Value::MATRIX;
 template <>
 const Value::Type ValueHelper<Eigen::Matrix4d>::TypeID = Value::MATRIX4D;
+template <> const Value::Type ValueHelper<Values>::TypeID = Value::VALUES;
 
 } // namespace command
 } // namespace dynamicgraph
diff --git a/tests/value.cpp b/tests/value.cpp
index f95b5ca..fe5eb64 100644
--- a/tests/value.cpp
+++ b/tests/value.cpp
@@ -351,3 +351,24 @@ BOOST_AUTO_TEST_CASE(value_matrix4d) {
                                 "  0   0   0   0"));
   }
 }
+
+BOOST_AUTO_TEST_CASE(value_values) {
+  using namespace dynamicgraph::command;
+
+  std::string s1("value #1");
+  double d1 = 0.3;
+
+  Value vs1(s1);
+  Value vd1(d1);
+
+  Values values;
+  values.push_back (vs1);
+  values.push_back (vd1);
+
+  Value vvalues (values);
+
+  BOOST_CHECK_EQUAL(vvalues.type(), Value::VALUES);
+
+  const Values& vs = vvalues.constValuesValue();
+  BOOST_CHECK_EQUAL(vs.size(), values.size());
+}
-- 
GitLab