[Debian-astro-commits] [gyoto] 116/221: Simplify introspection code by using new class Property::Value

Thibaut Jean-Claude Paumard thibaut at moszumanska.debian.org
Fri May 22 20:52:38 UTC 2015


This is an automated email from the git hooks/post-receive script.

thibaut pushed a commit to branch master
in repository gyoto.

commit 30a2278267e2130611faee81126582a0a3eaef1a
Author: Thibaut Paumard <paumard at users.sourceforge.net>
Date:   Thu Nov 27 12:05:00 2014 +0100

    Simplify introspection code by using new class Property::Value
---
 include/GyotoObject.h | 212 ++++++++++++++++++++++++--------------------
 lib/Object.C          | 240 +++++++++++++++++++++++++-------------------------
 yorick/gyoto_utils.C  |  50 +++++------
 3 files changed, 256 insertions(+), 246 deletions(-)

diff --git a/include/GyotoObject.h b/include/GyotoObject.h
index 7034e8d..b9b2330 100644
--- a/include/GyotoObject.h
+++ b/include/GyotoObject.h
@@ -122,102 +122,6 @@ namespace Gyoto {
   static Property const * const properties;		\
   virtual Property const * getProperties() const
 
-
-/**
- * \brief Object with properties
- */
-class Gyoto::Object
-{
- protected:
-  std::string kind_;
- public:
-  GYOTO_OBJECT;
-  Object (std::string const &kind) ;
-  Object () ;
-  Object (Object const &orig) ;
-  virtual ~Object();
-  void set(Property const &p, double val);
-  void set(Property const &p, double val, std::string const &unit);
-  void set(Property const &p, bool val);
-  void set(Property const &p, std::string const &val);
-  void set(Property const &p, std::vector<double> const &val);
-  //void set(std::string const pname, double val);
-  void get(Property const &p, double &val) const ;
-  void get(Property const &p, double &val, std::string const &unit) const ;
-  void get(Property const &p, bool &val) const ;
-  void get(Property const &p, std::string &val) const ;
-  void get(Property const &p, std::vector<double> &val) const;
-  //void get(std::string const pname, double &val);
-  Property const * property(std::string const pname) const;
-
-#ifdef GYOTO_USE_XERCES
-  void fillProperty(Gyoto::FactoryMessenger *fmp, Property const &p) const ;
-
-  /// Called from Factory
-  /**
-   * Object implementations should impement fillElement to save their
-   * parameters to XML and call the Metric::fillElement(fmp) for the
-   * shared properties
-   */
-  virtual void fillElement(Gyoto::FactoryMessenger *fmp) const ;
-
-  /**
-   * \brief Main loop in Subcontractor_t function
-   *
-   * The Subcontractor_t function for each Metric kind should look
-   * somewhat like this (templated as
-   * Gyoto::Metric::Subcontractor<MyKind>):
-\code
-SmartPointer<Metric::Generic>
-Gyoto::Metric::MyKind::Subcontractor(FactoryMessenger* fmp) {
-  SmartPointer<MyKind> gg = new MyKind();
-  gg -> setParameters(fmp);
-  return gg;
-}
-\endcode
-   *
-   * Each metric kind should implement setParameter(string name,
-   * string content, string unit) to interpret the individual XML
-   * elements. setParameters() can be overloaded in case the specific
-   * Metric class needs low level access to the FactoryMessenger. See
-   * Gyoto::Astrobj::UniformSphere::setParameters().
-   */
-  virtual void setParameters(Gyoto::FactoryMessenger *fmp) ;
-#endif
-  /**
-   * \brief Set parameter by name
-   *
-   * Assume MyKind is a subclass of Metric::Generic which has two
-   * members (a string StringMember and a double DoubleMember):
-\code
-int MyKind::setParameter(std::string name, std::string content, std::string unit) {
- if      (name=="StringMember") setStringMember(content);
- else if (name=="DoubleMember") setDoubleMemeber(atof(content.c_str()), unit);
- else return Generic::setParameter(name, content, unit);
- return 0;
-}
-\endcode
-   * If MyKind is not a direct subclass of Generic, it should call the
-   * corresponding setParameter() implementation instead of
-   * Generic::setParameter().
-   *
-   * \param name XML name of the parameter
-   * \param content string representation of the value
-   * \param unit string representation of the unit
-   * \return 0 if this parameter is known, 1 if it is not.
-   */
-  virtual int setParameter(std::string name,
-			    std::string content,
-			    std::string unit);
-
-  virtual void setParameter(Gyoto::Property const &p,
-			    std::string const &name,
-			    std::string const &content,
-			    std::string const &unit);
-
-};
-
-
 /**
  * \brief Property
  */
@@ -299,6 +203,122 @@ class Gyoto::Property
 
   Property const * find(std::string name) const;
 
+  class Value {
+  public:
+    Value();
+    ~Value();
+
+    double Double;
+    Value(double);
+    operator double() const;
+
+    bool Bool;
+    Value(bool);
+    operator bool() const;
+
+    long Long;
+    Value(long);
+    operator long() const;
+
+    std::string String;
+    Value(std::string);
+    operator std::string() const;
+
+    std::vector<double> VDouble;
+    Value(std::vector<double>);
+    operator std::vector<double>() const;
+
+  };
+
+};
+
+
+/**
+ * \brief Object with properties
+ */
+class Gyoto::Object
+{
+ protected:
+  std::string kind_;
+ public:
+  GYOTO_OBJECT;
+  Object (std::string const &kind) ;
+  Object () ;
+  Object (Object const &orig) ;
+  virtual ~Object();
+  void set(Property const &p, Property::Value const & val);
+  void set(Property const &p, Property::Value const & val, std::string const &unit);
+
+  Property::Value get(Property const &p) const;
+  Property::Value get(Property const &p, std::string const &unit) const;
+
+  Property const * property(std::string const pname) const;
+
+#ifdef GYOTO_USE_XERCES
+  void fillProperty(Gyoto::FactoryMessenger *fmp, Property const &p) const ;
+
+  /// Called from Factory
+  /**
+   * Object implementations should impement fillElement to save their
+   * parameters to XML and call the Metric::fillElement(fmp) for the
+   * shared properties
+   */
+  virtual void fillElement(Gyoto::FactoryMessenger *fmp) const ;
+
+  /**
+   * \brief Main loop in Subcontractor_t function
+   *
+   * The Subcontractor_t function for each Metric kind should look
+   * somewhat like this (templated as
+   * Gyoto::Metric::Subcontractor<MyKind>):
+\code
+SmartPointer<Metric::Generic>
+Gyoto::Metric::MyKind::Subcontractor(FactoryMessenger* fmp) {
+  SmartPointer<MyKind> gg = new MyKind();
+  gg -> setParameters(fmp);
+  return gg;
+}
+\endcode
+   *
+   * Each metric kind should implement setParameter(string name,
+   * string content, string unit) to interpret the individual XML
+   * elements. setParameters() can be overloaded in case the specific
+   * Metric class needs low level access to the FactoryMessenger. See
+   * Gyoto::Astrobj::UniformSphere::setParameters().
+   */
+  virtual void setParameters(Gyoto::FactoryMessenger *fmp) ;
+#endif
+  /**
+   * \brief Set parameter by name
+   *
+   * Assume MyKind is a subclass of Metric::Generic which has two
+   * members (a string StringMember and a double DoubleMember):
+\code
+int MyKind::setParameter(std::string name, std::string content, std::string unit) {
+ if      (name=="StringMember") setStringMember(content);
+ else if (name=="DoubleMember") setDoubleMemeber(atof(content.c_str()), unit);
+ else return Generic::setParameter(name, content, unit);
+ return 0;
+}
+\endcode
+   * If MyKind is not a direct subclass of Generic, it should call the
+   * corresponding setParameter() implementation instead of
+   * Generic::setParameter().
+   *
+   * \param name XML name of the parameter
+   * \param content string representation of the value
+   * \param unit string representation of the unit
+   * \return 0 if this parameter is known, 1 if it is not.
+   */
+  virtual int setParameter(std::string name,
+			    std::string content,
+			    std::string unit);
+
+  virtual void setParameter(Gyoto::Property const &p,
+			    std::string const &name,
+			    std::string const &content,
+			    std::string const &unit);
+
 };
 
 #endif
diff --git a/lib/Object.C b/lib/Object.C
index b878dad..8b68725 100644
--- a/lib/Object.C
+++ b/lib/Object.C
@@ -9,124 +9,133 @@ using namespace Gyoto ;
 
 GYOTO_PROPERTY_FINALIZE(Object, NULL);
 
+/// Value
+
+Property::Value::Value() {}
+Property::Value::~Value() {}
+
+Property::Value::Value(double val) : Double(val) {}
+Property::Value::operator double() const {return Double;}
+
+Property::Value::Value(bool val) : Bool(val) {}
+Property::Value::operator bool() const {return Bool;}
+
+Property::Value::Value(long val) : Long(val) {}
+Property::Value::operator long() const {return Long;}
+
+Property::Value::Value(std::string val) : String(val) {}
+Property::Value::operator std::string() const {return String;}
+
+Property::Value::Value(std::vector<double> val) : VDouble(val) {}
+Property::Value::operator std::vector<double>() const {return VDouble;}
+
+/// Object
+
 Gyoto::Object::Object(std::string const &name):kind_(name) {}
 Gyoto::Object::Object():kind_("") {}
 Gyoto::Object::Object(Object const &o):kind_(o.kind_) {}
 Gyoto::Object::~Object() {}
 
 
+void Object::set(Property const &p,
+		 Property::Value const &val,
+		 std::string const &unit) {
 
-void Object::set(Property const &p, double val) {
-  if (p.type != Property::double_t)
-    throwError("Property is no a double");
-  Property::set_double_t set = p.setter.set_double;
-  if (!set) throwError("Can't set this Property");
-  (this->*set)(val);
-}
-
-void Object::set(Property const &p, double val, std::string const &unit) {
-  if (p.type != Property::double_t)
-    throwError("Property is no a double");
-  Property::set_double_unit_t setu = p.setter_unit.set_double;
-  if (setu) {
-    (this->*setu)(val, unit);
-  } else {
-    if (unit != "") throwError("Can't set this property with unit");
-    set(p, val);
+  if (p.type == Property::double_t) {
+    Property::set_double_unit_t setu = p.setter_unit.set_double;
+    if (setu) {
+      (this->*setu)(val, unit);
+    } else {
+      if (unit != "") throwError("Can't set this property with unit");
+      set(p, val);
+    }
+    return;
   }
-}
 
-void Object::set(Property const &p, bool val) {
-  if (p.type != Property::bool_t)
-    throwError("Property is no a bool");
-  Property::set_bool_t set = p.setter.set_bool;
-  if (!set) throwError("Can't set this Property");
-  (this->*set)(val);
-}
+  if (unit != "")
+    throwError("Can't set this property with unit (not a double)");
 
-void Object::set(Property const &p, string const &val) {
-  if (p.type == Property::bool_t) {
-    cerr << "Object::set("<<p.name<<", "<<val<<")"<<std::endl<<std::endl;
-    set(p, val==p.name);
-  } else if (   p.type == Property::string_t
-	     || p.type == Property::filename_t) {
-    Property::set_string_t set = p.setter.set_string;
-    if (!set) throwError("Can't set this Property");
-    (this->*set)(val);
-  } else throwError("Cannot set this Property from a string");
-}
+  set(p, val);
+  return;
 
-void Object::set(Property const &p, vector<double> const &val) {
-  if (p.type != Property::vector_double_t)
-    throwError("Property is not a vector<double>");
-  Property::set_vector_double_t set = p.setter.set_vdouble;
-  if (!set) throwError("Can't set this Property");
-  (this->*set)(val);
 }
 
-// void Object::set(std::string const pname, double val) {
-//   Property const * const p = property(pname);
-//   if (!p) throwError ("No such Property");
-//   set(*p, val);
-// }
-
-void Object::get(Property const &p, double &val) const {
-  if (p.type != Property::double_t)
-    throwError("Property is no a double");
-  Property::get_double_t get = p.getter.get_double;
-  if (!get) throwError("Can't get this Property");
-  val = (this->*get)();
+void Object::set(Property const &p, Property::Value const &val) {
+# define ___local_case(type)			\
+  case Property::type##_t:			\
+    {						\
+      Property::set_##type##_t set = p.setter.set_##type; \
+      if (!set) throwError("Can't set this Property");	\
+      (this->*set)(val);				\
+    }							\
+    break
+  
+  switch (p.type) {
+    ___local_case(double);
+    ___local_case(bool);
+    ___local_case(long);
+  case Property::filename_t:
+    ___local_case(string);
+  case Property::vector_double_t:
+    {
+      Property::set_vector_double_t set = p.setter.set_vdouble;
+      if (!set) throwError("Can't set this Property");
+      (this->*set)(val);
+    }
+    break;
+  default:
+    throwError("Unimplemented Property type in Object::set");
+  }
+# undef ___local_case
 }
 
-void Object::get(Property const &p, double &val, std::string const &unit) const {
-  if (p.type != Property::double_t)
-    throwError("Property is no a double");
-  Property::get_double_unit_t getu = p.getter_unit.get_double;
-  if (getu) {
-    val = (this->*getu)(unit);
-  } else {
-    if (unit != "") throwError("Can't get this Property with unit");
-    get(p, val);
+Property::Value Object::get(Property const &p,
+			    std::string const &unit) const {
+
+  if (p.type == Property::double_t) {
+    Property::get_double_unit_t getu = p.getter_unit.get_double;
+    if (getu) return (this->*getu)(unit);
+    if (unit != "") throwError("Can't get this property with unit");
+    return get(p);
   }
-}
 
+  if (unit != "")
+    throwError("Can't set this property with unit (not a double)");
 
-void Object::get(Property const &p, bool &val) const {
-  if (p.type != Property::bool_t)
-    throwError("Property is no a bool");
-  Property::get_bool_t get = p.getter.get_bool;
-  if (!get) throwError("Can't get this Property");
-  val = (this->*get)();
+  return get(p);
 }
 
-void Object::get(Property const &p, string &val) const {
-  if (p.type == Property::bool_t) {
-    bool bval;
-    get(p, bval);
-    if (bval) val=p.name;
-    else val=p.name_false;
-  } else if (   p.type == Property::string_t
-	     || p.type == Property::filename_t) {
-    Property::get_string_t get = p.getter.get_string;
-    if (!get) throwError("Can't get this Property as a string");
-    val = (this->*get)();
+Property::Value Object::get(Property const &p) const {
+# define ___local_case(type) \
+  case Property::type##_t:     \
+    {			     \
+    Property::get_##type##_t get = p.getter.get_##type;	\
+    if (!get) throwError("Can't get this Property");	\
+    val = (this->*get)();				\
+    }							\
+    break
+
+  Property::Value val;
+  switch (p.type) {
+    ___local_case(bool);
+    ___local_case(double);
+    ___local_case(long);
+  case Property::filename_t:
+    ___local_case(string);
+  case Property::vector_double_t:
+    {
+      Property::get_vector_double_t get = p.getter.get_vdouble;
+      if (!get) throwError("Can't get this Property");
+      val = (this->*get)();
+    }
+    break;
+  default:
+    throwError("Unimplemented Property type in Object::get");
   }
+  return val;
+# undef ___local_case
 }
 
-void Object::get(Property const &p, vector<double> &val) const {
-  if (p.type != Property::vector_double_t)
-    throwError("Property is not a vector<double>");
-  Property::get_vector_double_t get = p.getter.get_vdouble;
-  if (!get) throwError("Can't get this Property");
-  val = (this->*get)();
-}
-
-// void Object::get(std::string const pname, double &val) {
-//   Property const * const p = property(pname);
-//   if (!p) throwError ("No such Property");
-//   get(*p, val);
-// }
-
 Property const * Object::property(std::string const pname) const {
   return getProperties() -> find(pname);
 }
@@ -136,33 +145,17 @@ void Object::fillProperty(Gyoto::FactoryMessenger *fmp, Property const &p) const
   string name=p.name;
   switch (p.type) {
   case Property::bool_t:
-    {
-      bool val;
-      get(p, val);
-      fmp->setParameter(val?name:p.name_false);
-    }
+    fmp->setParameter(get(p)?name:p.name_false);
     break;
   case Property::double_t:
-    {
-      double val;
-      get(p, val);
-      fmp->setParameter(name, val);
-    }
+    fmp->setParameter(name, double(get(p)));
     break;
   case Property::string_t:
   case Property::filename_t:
-    {
-      string val;
-      get(p, val);
-      fmp->setParameter(name, val);
-    }
+    fmp->setParameter(name, std::string(get(p)));
     break;
   case Property::vector_double_t:
-    {
-      std::vector<double> val;
-      get(p, val);
-      fmp->setParameter(name, val);
-    }
+    fmp->setParameter(name, get(p).VDouble);
     break;
   default:
     throwError("Property type unimplemented in Object::fillProperty()");
@@ -206,23 +199,26 @@ void Object::setParameters(Gyoto::FactoryMessenger *fmp)  {
 
 void Object::setParameter(Property const &p, string const &name,
 			  string const & content, string const & unit) {
+  Property::Value val;
   switch (p.type) {
   case Property::bool_t:
-    Object::set(p, name==p.name);
-    return;
+    val = (name==p.name);
+    break;
   case Property::double_t:
-    set(p, atof(content.c_str()), unit);
+    val = atof(content.c_str());
+    set(p, val, unit);
     return;
   case Property::filename_t:
   case Property::string_t:
-    set(p, content);
-    return;
+    val = content;
+    break;
   case Property::vector_double_t:
-    set(p, FactoryMessenger::parseArray(content));
-    return;
+    val = FactoryMessenger::parseArray(content);
+    break;
   default:
     throwError("Property type unimplemented in Object::setParameter()");
   }
+  set(p, val);
 }
 
 int Object::setParameter(string name, string content, string unit) {
diff --git a/yorick/gyoto_utils.C b/yorick/gyoto_utils.C
index ffa91e8..e285490 100644
--- a/yorick/gyoto_utils.C
+++ b/yorick/gyoto_utils.C
@@ -354,37 +354,30 @@ long int __ygyoto_var_idx(long id) {
 void ypush_property(Gyoto::SmartPointer<Gyoto::SmartPointee> ptr,
 		    Gyoto::Property const& p, int iarg,
 		    std::string name, std::string unit) {
+  Gyoto::Property::Value val;
+  if (p.type == Gyoto::Property::double_t)
+    val = ptr->get(p, unit);
+  else
+    val = ptr->get(p);
+
   switch(p.type) {
   case Gyoto::Property::bool_t:
-    {
-      bool val;
-      ptr->get(p, val);
-      ypush_long(name==p.name?val:!val);
-    }
+    ypush_long(name==p.name?bool(val):!val);
     break;
   case Gyoto::Property::double_t:
-    {
-      double val;
-      ptr->get(p, val, unit);
-      ypush_double(val);
-    }
+    ypush_double(val);
     break;
   case Gyoto::Property::string_t:
   case Gyoto::Property::filename_t:
-    {
-      string val;
-      ptr->get(p, val);
-      *ypush_q(0) = p_strcpy(val.c_str());
-    }
+    *ypush_q(0) = p_strcpy(string(val).c_str());
     break;
   case Gyoto::Property::vector_double_t:
     {
-      std::vector<double> val;
-      ptr->get(p, val);
-      size_t n=val.size();
+      std::vector<double> vval = val;
+      size_t n = vval.size();
       long dims[]={1, long(n)};
       double * buf = ypush_d(dims);
-      for (size_t i=0; i<n; ++i) buf[i]=val[i];
+      for (size_t i=0; i<n; ++i) buf[i]=vval[i];
     }
     break;
   default:
@@ -395,31 +388,32 @@ void ypush_property(Gyoto::SmartPointer<Gyoto::SmartPointee> ptr,
 void yget_property(Gyoto::SmartPointer<Gyoto::SmartPointee> ptr,
 		   Gyoto::Property const& p, int iarg, std::string name,
 		   std::string unit) {
+  Gyoto::Property::Value val;
   switch(p.type) {
   case Gyoto::Property::bool_t:
     {
-      bool val=ygets_l(iarg);
+      val=ygets_l(iarg);
       if (name != p.name) val = !val;
-      ptr->set(p, val);
     }
     break;
   case Gyoto::Property::double_t:
     ptr->set(p, ygets_d(iarg), unit);
-    break;
+    return;
   case Gyoto::Property::filename_t:
   case Gyoto::Property::string_t:
-    ptr -> set(p, string(ygets_q(iarg)));
-    return;
+    val =  string(ygets_q(iarg));
+    break;
   case Gyoto::Property::vector_double_t:
     {
       long n;
       double *buf = ygeta_d(iarg, &n, NULL);
-      std::vector<double> val(n, 0.);
-      for (size_t i=0; i<n; ++i) val[i]=buf[i];
-      ptr -> set(p, val);
+      std::vector<double> vval(n, 0.);
+      for (size_t i=0; i<n; ++i) vval[i]=buf[i];
+      val = vval;
     }
-    return;
+    break;
   default:
     y_error("Property type unimplemented in yget_property()");
    }
+  ptr->set(p, val);
 }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-astro/packages/gyoto.git



More information about the Debian-astro-commits mailing list