[Debian-astro-commits] [gyoto] 103/221: Start working on introspection framework: new classes 'Object' and 'Property', properties can be set and retrieved by name. Metric::Generic converted to this framework.

Thibaut Jean-Claude Paumard thibaut at moszumanska.debian.org
Fri May 22 20:52:37 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 ea26db033dfbf301f11d217ba0fb8fd62bb91d6a
Author: Thibaut Paumard <paumard at users.sourceforge.net>
Date:   Tue Nov 25 09:16:54 2014 +0100

    Start working on introspection framework: new classes 'Object' and 'Property', properties can be set and retrieved by name. Metric::Generic converted to this framework.
---
 include/GyotoBlackBodySpectrum.h     |   2 +-
 include/GyotoKerrBL.h                |   2 +-
 include/GyotoKerrKS.h                |   2 +-
 include/GyotoMetric.h                |  73 +-----------
 include/GyotoMinkowski.h             |   2 +-
 include/GyotoNumericalMetricLorene.h |   2 +-
 include/GyotoObject.h                | 189 ++++++++++++++++++++++++++++++
 include/GyotoPhoton.h                |   3 +
 include/GyotoPowerLawSpectrum.h      |   2 +-
 include/GyotoRotStar3_1.h            |   2 +-
 include/GyotoSmartPointer.h          |   6 +-
 include/GyotoSpectrum.h              |   6 +-
 lib/BlackBodySpectrum.C              |   5 +-
 lib/KerrBL.C                         |   5 +-
 lib/KerrKS.C                         |   5 +-
 lib/Makefile.am                      |   2 +-
 lib/Makefile.in                      |   5 +-
 lib/Metric.C                         |  89 +++++++-------
 lib/Minkowski.C                      |   5 +-
 lib/NumericalMetricLorene.C          |   3 +-
 lib/Object.C                         | 219 +++++++++++++++++++++++++++++++++++
 lib/Photon.C                         |  10 +-
 lib/PowerLawSpectrum.C               |   5 +-
 lib/RotStar3_1.C                     |   3 +-
 lib/SmartPointer.C                   |  11 +-
 lib/Spectrum.C                       |   2 -
 26 files changed, 519 insertions(+), 141 deletions(-)

diff --git a/include/GyotoBlackBodySpectrum.h b/include/GyotoBlackBodySpectrum.h
index 48db7ae..638bc40 100644
--- a/include/GyotoBlackBodySpectrum.h
+++ b/include/GyotoBlackBodySpectrum.h
@@ -76,7 +76,7 @@ class Gyoto::Spectrum::BlackBody : public Gyoto::Spectrum::Generic {
   using Gyoto::Spectrum::Generic::operator();
   virtual double operator()(double nu) const;
 
-  virtual void setParameter(std::string name,
+  virtual int setParameter(std::string name,
 			    std::string content,
 			    std::string unit);
 
diff --git a/include/GyotoKerrBL.h b/include/GyotoKerrBL.h
index 90587c2..b7ab824 100644
--- a/include/GyotoKerrBL.h
+++ b/include/GyotoKerrBL.h
@@ -125,7 +125,7 @@ class Gyoto::Metric::KerrBL : public Metric::Generic {
   void MakeMomentum(const double coordin[8], const double cst[5], double coordout[8]) const;
   ///< Transforms from Boyer-Lindquist coordinates [t,r,th,phi,tdot,rdot,thdot,phidot] to [t,r,th,phi,pt,pr,pth,pphi] where pt,pr... are generalized momenta.
 
-  virtual void setParameter(std::string, std::string, std::string);
+  virtual int setParameter(std::string, std::string, std::string);
 #ifdef GYOTO_USE_XERCES
   virtual void fillElement(FactoryMessenger *fmp); ///< called from Factory
 #endif
diff --git a/include/GyotoKerrKS.h b/include/GyotoKerrKS.h
index 953d6da..3200d44 100644
--- a/include/GyotoKerrKS.h
+++ b/include/GyotoKerrKS.h
@@ -115,7 +115,7 @@ class Gyoto::Metric::KerrKS
   virtual void circularVelocity(double const pos[4], double vel [4],
 				double dir=1.) const ;
 
-  virtual void setParameter(std::string, std::string, std::string);
+  virtual int setParameter(std::string, std::string, std::string);
 #ifdef GYOTO_USE_XERCES
   virtual void fillElement(FactoryMessenger *fmp);
 #endif
diff --git a/include/GyotoMetric.h b/include/GyotoMetric.h
index 572db3d..37c3d34 100644
--- a/include/GyotoMetric.h
+++ b/include/GyotoMetric.h
@@ -145,13 +145,12 @@ namespace Gyoto {
  *
  */
 class Gyoto::Metric::Generic
-: protected Gyoto::SmartPointee,
+: public Gyoto::SmartPointee,
   public Gyoto::Hook::Teller
 {
   friend class Gyoto::SmartPointer<Gyoto::Metric::Generic>;
 
  private:
-  std::string kind_; ///< Metric kind name (e.g. "KerrBL")
   double mass_;     ///< Mass yielding geometrical unit (in kg).
   int coordkind_; ///< Kind of coordinates (cartesian-like, spherical-like, unspecified)
 
@@ -194,13 +193,17 @@ class Gyoto::Metric::Generic
 
 
  public:
+  static Property const * const properties;
+  virtual Property const * getProperties() const;
+
+
   const std::string kind() const; ///< Get kind_
   int getRefCount();
   
   // Constructors - Destructor
   // -------------------------
   Generic(const int coordkind, const std::string &name); ///< Constructor setting Generic::coordkind_ and kind_
-
+  Generic(Generic const &o); ///< Copy constructor
   virtual ~Generic() ;                        ///< Destructor
   
   // Mutators / assignment
@@ -367,32 +370,6 @@ class Gyoto::Metric::Generic
  
 
   /**
-   * \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 void setParameter(std::string name,
-			    std::string content,
-			    std::string unit);
-
-  /**
    * \brief Computes the orthonormal local tetrad of the observer
    * 
    * \param obskind  input: kind of observer (eg: "ZAMO","KeplerianObserver"...)
@@ -408,44 +385,6 @@ int MyKind::setParameter(std::string name, std::string content, std::string unit
 			      double screen3[4]) const ;
 
   // Outputs
-#ifdef GYOTO_USE_XERCES
-
-  /**
-   * \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) ;
-
-  /**
-   * Metrics implementations should impement fillElement to save their
-   * parameters to XML and call the Metric::fillElement(fmp) for the
-   * shared properties
-   */
-
-  virtual void fillElement(FactoryMessenger *fmp) ; ///< called from Factory
-
-  /**
-   * \brief Process generic XML parameters 
-   */
-  void processGenericParameters(Gyoto::FactoryMessenger *fmp) ;
-#endif
 
   /**
    * \brief Metric coefficients
diff --git a/include/GyotoMinkowski.h b/include/GyotoMinkowski.h
index edca0b2..fc5d5a8 100644
--- a/include/GyotoMinkowski.h
+++ b/include/GyotoMinkowski.h
@@ -56,7 +56,7 @@ class Gyoto::Metric::Minkowski
   virtual Minkowski* clone() const ;
   void gmunu(double g[4][4], const double * x) const ;
   int christoffel(double dst[4][4][4], const double * x) const ;
-  virtual void setParameter(std::string, std::string, std::string);
+  virtual int setParameter(std::string, std::string, std::string);
 #ifdef GYOTO_USE_XERCES
   virtual void fillElement(FactoryMessenger *fmp); ///< called from Factory
 #endif
diff --git a/include/GyotoNumericalMetricLorene.h b/include/GyotoNumericalMetricLorene.h
index 5cc2b18..47fdf6e 100644
--- a/include/GyotoNumericalMetricLorene.h
+++ b/include/GyotoNumericalMetricLorene.h
@@ -175,7 +175,7 @@ class Gyoto::Metric::NumericalMetricLorene
   int diff(double tt, const double y[7], double res[7]) const ;
   virtual int diff(const double y[7], double res[7], int indice_time) const ;
 
-  virtual void setParameter(std::string, std::string, std::string);
+  virtual int setParameter(std::string, std::string, std::string);
 #ifdef GYOTO_USE_XERCES
   virtual void fillElement(FactoryMessenger *fmp); /// < called from Factory
   virtual void setParameters(FactoryMessenger *fmp);
diff --git a/include/GyotoObject.h b/include/GyotoObject.h
new file mode 100644
index 0000000..48c4673
--- /dev/null
+++ b/include/GyotoObject.h
@@ -0,0 +1,189 @@
+/**
+ * \file GyotoObject.h
+ * \brief Introspectbale objects 
+ */
+
+/*
+    Copyright 2014 Thibaut Paumard
+
+    This file is part of Gyoto.
+
+    Gyoto is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    Gyoto 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with Gyoto.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __GyotoObject_H_
+#define __GyotoObject_H_
+
+#include "GyotoConfig.h"
+#include <string>
+
+namespace Gyoto {
+  class Object;
+  class Property;
+  class FactoryMessenger;
+}
+
+/**
+ * \brief Object with properties
+ */
+class Gyoto::Object
+{
+ protected:
+  std::string kind_;
+ public:
+  static Property const * const properties;
+  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(std::string const pname, double val);
+  void get(Property const &p, double &val);
+  void get(Property const &p, double &val, std::string const &unit);
+  void get(Property const &p, bool &val);
+  void set(Property const &p, std::string &val);
+  //void get(std::string const pname, double &val);
+  Property const * property(std::string const pname) const;
+  virtual Property const * getProperties() const;
+
+#ifdef GYOTO_USE_XERCES
+  void fillProperty(Gyoto::FactoryMessenger *fmp, Property const &p) ;
+
+  /// 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) ;
+
+  /**
+   * \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);
+
+
+};
+
+
+/**
+ * \brief Property
+ */
+class Gyoto::Property
+{
+ private:
+
+ public:
+  enum type_e {double_t, long_t, bool_t};
+  std::string name;
+  std::string name_false;
+  int type;
+  typedef void (Object::* set_double_t)(double val);
+  typedef double (Object::* get_double_t)() const;
+  typedef void (Object::* set_double_unit_t)(double val,
+					     std::string const &unit);
+  typedef double (Object::* get_double_unit_t)(std::string const &unit) const;
+  typedef void (Object::* set_long_t)(double val);
+  typedef long (Object::* get_long_t)() const;
+  typedef void (Object::* set_bool_t)(bool val);
+  typedef bool (Object::* get_bool_t)() const;
+  union setter_t {
+    set_double_t set_double;
+    set_long_t set_long;
+    set_bool_t set_bool;
+  };
+  union getter_t {
+    get_double_t get_double;
+    get_long_t get_long;
+    get_bool_t get_bool;
+  };
+  union setter_unit_t {set_double_unit_t set_double;};
+  union getter_unit_t {get_double_unit_t get_double;};
+  setter_t setter;
+  getter_t getter;
+  setter_unit_t setter_unit;
+  getter_unit_t getter_unit;
+  Property const * const  * const parents;
+  
+  Property(std::string name,
+	   set_double_t set_double,
+	   get_double_t get_double,
+	   Property const * const * ancestors);
+
+  Property(std::string name,
+	   set_double_t set_double,
+	   get_double_t get_double,
+	   set_double_unit_t set_double_unit,
+	   get_double_unit_t get_double_unit,
+	   Property const * const * ancestors);
+
+  Property(std::string name,
+	   std::string name_false,
+	   set_bool_t set_bool,
+	   get_bool_t get_bool,
+	   Property const * const * ancestors);
+
+  Property const * find(std::string name) const;
+
+};
+
+#endif
diff --git a/include/GyotoPhoton.h b/include/GyotoPhoton.h
index ede2a5e..76a2c59 100644
--- a/include/GyotoPhoton.h
+++ b/include/GyotoPhoton.h
@@ -267,6 +267,9 @@ class Gyoto::Photon : public Gyoto::Worldline, protected Gyoto::SmartPointee {
    */
   virtual void transmit(size_t i, double t);
 
+  int setParameter(std::string name,
+			   std::string content,
+			   std::string unit) ;
  private:
   /// Allocate Photon::transmission_
   void _allocateTransmission();
diff --git a/include/GyotoPowerLawSpectrum.h b/include/GyotoPowerLawSpectrum.h
index 83f1380..52ac99a 100644
--- a/include/GyotoPowerLawSpectrum.h
+++ b/include/GyotoPowerLawSpectrum.h
@@ -74,7 +74,7 @@ class Gyoto::Spectrum::PowerLaw : public Gyoto::Spectrum::Generic {
   virtual double operator()(double nu) const;
 
 #ifdef GYOTO_USE_XERCES
-  virtual void setParameter(std::string name,
+  virtual int setParameter(std::string name,
 			    std::string content,
 			    std::string unit);
 
diff --git a/include/GyotoRotStar3_1.h b/include/GyotoRotStar3_1.h
index fdc92ae..4f84353 100644
--- a/include/GyotoRotStar3_1.h
+++ b/include/GyotoRotStar3_1.h
@@ -126,7 +126,7 @@ class Gyoto::Metric::RotStar3_1 : public Gyoto::Metric::Generic {
   double ScalarProd(const double pos[4],
 		    const double u1[4], const double u2[4]) const ;
 
-  virtual void setParameter(std::string, std::string, std::string);
+  virtual int setParameter(std::string, std::string, std::string);
 #ifdef GYOTO_USE_XERCES
   virtual void fillElement(FactoryMessenger *fmp); ///< called from Factory
   virtual void setParameters(Gyoto::FactoryMessenger *fmp) ;
diff --git a/include/GyotoSmartPointer.h b/include/GyotoSmartPointer.h
index e055365..79b09e7 100644
--- a/include/GyotoSmartPointer.h
+++ b/include/GyotoSmartPointer.h
@@ -44,13 +44,12 @@
 #include <pthread.h>
 #endif
 
-
 namespace Gyoto {
   class SmartPointee;
-  class FactoryMessenger;
   template <class T> class SmartPointer;
 }
 
+#include <GyotoObject.h>
 #include <GyotoError.h>
 #include <stddef.h>
 #include <iostream>
@@ -76,7 +75,7 @@ namespace Gyoto {
  * @endcode
  *
  */
-class Gyoto::SmartPointee
+class Gyoto::SmartPointee : public Gyoto::Object
 {
  private:
   int refCount; ///< Reference counter.
@@ -90,6 +89,7 @@ class Gyoto::SmartPointee
 
  public:
   SmartPointee () ;
+  SmartPointee (std::string kind) ;
   SmartPointee (const   SmartPointee&) ; ///< Copy constructor
   void incRefCount () ; ///< Increment the reference counter. Warning: Don't mess with the counter.
   int decRefCount () ;  ///< Decrement the reference counter and return current value. Warning: Don't mess with the counter.
diff --git a/include/GyotoSpectrum.h b/include/GyotoSpectrum.h
index e4de1af..b496666 100644
--- a/include/GyotoSpectrum.h
+++ b/include/GyotoSpectrum.h
@@ -122,7 +122,7 @@ namespace Gyoto{
  *  Light emitted by e.g. a Star
  *
  */
-class Gyoto::Spectrum::Generic : protected Gyoto::SmartPointee {
+class Gyoto::Spectrum::Generic : public Gyoto::SmartPointee {
   friend class Gyoto::SmartPointer<Gyoto::Spectrum::Generic>;
  protected:
   std::string kind_; ///< e.g. constants, blackbody...
@@ -172,10 +172,6 @@ class Gyoto::Spectrum::Generic : protected Gyoto::SmartPointee {
   virtual double integrate(double nu1, double nu2,
 			   const Spectrum::Generic * opacity, double ds) ;
 
-  virtual void setParameter(std::string name,
-			    std::string content,
-			    std::string unit) ;
-  ///< Set any parameter by its name
 
 #ifdef GYOTO_USE_XERCES
   /**
diff --git a/lib/BlackBodySpectrum.C b/lib/BlackBodySpectrum.C
index a2690cb..d0ec228 100644
--- a/lib/BlackBodySpectrum.C
+++ b/lib/BlackBodySpectrum.C
@@ -45,13 +45,14 @@ double Spectrum::BlackBody::operator()(double nu) const {
     /(exp(GYOTO_PLANCK_OVER_BOLTZMANN*nu*Tm1_)-1.);
 }
 
-void Spectrum::BlackBody::setParameter(std::string name,
+int Spectrum::BlackBody::setParameter(std::string name,
 				       std::string content,
 				       std::string unit) {
   char * tc=const_cast<char*>(content.c_str());
   if (name=="Temperature") temperature(atof(tc));
   else if (name=="Scaling") scaling(atof(tc));
-  else Spectrum::Generic::setParameter(name, content, unit);
+  else return Spectrum::Generic::setParameter(name, content, unit);
+  return 0;
 }
 
 #ifdef GYOTO_USE_XERCES
diff --git a/lib/KerrBL.C b/lib/KerrBL.C
index cef2e6f..c99c0f4 100644
--- a/lib/KerrBL.C
+++ b/lib/KerrBL.C
@@ -1242,11 +1242,12 @@ void KerrBL::fillElement(Gyoto::FactoryMessenger *fmp) {
 }
 #endif
 
-void KerrBL::setParameter(string name, string content, string unit) {
+int KerrBL::setParameter(string name, string content, string unit) {
   if      (name=="Spin")          spin          (atof(content.c_str()));
   else if (name=="DiffTol")       difftol       (atof(content.c_str()));
   else if (name=="GenericIntegrator") genericIntegrator(true);
   else if (name=="SpecificIntegrator") genericIntegrator(false);
   else if (name=="HorizonSecurity") horizonSecurity(atof(content.c_str()));
-  else Generic::setParameter(name, content, unit);
+  else return Generic::setParameter(name, content, unit);
+  return 0;
 }
diff --git a/lib/KerrKS.C b/lib/KerrKS.C
index fcdd113..2667fc8 100644
--- a/lib/KerrKS.C
+++ b/lib/KerrKS.C
@@ -674,12 +674,13 @@ int KerrKS::isStopCondition(double const * const coord) const {
   return (r<rsink_ && rdot >0 && Tdot>0);
 }
 
-void KerrKS::setParameter(string name, string content, string unit) {
+int KerrKS::setParameter(string name, string content, string unit) {
   if (name=="Spin") spin(atof(content.c_str()));
   else if (name=="HorizonSecurity") horizonSecurity(atof(content.c_str()));
   else if (name=="GenericIntegrator") genericIntegrator(true);
   else if (name=="SpecificIntegrator") genericIntegrator(false);
-  else Generic::setParameter(name, content, unit);
+  else return Generic::setParameter(name, content, unit);
+  return 0;
 }
 
 #ifdef GYOTO_USE_XERCES
diff --git a/lib/Makefile.am b/lib/Makefile.am
index c734138..bfa32f0 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -18,7 +18,7 @@ libgyoto at FEATURES@_la_SOURCES =  Astrobj.C Factory.C Register.C SmartPointer.C U
 	WIP.C Worldline.C Photon.C Scenery.C			\
 	WorldlineIntegState.C Error.C Screen.C Spectrum.C		\
 	Spectrometer.C ComplexSpectrometer.C UniformSpectrometer.C \
-	ThinDisk.C Converters.C Functors.C Hooks.C
+	ThinDisk.C Converters.C Functors.C Hooks.C Object.C
 libgyoto at FEATURES@_la_LIBS = $(XERCESLDFLAGS)
 libgyoto at FEATURES@_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(VERSINFO)
 
diff --git a/lib/Makefile.in b/lib/Makefile.in
index ae050eb..86dbc67 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -170,7 +170,7 @@ am_libgyoto at FEATURES@_la_OBJECTS = Astrobj.lo Factory.lo Register.lo \
 	Photon.lo Scenery.lo WorldlineIntegState.lo Error.lo Screen.lo \
 	Spectrum.lo Spectrometer.lo ComplexSpectrometer.lo \
 	UniformSpectrometer.lo ThinDisk.lo Converters.lo Functors.lo \
-	Hooks.lo
+	Hooks.lo Object.lo
 libgyoto at FEATURES@_la_OBJECTS = $(am_libgyoto at FEATURES@_la_OBJECTS)
 libgyoto at FEATURES@_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
@@ -429,7 +429,7 @@ libgyoto at FEATURES@_la_SOURCES = Astrobj.C Factory.C Register.C SmartPointer.C Ut
 	WIP.C Worldline.C Photon.C Scenery.C			\
 	WorldlineIntegState.C Error.C Screen.C Spectrum.C		\
 	Spectrometer.C ComplexSpectrometer.C UniformSpectrometer.C \
-	ThinDisk.C Converters.C Functors.C Hooks.C
+	ThinDisk.C Converters.C Functors.C Hooks.C Object.C
 
 libgyoto at FEATURES@_la_LIBS = $(XERCESLDFLAGS)
 libgyoto at FEATURES@_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(VERSINFO)
@@ -601,6 +601,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/KerrKS.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/Metric.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/Minkowski.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/Object.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/PageThorneDisk.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/PatternDisk.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/PatternDiskBB.Plo at am__quote@
diff --git a/lib/Metric.C b/lib/Metric.C
index 8d28c40..6979165 100644
--- a/lib/Metric.C
+++ b/lib/Metric.C
@@ -32,8 +32,51 @@ using namespace Gyoto;
 
 Register::Entry* Metric::Register_ = NULL;
 
+//// Gyoto::Object API
+// Keplerian/NonKeplerian
+
+#define GYOTO_PROPERTY_MAKE_ANCESTORS(name, ancestor)	\
+  Property const * const name##_ancestors[] = {ancestor, NULL}
+
+#define GYOTO_PROPERTY_BOOL(name, namef, fname, ancestor) \
+  GYOTO_PROPERTY_MAKE_ANCESTORS(name, ancestor); \
+  Property const name \
+        (#name, \
+         #namef, \
+         (Property::set_bool_t)&fname, \
+         (Property::get_bool_t)&fname, \
+         name##_ancestors)
+
+#define GYOTO_PROPERTY_DOUBLE(name, fname, ancestor) \
+  GYOTO_PROPERTY_MAKE_ANCESTORS(name, ancestor); \
+  Property const name \
+        (#name, \
+         (Property::set_double_t)&fname, \
+         (Property::get_double_t)&fname, \
+         name##_ancestors)
+
+GYOTO_PROPERTY_BOOL(Keplerian, NonKeplerian, Metric::Generic::keplerian, Object::properties);
+GYOTO_PROPERTY_DOUBLE(DeltaMaxOverR, Metric::Generic::deltaMaxOverR, &Keplerian);
+GYOTO_PROPERTY_DOUBLE(DeltaMax, Metric::Generic::deltaMax, &DeltaMaxOverR);
+GYOTO_PROPERTY_DOUBLE(DeltaMin, Metric::Generic::deltaMin, &DeltaMax);
+
+// Mass
+Property const * const _Mass_ancestors[] = {&DeltaMin, NULL};
+Property _Mass(std::string("Mass"),
+	       (Property::set_double_t)&Metric::Generic::mass,
+	       (Property::get_double_t)&Metric::Generic::mass,
+	       (Property::set_double_unit_t)&Metric::Generic::mass,
+	       (Property::get_double_unit_t)&Metric::Generic::mass,
+	       _Mass_ancestors);
+Property const * const Metric::Generic::properties = &_Mass;
+
+Property const * Metric::Generic::getProperties() const {
+  return Metric::Generic::properties;
+}
+///
+
 Metric::Generic::Generic(const int coordkind, const std::string &name) :
-  kind_(name), mass_(1.), coordkind_(coordkind),
+  SmartPointee(name), mass_(1.), coordkind_(coordkind),
   delta_min_(GYOTO_DEFAULT_DELTA_MIN),
   delta_max_(GYOTO_DEFAULT_DELTA_MAX),
   delta_max_over_r_(GYOTO_DEFAULT_DELTA_MAX_OVER_R),
@@ -47,7 +90,12 @@ Metric::Generic::Generic(const int coordkind, const std::string &name) :
 # endif
 }
 
-// No copy constructor needed, default is fine
+Metric::Generic::Generic(Generic const &o):
+  SmartPointee(o), mass_(o.mass_), coordkind_(o.coordkind_),
+  delta_min_(o.delta_min_), delta_max_(o.delta_max_),
+  delta_max_over_r_(o.delta_max_over_r_), keplerian_(o.keplerian_)
+{}
+
 Metric::Generic * Metric::Generic::clone() const {
   string msg = "Metric::Generic::clone() called: cloning not supported for metric kind ";
   msg += kind();
@@ -542,43 +590,6 @@ double Metric::Generic::getPotential(double pos[4], double l_cst) const{
 
 int Metric::Generic::getRefCount() { return SmartPointee::getRefCount(); }
 
-#ifdef GYOTO_USE_XERCES
-void Metric::Generic::fillElement(Gyoto::FactoryMessenger *fmp) {
-  fmp -> setSelfAttribute("kind", kind_);
-  fmp -> setParameter("Mass", mass());
-  fmp -> setParameter("DeltaMin", delta_min_);
-  fmp -> setParameter("DeltaMax", delta_max_);
-  fmp -> setParameter("DeltaMaxOverR", delta_max_over_r_);
-  if (keplerian_) fmp -> setParameter("Keplerian");
-}
-
-void Metric::Generic::setParameters(Gyoto::FactoryMessenger *fmp)  {
-  string name="", content="", unit="";
-  if (fmp)
-    while (fmp->getNextParameter(&name, &content, &unit))
-      setParameter(name, content, unit);
-}
-
-void Metric::Generic::processGenericParameters(Gyoto::FactoryMessenger *fmp)  {
-  if (!fmp) return;
-  string name="", content="";
-  fmp -> reset();
-  while (fmp->getNextParameter(&name, &content)) {
-    if(name=="Mass")
-      mass(atof(content.c_str()), fmp -> getAttribute("unit"));
-  }
-}
-
-#endif
-
-void Metric::Generic::setParameter(string name, string content, string unit) {
-  if      (name=="Mass")     mass(atof(content.c_str()), unit);
-  else if (name=="DeltaMin") deltaMin(atof(content.c_str()));
-  else if (name=="DeltaMax") deltaMax(atof(content.c_str()));
-  else if (name=="DeltaMaxOverR") deltaMaxOverR (atof(content.c_str()));
-  else if (name=="Keplerian")keplerian(true);
-}
-
 void Metric::initRegister() {
   if (Gyoto::Metric::Register_) delete Gyoto::Metric::Register_;
   Gyoto::Metric::Register_ = NULL;
diff --git a/lib/Minkowski.C b/lib/Minkowski.C
index c8167fb..8aab3b6 100644
--- a/lib/Minkowski.C
+++ b/lib/Minkowski.C
@@ -215,8 +215,9 @@ void Minkowski::fillElement(Gyoto::FactoryMessenger *fmp) {
 #endif
 
 // setParameter is the minimal interface to read data from the XML.
-void Minkowski::setParameter(string name, string content, string unit){
+int Minkowski::setParameter(string name, string content, string unit){
   if      (name=="Spherical")     coordKind(GYOTO_COORDKIND_SPHERICAL);
   else if (name=="Cartesian")     coordKind(GYOTO_COORDKIND_CARTESIAN);
-  else Generic::setParameter(name, content, unit);
+  else return Generic::setParameter(name, content, unit);
+  return 0;
 }
diff --git a/lib/NumericalMetricLorene.C b/lib/NumericalMetricLorene.C
index 8f3db33..e3061eb 100644
--- a/lib/NumericalMetricLorene.C
+++ b/lib/NumericalMetricLorene.C
@@ -1630,7 +1630,8 @@ void  NumericalMetricLorene::setParameter(string name,
     r_refine_  = parms[0];
     h0_refine_ = parms[1];
   }
-  else  Generic::setParameter(name, content, unit);
+  else  return Generic::setParameter(name, content, unit);
+  return 0;
 }
 
 #ifdef GYOTO_USE_XERCES
diff --git a/lib/Object.C b/lib/Object.C
new file mode 100644
index 0000000..4a96d12
--- /dev/null
+++ b/lib/Object.C
@@ -0,0 +1,219 @@
+#include "GyotoObject.h"
+#include "GyotoError.h"
+#include "GyotoFactoryMessenger.h"
+
+#include <iostream>
+
+using namespace std ;
+using namespace Gyoto ;
+
+Property const * const Object::properties = NULL;
+
+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, 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);
+  }
+}
+
+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);
+}
+
+void Object::set(Property const &p, string const &val) {
+  throwError("called");
+  if (p.type != Property::bool_t)
+    throwError("Property is no a bool");
+  cerr << "Object::set("<<p.name<<", "<<val<<")"<<std::endl<<std::endl;
+  set(p, val==p.name);
+}
+
+// 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) {
+  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::get(Property const &p, double &val, std::string const &unit) {
+  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 set this Property with unit");
+    get(p, val);
+  }
+}
+
+
+void Object::get(Property const &p, bool &val) {
+  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)();
+}
+
+void Object::set(Property const &p, string &val) {
+  if (p.type != Property::bool_t)
+    throwError("Property is no a bool");
+  bool bval;
+  get(p, bval);
+  if (bval) val=p.name;
+  else val=p.name_false;
+}
+
+// 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);
+}
+
+Property const * Object::getProperties() const {
+  return properties;
+}
+
+
+#ifdef GYOTO_USE_XERCES
+void Object::fillProperty(Gyoto::FactoryMessenger *fmp, Property const &p) {
+  string name=p.name;
+  switch (p.type) {
+  case Property::bool_t:
+    {
+      bool val;
+      get(p, val);
+      fmp->setParameter(val?name:p.name_false);
+    }
+    break;
+  case Property::double_t:
+    {
+      double val;
+      get(p, val);
+      fmp->setParameter(name, val);
+    }
+    break;
+  default:
+    throwError("Unimplemented");
+  }
+}
+
+void Object::fillElement(Gyoto::FactoryMessenger *fmp) {
+  fmp -> setSelfAttribute("kind", kind_);
+
+  Property const * prop = getProperties();
+  if (prop) {
+    fillProperty(fmp, *prop);
+    if (prop->parents) {
+      Property const * const * parent;
+      for (parent=prop->parents; *parent; ++parent) {
+	fillProperty(fmp, **parent);
+      } 
+    }
+  }
+}
+
+void Object::setParameters(Gyoto::FactoryMessenger *fmp)  {
+  string name="", content="", unit="";
+  if (fmp)
+    while (fmp->getNextParameter(&name, &content, &unit))
+      setParameter(name, content, unit);
+}
+
+#endif
+
+int Object::setParameter(string name, string content, string unit) {
+  Property const * prop = property(name);
+  if (!prop) {
+    std::string errmsg="Object::setParameter(): no such property: ";
+    errmsg += name;
+    throwError(errmsg);
+  }
+  switch (prop->type) {
+  case Property::bool_t:
+    Object::set(*prop, name==prop->name);
+    return 0;
+  case Property::double_t:
+    set(*prop, atof(content.c_str()), unit);
+    return 0;
+  default:;
+  }
+  return 1;
+}
+
+//// Property
+
+Property::Property(string n, set_double_t set, get_double_t get,
+		   Property const * const * ancestors)
+  : name(n), type(double_t), parents(ancestors) {
+  setter.set_double=set;
+  getter.get_double=get;
+  setter_unit.set_double=NULL;
+  getter_unit.get_double=NULL;
+}
+
+Property::Property(string n, set_double_t set, get_double_t get,
+		   set_double_unit_t setu, get_double_unit_t getu,
+		   Property const * const * ancestors)
+  : name(n), type(double_t), parents(ancestors) {
+  setter.set_double=set;
+  getter.get_double=get;
+  setter_unit.set_double=setu;
+  getter_unit.get_double=getu;
+}
+
+Property::Property(string n, string nf, set_bool_t set, get_bool_t get,
+		   Property const * const * ancestors)
+  : name(n), name_false(nf), type(bool_t), parents(ancestors) {
+  setter.set_bool=set;
+  getter.get_bool=get;
+}
+
+Property const * Property::find(std::string n) const {
+  if (this == NULL) return NULL;
+  if (name == n || (type == bool_t && name_false == n)) return this;
+  if (parents == NULL) return NULL;
+  Property const * const * p ;
+  Property const * result = NULL;
+  for (p=parents;  *p != NULL; ++p) {
+    result = (*p)->find(n);
+    if (result) break;
+  }
+  return result; 
+}
diff --git a/lib/Photon.C b/lib/Photon.C
index 1f1cd18..170f47c 100644
--- a/lib/Photon.C
+++ b/lib/Photon.C
@@ -583,8 +583,16 @@ SmartPointer<Photon> Gyoto::Photon::Subcontractor(FactoryMessenger* fmp) {
 
   SmartPointer<Photon> ph = new Photon();
   ph -> astrobj( fmp->astrobj() );
-  ph -> setParameters(fmp);
+  ph -> Worldline::setParameters(fmp);
+  ph -> SmartPointee::setParameters(fmp);
 
   return ph;
 }
 #endif
+
+int Photon::setParameter(std::string name,
+			   std::string content,
+			 std::string unit) {
+  return (Worldline::setParameter(name, content, unit) &&
+	  SmartPointee::setParameter(name, content, unit));
+}
diff --git a/lib/PowerLawSpectrum.C b/lib/PowerLawSpectrum.C
index 4177ed1..7d81d71 100644
--- a/lib/PowerLawSpectrum.C
+++ b/lib/PowerLawSpectrum.C
@@ -49,13 +49,14 @@ void Spectrum::PowerLaw::fillElement(FactoryMessenger *fmp) const {
   Spectrum::Generic::fillElement(fmp);
 }
 
-void Gyoto::Spectrum::PowerLaw::setParameter(std::string name,
+int Gyoto::Spectrum::PowerLaw::setParameter(std::string name,
 			      std::string content,
 			      std::string unit) {
   char * tc=const_cast<char*>(content.c_str());
   if (name=="Exponent") exponent(atof(tc));
   else if (name=="Constant") constant(atof(tc));
-  else Spectrum::Generic::setParameter(name, content, unit);
+  else return Spectrum::Generic::setParameter(name, content, unit);
+  return 0;
 }
 
 #endif
diff --git a/lib/RotStar3_1.C b/lib/RotStar3_1.C
index f904822..6c5288e 100644
--- a/lib/RotStar3_1.C
+++ b/lib/RotStar3_1.C
@@ -767,7 +767,8 @@ void RotStar3_1::fillElement(Gyoto::FactoryMessenger *fmp) {
 void RotStar3_1::setParameter(string name, string content, string unit){
   if      (name=="IntegKind")     integKind(atoi(content.c_str()));
   else if (name=="File")          fileName(content.c_str());
-  else Generic::setParameter(name, content, unit);
+  else return Generic::setParameter(name, content, unit);
+  return 0;
 }
 
 void RotStar3_1::setParameters(FactoryMessenger* fmp) {
diff --git a/lib/SmartPointer.C b/lib/SmartPointer.C
index 0d76745..850505f 100644
--- a/lib/SmartPointer.C
+++ b/lib/SmartPointer.C
@@ -30,8 +30,15 @@ Gyoto::SmartPointee::SmartPointee() :
   pthread_mutex_init(&mutex_, NULL);
 #endif
 }
-Gyoto::SmartPointee::SmartPointee(const SmartPointee&) :
-  refCount (0)
+Gyoto::SmartPointee::SmartPointee(std::string name) :
+  Object(name), refCount (0)
+{
+#ifdef HAVE_PTHREAD
+  pthread_mutex_init(&mutex_, NULL);
+#endif
+}
+Gyoto::SmartPointee::SmartPointee(const SmartPointee&o) :
+  Object(o), refCount (0)
 {
 #ifdef HAVE_PTHREAD
   pthread_mutex_init(&mutex_, NULL);
diff --git a/lib/Spectrum.C b/lib/Spectrum.C
index 9cba688..b37f051 100644
--- a/lib/Spectrum.C
+++ b/lib/Spectrum.C
@@ -120,8 +120,6 @@ double Spectrum::Generic::operator()(double nu, double opacity, double ds)
   return 0.;
 }
 
-void Spectrum::Generic::setParameter(std::string, std::string, std::string) {}
-
 #ifdef GYOTO_USE_XERCES
 // do nothing... for now
 void Spectrum::Generic::fillElement(FactoryMessenger *fmp ) const {

-- 
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