Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

parameter.h

Go to the documentation of this file.
00001 
00007 #ifndef ___PARAMETER_H___
00008 #define ___PARAMETER_H___
00009 
00010 
00011 #include <stdio.h>
00012 #include <string>
00013 using std::string;
00014 
00015 #include "msg.h"
00016 #include "tristate.h"
00017 #include "stringutils.h"
00018 #include "polymorph.h"
00019 
00020 
00021 /*    Parameter datatypes    */
00022 #define PARAM_USTRING         0
00023 #define PARAM_3BOOL           1
00024 #define PARAM_INT             2
00025 #define PARAM_DOUBLE          3
00026 #define PARAM_BOOL            4
00027 
00028 
00029 // Can this be eliminated?
00030 typedef int cmdstat; 
00031 
00032 #define SETFN_ARGS2  const string& name, Typeless& param, const Typeless& newvalue
00033 typedef cmdstat (*ParamSetFn2)( SETFN_ARGS2 );
00034 
00035 
00036 class SetFnWrapper2 {
00037 public:
00038   SetFnWrapper2() { }
00039   virtual ~SetFnWrapper2() { }
00040   virtual cmdstat operator() ( SETFN_ARGS2 )=0; 
00041 };
00042 
00043 
00044 #define SETFN_DECLARE2(fnname)                             \
00045 cmdstat fnname( SETFN_ARGS2 );                              \
00046 struct setfnobj2_ ## fnname : public SetFnWrapper2 {         \
00047   cmdstat operator() ( SETFN_ARGS2 )  {                       \
00048     return fnname(name,param,newvalue);                        \
00049   }                                                             \
00050 }
00051 
00052 
00054 #define SETFNOBJ_DECLARE2(Owner,fnname)                   \
00055 cmdstat fnname ( SETFN_ARGS2 );                            \
00056 class setfnobj2_ ## fnname : public SetFnWrapper2 {         \
00057   Owner* owner;                                              \
00058 public:                                                       \
00059   setfnobj2_ ## fnname (Owner* owner_i) : owner(owner_i) { };  \
00060   cmdstat operator() ( SETFN_ARGS2 )  {                         \
00061     return owner->fnname(name,param,newvalue);                   \
00062   }                                                               \
00063 };                                                                 \
00064 friend class setfnobj2_ ## fnname
00065 
00066 
00067 
00079 template <class T=int>
00080 class ParameterDefinition {
00081 
00082 public:
00083   typedef ParameterDefinition<T> self;
00084 
00086   ParameterDefinition(const Typeless& externallocation, const char *name_i="", 
00087                         bool is_constant_i=false)
00088   : val_ptr(externallocation.clone(),true),
00089     name_str(name_i), constant(is_constant_i),
00090     been_set(false), doc(0),
00091     low_bound(new Polymorph<int>(0),true), enforce_lower(false),
00092     upp_bound(new Polymorph<int>(0),true), enforce_upper(false),
00093     setfn2(0) {  }
00094 
00096   ParameterDefinition()
00097   : val_ptr(new Polymorph<int>(0),true),
00098     name_str(""), constant(false),
00099     been_set(false), doc(0),
00100     low_bound(new Polymorph<int>(0),true), enforce_lower(false),
00101     upp_bound(new Polymorph<int>(0),true), enforce_upper(false),
00102     setfn2(0) {  }
00103   
00104   int  check2() const {  return check2(datavalue());  }
00105   int  check2(const Typeless& val) const;
00106 
00107   string usage_string(const string prefix="")  const;
00108   string doc_string(const string prefix="")    const
00109     {  return usage_string(prefix) + (doc? "\n\n" + documentation() : "") + "\n";  }
00110 
00111   template <class BT>
00112   self& add_lower_bound(const BT& bound)
00113     {  low_bound=PolymorphPtr(new Polymorph<BT>(bound),true); enforce_lower = true; return *this;  }
00114   
00115   template <class BT>
00116   self& add_upper_bound(const BT& bound)
00117     {  upp_bound=PolymorphPtr(new Polymorph<BT>(bound),true); enforce_upper = true; return *this;  }
00118     
00119   
00123   self& add_doc(const char* docstring)     {  doc=docstring;      return *this;  }
00124 
00128   self& add_default_expr(const string& expr) {  default_expr=expr;  return *this;  }
00129 
00139   self& add_setfn(SetFnWrapper2* fnobj)    {  setfn2 = fnobj;     return *this;  }
00140 
00141   const char * get_default_expr() const   {  return default_expr!="" ? default_expr.c_str() : 0;  }
00142 
00149   string stringrep(const Typeless& value, const string& flags="", bool pretty=false) const {
00150     return (pretty?
00151             value.prettyprint( String::StreamFormat(flags)) :
00152             value.stringrep(   String::StreamFormat(flags)));
00153   }
00154   
00155   string stringrep(const string& flags="", bool pretty=false) const
00156     {  return stringrep(datavalue(),flags,pretty);  }
00157 
00158   void mark_set() {  been_set=true;  }
00159   bool has_been_set() const {  return been_set;  }
00160 
00161   bool set(const StringParser& parser, const string& s,
00162            bool mark=true, bool verbose=changes_verbose,
00163            const string& prefix="");
00170   void update_default_value(const StringParser& sp) {
00171     if (!has_been_set() && get_default_expr())
00172       set(sp,get_default_expr(),false);
00173   }
00174   
00177   bool definition_matches(const self& o) const
00178     {  return (name()==o.name() && is_constant()==o.is_constant() &&
00179                datavalue().typestring()==o.datavalue().typestring());  }
00180 
00181   bool is_constant()      const {  return constant;  }
00182   bool is_valid()         const {  return (!name_str.empty() && val_ptr.valueptr()!=0);  }
00183 
00184   inline const Typeless& datavalue() const {  return *val_ptr;  }
00185   
00186   inline       Typeless& datavalue()       {  return *(val_ptr.valueptr());  }
00187 
00188   string print_to_str(const string prefix="") const {
00189     /* Protects string substitution commands so that they are not taken literally when executed */ 
00190     const string rep = String::replace_all(stringrep(datavalue(),"",true),string("$"),string("$$$$"));
00191     return ("set " + prefix + name() + "=" + rep);
00192   }
00193       
00194   const string&  name() const {  return name_str;  }
00195 
00197   bool operator<(const self& o) const {  return( name() < o.name());  }
00198 
00199   static void message(Msg::MessageLevel m, const string& s)
00200     {  if (mhp && *mhp) (**mhp)(m,s);  }
00201   
00202   static bool changes_verbose; 
00206   self* duplicate() const {
00207     self* o = new self(*this);
00208     o->val_ptr = PolymorphPtr((*val_ptr).duplicate());
00209     return o;
00210   };
00211 
00212 private:
00213   static Msg::LevelHandler<>** mhp;
00214 
00215   typedef OwningPointer<Typeless,CopyUsingClone<Typeless> > PolymorphPtr;
00216 
00217   PolymorphPtr val_ptr;             
00218   string name_str;                  
00219   bool constant;                    
00220   string default_expr;              
00221   int been_set;                     
00222   const char *doc;                  
00223   PolymorphPtr low_bound;           
00224   int enforce_lower;                
00225   PolymorphPtr upp_bound;           
00226   int enforce_upper;                
00227   SetFnWrapper2* setfn2;            
00229   string documentation() const;
00230   string type_string()   const {  return datavalue().typestring();  }
00231   string value_string()  const {  return stringrep(datavalue(),"",true);  }
00232   string range_string()  const
00233     {  return string("[" + (enforce_lower? stringrep(*low_bound,"",true) : "*") +
00234                      "," + (enforce_upper? stringrep(*upp_bound,"",true) : "*") + "]");  }
00235 };
00236 
00237 
00238 
00239 /* Static variables */
00240 template <class T>
00241 Msg::LevelHandler<>** ParameterDefinition<T>::mhp=&(Msg::LevelHandler<>::default_instance());
00242 template<class T>
00243 bool ParameterDefinition<T>::changes_verbose=true;
00244 
00245 
00246 
00250 template <class T>
00251 bool ParameterDefinition<T>::set(const StringParser& parser, const string& s,
00252                                  bool mark, bool verbose, const string& prefix)
00253 {
00254   if (!is_valid())
00255     return false;
00256   
00257   if (is_constant()) {
00258     message(Msg::Error,"Can't change value of symbolic constant "+prefix+name());
00259     return false;
00260   }
00261 
00262   Typeless&       existing = *(val_ptr.valueptr());
00263   const Typeless* newvalue = (*val_ptr).parse(parser,s);
00264   
00265   if (check2(*newvalue))
00266     return false;
00267 
00268   if (mark) mark_set();
00269 
00270   bool status=true;
00271 
00272   /* Uses string representation as the standard to decide whether a value has changed */
00273   const string originalrep = stringrep();
00274   if (setfn2) status = ((*setfn2)(name(),existing,    *newvalue)>=0);
00275   else                                   existing.set(*newvalue);
00276 
00277   if (verbose && !(stringrep() == originalrep))
00278     message(Msg::Notify,"Changed parameter " + prefix + name() + " to " + stringrep("",true) + "");
00279 
00280   return true;
00281 }
00282 
00283 
00284 
00289 template <class T>
00290 int ParameterDefinition<T>::check2(const Typeless& value) const
00291 {
00292   if (enforce_lower && value < *low_bound ) {
00293     message(Msg::Error,name()+" too small (" + value.stringrep() +
00294             " < " + (*low_bound).stringrep() + ")");
00295     return 1;
00296   }
00297   
00298   if (enforce_upper && value > *upp_bound) {
00299     message(Msg::Error,name()+" too large (" + value.stringrep() +
00300             " > " + (*upp_bound).stringrep() + ")");
00301     return 1;
00302   }
00303 
00304   return 0;
00305 }
00306 
00307 
00308 
00309 template <class T>
00310 string ParameterDefinition<T>::usage_string(const string prefix)  const
00311 {
00312   const int    colpos  = 40; /* Position of second column */
00313   const string column1 = prefix+name()+"="+value_string() 
00314     + (get_default_expr()? " [default: " + default_expr + "] " : string(" "));
00315 
00316   const string spaces(std::max(0,int((colpos-1)-column1.length())),' ');
00317   const string column2 = 
00318     "(" + type_string() +
00319     (constant? " constant" : 
00320      (enforce_lower || enforce_upper ? 
00321       " with range " + range_string() : "")) + ")";
00322   
00323   return column1 + spaces + column2;
00324 }
00325 
00326 
00327 
00329 template <class T>
00330 string ParameterDefinition<T>::documentation() const
00331 {
00332   string s = doc;
00333   unsigned pos;
00334   const string namemarker="%s";
00335   while ((pos=s.find(namemarker))<s.length())
00336     s.replace(pos,namemarker.length(),name());
00337   return s;
00338 }
00339 
00340 
00341 
00342 #endif /* ___PARAMETER_H___ */

Generated on Mon Jan 20 02:35:45 2003 for RF-LISSOM by doxygen1.3-rc2