Jafar
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
parents.hpp
Go to the documentation of this file.
00001 
00009 #ifndef __rtslam_parents_H__
00010 #define __rtslam_parents_H__
00011 
00012 #include <list>
00013 #include <vector>
00014 #include <iostream>
00015 #include <boost/smart_ptr.hpp>
00016 #include <boost/bind.hpp>
00017 
00018 #include "rtslam/rtSlam.hpp"
00019 
00020 
00021 namespace jafar {
00026   namespace rtslam {
00027 
00028 
00029 
00030 /* --- PARENT --------------------------------------------------------------- */
00031 /* --- PARENT --------------------------------------------------------------- */
00032 /* --- PARENT --------------------------------------------------------------- */
00033 
00034 /* Use this generic class by inhereting from it in the parent class.
00035  * The child class can be known only partially:
00036  * (ie class Child; class Parent : public ParentOf<Child> {...}; class Child { ... };)
00037  */
00038 template<class Child>
00039 class ParentOf {
00040 public:
00041   typedef boost::shared_ptr<Child> Child_ptr;
00042   typedef std::list<Child_ptr> ChildList;
00043 
00044 public:
00045   ChildList childList;
00046 
00047 public:
00048   ~ParentOf(void) {
00049 //    std::cout << "Destroy Parent. " << std::endl;
00050   }
00051 
00052   void registerChild(const Child_ptr & ptr) {
00053     childList.push_back(ptr);
00054   }
00055   void unregisterChild(const Child_ptr & ptr) {
00056 //    remove(childList.begin(), childList.end(), ptr);
00057     childList.remove(ptr);
00058 //    childList.pop_back();
00059   }
00060 
00061   void display(std::ostream& os) const {
00062     os << "PTR LIST [ ";
00063     for (typename ChildList::const_iterator iter = childList.begin(); iter
00064         != childList.end(); ++iter) {
00065       os << iter->get() << " ";
00066     }
00067     os << " ]";
00068   }
00069 };
00070 
00071 /* The Macro define a type to access to ParentOf::ChildList, with name <TYPE>List,
00072  * plus two accessors (const and non-const) to access directly to the list
00073  * of children, with name <ACCESS>List().
00074  */
00075 #define ENABLE_ACCESS_TO_CHILDREN(Child,typeName,accessName)    \
00076   public: typedef ParentOf<Child>::ChildList typeName##List; \
00077   typeName##List & accessName##List( void )           \
00078   {  return ParentOf<Child>::childList; }     \
00079   const typeName##List & accessName##List( void ) const           \
00080   {  return ParentOf<Child>::childList; }     \
00081 
00082 
00083 /* --- CHILD ---------------------------------------------------------------- */
00084 /* --- CHILD ---------------------------------------------------------------- */
00085 /* --- CHILD ---------------------------------------------------------------- */
00086 
00087 /* Use this generic class by inhereting from it in the child class.
00088  * The parent class can be known only partially:
00089  * (ie class Parent; class Child : public ChildOf<Parent> {...}; class Parent { ... };)
00090  */
00091 template<class Parent>
00092 class ChildOf {
00093 public:
00094   typedef boost::weak_ptr<Parent> Parent_wptr;
00095   typedef boost::shared_ptr<Parent> Parent_ptr;
00096 
00097 private:
00098   Parent_wptr parent_wptr;
00099 
00100 public:
00101 
00103   ~ChildOf(void) {
00104     unlinkFromParent();
00105   }
00106 
00107   void linkToParent(const boost::shared_ptr<Parent> & ptr) {
00108     parent_wptr = ptr;
00109   }
00111   void unlinkFromParent(void) {
00112     parent_wptr.reset();
00113   }
00114 
00117   Parent_ptr parentPtr(void) {
00118     Parent_ptr sptr = parent_wptr.lock();
00119     if (!sptr) {
00120       std::cerr << __FILE__ << ":" << __LINE__ << " ChildOf::parentPtr threw weak" << std::endl;
00121       throw "WEAK";
00122     }
00123     return sptr;
00124   }
00125   const Parent_ptr parentPtr(void) const {
00126     Parent_ptr sptr = parent_wptr.lock();
00127     if (!sptr) {
00128       std::cerr << __FILE__ << ":" << __LINE__ << " ChildOf::parentPtr threw weak" << std::endl;
00129       throw "WEAK";
00130     }
00131     return sptr;
00132   }
00133   Parent& parent(void) {
00134     Parent_ptr sptr = parent_wptr.lock();
00135     if (!sptr) {
00136       std::cerr << __FILE__ << ":" << __LINE__ << " ChildOf::parent threw weak" << std::endl;
00137       throw "WEAK";
00138     }
00139     return *sptr;
00140   }
00141   const Parent& parent(void) const {
00142     Parent_ptr sptr = parent_wptr.lock();
00143     if (!sptr) {
00144       std::cerr << __FILE__ << ":" << __LINE__ << " ChildOf::parent const threw weak" << std::endl;
00145       throw "WEAK";
00146     }
00147     return *sptr;
00148   }
00149 
00150   void display(std::ostream& os) const {
00151     os << this << "->" << parent_wptr.lock().get();
00152   }
00153 
00154 };
00155 
00156 /* Connect the link to the Parent, and register into parent.
00157  * To be defined as a public member of the child class. The name
00158  * of the Child class has to be specified explicitely.
00159  * PRE:
00160  *  - The class <Parent> should be known at the call of the macros.
00161  *  - The child class (where the macro is called) should have enable_shared_from_this.
00162  */
00163 #define ENABLE_LINK_TO_FATHER(Parent,Child)                   \
00164     public: void linkToParent( boost::shared_ptr<Parent> ptr )          \
00165   {                                                           \
00166     ChildOf<Parent>::linkToParent(ptr);                       \
00167     ptr->ParentOf<Child>::registerChild(shared_from_this());  \
00168   }
00169 
00170 /* Same as before, except that the function is defined with
00171  * name linkToParent<Parent> (ie, for Parent=Sen, linkToParentSen). */
00172 #define ENABLE_LINK_TO_PARENT(Parent,name,Child)              \
00173     public: void linkToParent##name( boost::shared_ptr<Parent> ptr )  \
00174   {                                                           \
00175     ChildOf<Parent>::linkToParent(ptr);                       \
00176     ptr->ParentOf<Child>::registerChild(shared_from_this());  \
00177   }
00178 
00179 /* Define three accessor function, one to the pointer, two on
00180  * the reference (const and non-const). The function are called
00181  * fatherPtr() and father() respectively.
00182  */
00183 #define ENABLE_ACCESS_TO_FATHER(Parent)                       \
00184     public: \
00185   boost::shared_ptr<Parent> father##Ptr( void )               \
00186   {  return ChildOf<Parent>::parentPtr(); }                   \
00187   const boost::shared_ptr<Parent> father##Ptr( void ) const               \
00188   {  return ChildOf<Parent>::parentPtr(); }                   \
00189   Parent& father( void )                                      \
00190   {    return ChildOf<Parent>::parent();  }                   \
00191   const Parent& father( void ) const                          \
00192   {    return ChildOf<Parent>::parent();  }
00193 
00194 /* Same as before, except that the function is given an
00195  * explicit name, to handle the case of multiple parent.
00196  */
00197 #define ENABLE_ACCESS_TO_PARENT(Parent,accessName)            \
00198     public: \
00199   boost::shared_ptr<Parent> accessName##Ptr( void )           \
00200   {  return ChildOf<Parent>::parentPtr(); }                   \
00201   const boost::shared_ptr<Parent> accessName##Ptr( void ) const           \
00202   {  return ChildOf<Parent>::parentPtr(); }                   \
00203   Parent& accessName( void )                                  \
00204   {    return ChildOf<Parent>::parent();  }                   \
00205   const Parent& accessName( void ) const                      \
00206   {    return ChildOf<Parent>::parent();  }
00207 
00208 /* The ENABLE_LINK_TO_PARENT could be modified to link in the other way.
00209  * However, it is not possible a priori to have both initialization enabled
00210  * at the same time. Work to be done if need.
00211  */
00212 
00213 /* --- SPECIFIC CHILD ------------------------------------------------------- */
00214 /* --- SPECIFIC CHILD ------------------------------------------------------- */
00215 /* --- SPECIFIC CHILD ------------------------------------------------------- */
00216 
00217 /* Use this generic class by inhereting from it in the child class.
00218  * The parent class can be known only partially:
00219  * (ie class Parent; class Child : public ChildOf<Parent> {...}; class Parent { ... };)
00220  */
00221 template<class Parent>
00222 class SpecificChildOf {
00223 public:
00224   typedef boost::weak_ptr<Parent> Parent_wptr;
00225   typedef boost::shared_ptr<Parent> Parent_ptr;
00226 
00227 public:
00228   Parent_wptr parent_wptr;
00229 
00230 public:
00231 
00233   ~SpecificChildOf(void) {
00234     unlinkFromParent();
00235   }
00236 
00237   template<class ParentAbstract>
00238   void linkToParentSpecific(const boost::shared_ptr<ParentAbstract> & ptr) {
00239     boost::shared_ptr<Parent> spec_ptr =
00240         SPTR_CAST<Parent>(ptr);
00241     parent_wptr = spec_ptr;
00242   }
00243 
00244   void linkToParentSpecific(const boost::shared_ptr<Parent> & ptr) {
00245     parent_wptr = ptr;
00246   }
00247 
00249   void unlinkFromParent(void) {
00250     parent_wptr.reset();
00251   }
00252 
00255   Parent_ptr parentPtr(void) {
00256     Parent_ptr sptr = parent_wptr.lock();
00257     if (!sptr) {
00258       std::cerr << __FILE__ << ":" << __LINE__ << " SpecificChildOf::parentPtr threw weak" << std::endl;
00259       throw "WEAK";
00260     }
00261     return sptr;
00262   }
00263   Parent& parent(void) {
00264     Parent_ptr sptr = parent_wptr.lock();
00265     if (!sptr) {
00266       std::cerr << __FILE__ << ":" << __LINE__ << " SpecificChildOf::parent threw weak" << std::endl;
00267       throw "WEAK";
00268     }
00269     return *sptr;
00270   }
00271   const Parent& parent(void) const {
00272     Parent_ptr sptr = parent_wptr.lock();
00273     if (!sptr) {
00274       std::cerr << __FILE__ << ":" << __LINE__ << " SpecificChildOf::parent const threw weak" << std::endl;
00275       throw "WEAK";
00276     }
00277     return *sptr;
00278   }
00279 
00280   void display(std::ostream& os) const {
00281     os << this << "->" << parent_wptr.lock().get();
00282   }
00283 
00284 };
00285 
00295 #define ENABLE_LINK_TO_SPECIFIC_FATHER(ParentGen,ParentSpec,Child)   \
00296     public: void linkToParent( const boost::shared_ptr<ParentGen>& ptr )       \
00297   {                                                                  \
00298     ChildOf<ParentGen>::linkToParent( ptr );                         \
00299     SpecificChildOf<ParentSpec>::linkToParentSpecific( ptr );        \
00300     ptr->ParentOf<Child>::registerChild(shared_from_this());         \
00301   } \
00302   void linkToParent( const boost::shared_ptr<ParentSpec>& ptr )      \
00303   {                                                                  \
00304     ChildOf<ParentGen>::linkToParent( ptr );                         \
00305     SpecificChildOf<ParentSpec>::linkToParentSpecific( ptr );        \
00306     ptr->ParentOf<Child>::registerChild(shared_from_this());         \
00307   }
00308 
00309 #define ENABLE_LINK_TO_SPECIFIC_PARENT(ParentGen,ParentSpec,name,Child)         \
00310     public: void linkToParent##name( const boost::shared_ptr<ParentGen>& ptr )  \
00311   {                                                                             \
00312     ChildOf<ParentGen>::linkToParent( ptr );                                    \
00313     SpecificChildOf<ParentSpec>::linkToParentSpecific( ptr );                   \
00314     ptr->ParentOf<Child>::registerChild(shared_from_this());                    \
00315   }                                                                             \
00316   void linkToParent##name( const boost::shared_ptr<ParentSpec>& ptr )           \
00317   {                                                                             \
00318     ChildOf<ParentGen>::linkToParent( ptr );                                    \
00319     SpecificChildOf<ParentSpec>::linkToParentSpecific( ptr );                   \
00320     ptr->ParentOf<Child>::registerChild(shared_from_this());                    \
00321   }
00322 
00323 /* Define three accessors (to the pointer and to the const/non-const reference)
00324  * with names <ACCESS>Ptr() and <ACCESS>().
00325  */
00326 #define ENABLE_ACCESS_TO_SPECIFIC_PARENT(Parent,accessName)         \
00327     public: boost::shared_ptr<Parent> accessName##Ptr( void )       \
00328   {  return SpecificChildOf<Parent>::parentPtr(); }                 \
00329   Parent& accessName( void )                                        \
00330   {    return SpecificChildOf<Parent>::parent();  }                 \
00331   const Parent& accessName( void ) const                            \
00332   {    return SpecificChildOf<Parent>::parent();  }
00333 
00334 
00335 
00336 
00337 
00338 
00339 /* --- WEAK PARENT --------------------------------------------------------- */
00340 /* --- WEAK PARENT --------------------------------------------------------- */
00341 /* --- WEAK PARENT --------------------------------------------------------- */
00342 
00343 /* The weak-parent paradigm is similar to the parent one, except that
00344  * only weak-ptr are stored. This means that there is no "owner" relation
00345  * from the parent on the child (ie, the child is not destroyed when father dies
00346  * (good news for the child ;) ).
00347  *
00348  * Use this generic class by inhereting from it in the parent class.
00349  * The child class can be known only partially:
00350  * (ie class Child; class WeakParent : public WeakParentOf<Child> {...}; class Child { ... };)
00351  *
00352  * Use: the class just have to inherit (public) from WeakParentOf<Child>, with Child
00353  * a partially known class. For convenience, the macro ENABLE_ACCESS_TO_CHILDREN()
00354  * macro can be called inside the class for some extra accessor-aliases definition.
00355  * The child class has to inherit from the standard ChildOf<Parent> class, with
00356  * parent full defined. The weak-specific macros has to be used (see below).
00357  * As a new requierement, the UNREGISTER_FROM_WEAK_PARENT has to be called in the
00358  * destructor of the (weak)-child.
00359  */
00360 template<class Child>
00361 class WeakParentOf {
00362 public:
00363   typedef boost::shared_ptr<Child> Child_ptr;
00364   typedef boost::weak_ptr<Child> Child_wptr;
00365   typedef std::vector<Child_wptr> ChildList;
00366 
00367 protected: // Iterator
00368 
00369   /* iterator and const_iterator enables a direct use of  the list of child,
00370    * by defining a *iter that lock() the weak to a shared.
00371    * use for( iterator iter = childList().begin(); iter != childList().end(); ++iter ) ...
00372    */
00373 
00374   template< class basic_iterator>
00375   class generic_iterator
00376   {
00377   public:
00378     typedef Child_ptr Insider;
00379 
00380   protected:
00381     basic_iterator iter;
00382   private:
00383     generic_iterator( void ) {}
00384   public:
00385     generic_iterator( const  basic_iterator&  i ) : iter(i) {}
00386     generic_iterator& operator++ ( void ) { iter++; return *this; }
00387     generic_iterator& operator++ ( int ) { iter++; return *this; }
00388     friend bool operator== ( const generic_iterator & i1, const generic_iterator & i2 )
00389     { return i1.iter == i2.iter; }
00390     friend bool operator!= ( const generic_iterator & i1, const generic_iterator & i2 )
00391     { return i1.iter != i2.iter; }
00392     friend bool operator== ( const generic_iterator & i1, const  basic_iterator & i2 )
00393     { return i1.iter == i2; }
00394     friend bool operator!= ( const generic_iterator & i1, const  basic_iterator & i2 )
00395     { return i1.iter != i2; }
00396     friend bool operator== ( const  basic_iterator & i1, const generic_iterator & i2 )
00397     { return i1 == i2.iter; }
00398     friend bool operator!= ( const  basic_iterator & i1, const generic_iterator & i2 )
00399     { return i1 != i2.iter; }
00400 
00401     operator bool ( void )
00402     { return (! iter->expired()); }
00403 
00404     Insider operator* (void)
00405     {
00406       Insider ptr = iter->lock();
00407       if(! ptr )
00408   {
00409     std::cerr << __FILE__ << ":" << __LINE__ << " WeakParentOf::operator* threw weak" << std::endl;
00410     throw "WEAK";
00411   }
00412       return ptr;
00413     }
00414   };
00415 
00416   typedef typename WeakParentOf<Child>::ChildList ExChildList;
00417   typedef typename WeakParentOf<Child>::ChildList::iterator basic_iterator;
00418   typedef typename WeakParentOf<Child>::ChildList::const_iterator basic_const_iterator;
00419 
00420 public:
00421   typedef generic_iterator<basic_iterator> iterator;
00422   typedef generic_iterator<basic_const_iterator> const_iterator;
00423 
00424 public:
00425   ChildList childList;
00426 
00427 public:
00428   ~WeakParentOf(void) {
00429 //    std::cout << "Destroy Parent. " << std::endl;
00430   }
00431 
00432   void registerChild(const Child_ptr & ptr) {
00433     Child_wptr wptr = ptr;
00434     childList.push_back(wptr);
00435   }
00436 
00437   /* Predicate fonctor to compare a weak_ptr to a reference
00438    * shared_ptr. */
00439   struct WeakPtrComparison
00440   {
00441     Child_ptr refptr;
00442     WeakPtrComparison( const Child_ptr & ptr ) : refptr(ptr) {}
00443     bool operator() (const Child_wptr & wptr)
00444     {
00445       Child_ptr ptr = wptr.lock();
00446       return refptr == ptr;
00447     }
00448   };
00449 
00450 
00451   void unregisterChild(const Child_ptr & ptr)
00452   {
00453     childList.erase(remove_if(childList.begin(), childList.end(),
00454             WeakPtrComparison(ptr)  ),
00455         childList.end());
00456   }
00457 
00458   /* Remove all expired weak pointers from the list.
00459    * Use that in the destructor of the weak child (when the weak pointed object
00460    * is destroyed, the corresponding weak pointer is set to expired
00461    * before entering the weak-pointed destructor).
00462    */
00463   void cleanExpired( void )
00464   {
00465     childList.erase(remove_if(childList.begin(), childList.end(),
00466             boost::bind(&Child_wptr::expired,_1)  ),
00467         childList.end());
00468   }
00469 
00470   void display(std::ostream& os) const { // TODO: should be const
00471     os << "PTR LIST [ ";
00472     for ( const_iterator iter = childList.begin(); iter!= childList.end(); ++iter)
00473       {
00474   if( iter )
00475     {Child_ptr toto = *iter;  os << toto.get() << " ";}
00476   else { os << "--expired-- ";}
00477       }
00478     os << " ]";
00479   }
00480 };
00481 
00482 /* The Macro define a type to access to ParentOf::ChildList, with name <TYPE>List,
00483  * plus two accessors (const and non-const) to access directly to the list
00484  * of children, with name <ACCESS>List().
00485  */
00486 #define ENABLE_ACCESS_TO_WEAK_CHILDREN(Child,typeName,accessName)     \
00487   public: typedef WeakParentOf<Child>::ChildList typeName##List;  \
00488   typeName##List & accessName##List( void )       \
00489   {  return WeakParentOf<Child>::childList; }       \
00490   const typeName##List & accessName##List( void ) const     \
00491   {  return WeakParentOf<Child>::childList; }
00492 
00493 
00494 
00495 /* --- WEAK CHILD ----------------------------------------------------------- */
00496 /* --- WEAK CHILD ----------------------------------------------------------- */
00497 /* --- WEAK CHILD ----------------------------------------------------------- */
00498 
00499 /* Use this macro to define the linkToWeakParent## function. This function
00500  * **HAS TO** be called after the construction for enabling the link (cannot
00501  * be called from inside the constructor, due to shared_from_this limitation).
00502  * Similtaneously, the classical ENABLE_ACCESS_TO_PARENT can be used as upper.
00503  */
00504 #define ENABLE_LINK_TO_WEAK_PARENT(Parent,Child) \
00505   void linkToWeakParent##Parent( boost::shared_ptr<Parent> ptr )  \
00506   {                 \
00507     ChildOf<Parent>::linkToParent(ptr);         \
00508     ptr->WeakParentOf<Child>::registerChild                             \
00509          (boost::enable_shared_from_this<Child>::shared_from_this()); \
00510   }
00511 
00512 
00513 /* This macro **HAS TO** be called from inside the destructor, for removing
00514  * the corresponding (expired) smart pointer from the child list of the father.
00515  */
00516 #define UNREGISTER_FROM_WEAK_PARENT(Parent)          \
00517   try { ChildOf<Parent>::parentPtr()->cleanExpired(); } \
00518   catch(const char *e) { if (strcmp(e,"WEAK")) throw e; }
00519 
00520 
00521 /* --- SPEC WEAK CHILD ------------------------------------------------------ */
00522 /* --- SPEC WEAK CHILD ------------------------------------------------------ */
00523 /* --- SPEC WEAK CHILD ------------------------------------------------------ */
00524 
00525 /* The weak pointer can be used for specific link (ie link from abstract-parent
00526  * to the abstract-child, while simultaneously the same link from the specific-
00527  * parent to the specific-child. The abstract child inherit from ChildOf<ParentA>
00528  * and from enable_shared_from_this. The specific child inherit from
00529  * ChildOf<ParentS> but not from enable_shared_from_this. The macro
00530  * ENABLE_ACCESS can be used in both child, but the macros ENABLE_LINK
00531  * and UNREGISTER have to be used **ONLY** in the specific child class.
00532  * Example below.
00533  *
00534  * struct ChildSpec; class ChildAbs;
00535  * struct ParentAbs : public WeakParentOf<ChildAbs>
00536  * {
00537  *   ENABLE_ACCESS_TO_WEAK_CHILDREN(ChildAbs,ChildAbs,childAbs);
00538  * };
00539  * struct ParentSpec : public ParentAbs, public WeakParentOf<ChildSpec>
00540  * {
00541  *   ENABLE_ACCESS_TO_WEAK_CHILDREN(ChildSpec,ChildSpec,childSpec);
00542  * };
00543  * struct ChildAbs : public ChildOf<ParentAbs>,
00544  *         public boost::enable_shared_from_this<ParentAbs>
00545  * {
00546  *   ENABLE_ACCESS_TO_PARENT(ParentAbs,parentAbs);
00547  * };
00548  * struct ChildSpec: public ChildAbs, public ChildOf<ParentSpec>
00549  * {
00550  *   ENABLE_ACCESS_TO_PARENT(ParentSpec,parentSpec);
00551  *   ENABLE_LINK_TO_WEAK_SPECIFIC_PARENT(ParentAbs,ParentSpec,
00552  *              ChildAbs,ChildSpec,NAME);
00553  *   virtual ~ChildSpec( void )
00554  *   {
00555  *     UNREGISTER_FROM_WEAK_SPECIFIC_PARENT(ParentSpec,ChildSpec);
00556  *     UNREGISTER_FROM_WEAK_SPECIFIC_PARENT(ParentAbs,ChildAbs);
00557  *   }
00558  * };
00559  *
00560  */
00561 
00562 /* Call this macro inside the (weak-specific) child class (inheriting from
00563  * ChildOf<>), to define the function linkToWeakParent##name. The 4 types
00564  * parent/child have to be specified. */
00565 #define ENABLE_LINK_TO_WEAK_SPECIFIC_PARENT(ParentAbs,ParentSpec,ChildAbs,ChildSpec,name) \
00566   void linkToWeakParent##name( boost::shared_ptr<ParentSpec> ptr )      \
00567   {                     \
00568     ChildOf<ParentSpec>::linkToParent(ptr);                                 \
00569     ptr->WeakParentOf<ChildSpec>::registerChild                             \
00570          (SPTR_CAST<ChildSpec>(shared_from_this()));      \
00571     ChildOf<ParentAbs>::linkToParent(ptr);                                  \
00572     ptr->WeakParentOf<ChildAbs>::registerChild(shared_from_this());         \
00573   }
00574 
00575 /* Call this macro from inside the destructor of the specific child.
00576  * Remove the _this_ reference from the parents (spec and abs) childlist.
00577  */
00578 #define UNREGISTER_FROM_WEAK_SPECIFIC_PARENT(Parent,Child)  \
00579   try { ChildOf<Parent>::parentPtr()->WeakParentOf<Child>::cleanExpired(); } \
00580   catch(const char *e) { if (strcmp(e,"WEAK")) throw e; }
00581 
00582   }} // namespace jafar/rtslam
00583 
00584 #endif // #ifndef __rtslam_parents_H__
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on Wed Oct 15 2014 00:37:26 for Jafar by doxygen 1.7.6.1
LAAS-CNRS