Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

CfgPromptConfigurable.cxx

Go to the documentation of this file.
00001 #include "CfgPromptConfigurable.h"
00002 #include "CfgDialog.h"
00003 #include "MessageService/MsgService.h"
00004 #include <string.h>
00005 #include <stdlib.h>
00006 #include <typeinfo> 
00007 #include <assert.h>
00008 
00009 ClassImp(CfgPromptConfigurable)
00010 CVSID( " $Id: CfgPromptConfigurable.cxx,v 1.5 2008/10/10 23:34:22 bckhouse Exp $" );
00011 
00012 CfgPromptConfigurable::CfgPromptConfigurable()
00013 {
00062 }
00063 
00064 void CfgPromptConfigurable::InitializeConfig(const Registry& initConfig)
00065 {
00066   fConfig.UnLockKeys();
00067   fConfig.UnLockValues();
00068   fConfig.Clear();
00069   fConfig=initConfig;
00070   fConfig.SetDirty(false); // Do this whenever ConfigModified is called.
00071   fConfig.LockKeys();
00072   fConfig.UnLockValues();
00073 
00074   // For GUIs:
00075   fDefaultConfig=initConfig;
00076 
00077   ConfigModified();
00078 }
00079 
00080 Bool_t CfgPromptConfigurable::Split(const char* line, char sep, string& a, string& b)
00081 {
00082  //======================================================================
00083   // Purpose: Split a character string into two pieces given a
00084   //          separator.  Example peas::carots::beans into 
00085   //          a = peas 
00086   //          b = carots::beans
00087   //
00088   //          Or, peas -> a=peas, b=""
00089   //
00090   // Inputs: line - the text to split
00091   //         sep  - the separation character (':' in the example above)
00092   //         a    - text before the separator
00093   //         b    - text after separator
00094   //  
00095   // Return value: true if a split happened, false otherwise.
00096   //======================================================================
00097   // Clear a and b strings
00098   bool split = false;
00099   a = "";
00100   b = "";
00101   const char* c = line;
00102   while(*c != '\0') {
00103     if(*c == sep) { 
00104       split=true;
00105       break;
00106     }
00107     a+=(*c);
00108     ++c;
00109   }
00110   while(*c == sep) { ++c; };
00111   b = c;
00112   return split;
00113 }
00114 
00115 bool CfgPromptConfigurable::IsInt(const std::string& s, Int_t& i)
00116 {
00117   //======================================================================
00118   // Does the string s represent an integer?
00119   //======================================================================
00120   const char* ss = s.c_str();
00121   char* endptr;
00122   double d = strtod(ss, &endptr);
00123   if (endptr==ss && d==0.0) return false; // Conversion to double failed...
00124   
00125   // Check if this number is int or float
00126   if (strchr(ss,'.')) return false;
00127   if (strchr(ss,'E')) return false;
00128   if (strchr(ss,'e')) return false;
00129 
00130   // All checks for "intness" passed  
00131   i = atoi(ss);
00132   
00133   return true;
00134 }
00135 
00136 
00137 //......................................................................
00138 
00139 bool CfgPromptConfigurable::IsFloat(const std::string& s, Double_t& val)
00140 {
00141 //======================================================================
00142 // Does the string s represent an integer?
00143 //======================================================================
00144   char* endptr;
00145   double d = strtod(s.c_str(), &endptr);
00146   if (endptr==s && d==0.0) return false; // Conversion to double failed...
00147   
00148   // All checks for "floatness" passed
00149   val = d;
00150   return true;
00151 }
00152 
00153 
00154 void CfgPromptConfigurable::Set(CfgDialog* d) 
00155 {
00156 //======================================================================
00157 // Update the configuration parameters. Allow a CfgDialog object to be
00158 // passed in. If none is passed in use the default, text based dialog
00159 // object.
00160 //======================================================================
00161   bool deleteDialog = false;
00162   if (d==0) {
00163     d = new CfgDialog();
00164     deleteDialog = true;
00165   }
00166 
00167   // Set up d with the default configuration parameters
00168   d->SetDefault(fDefaultConfig);
00169   d->SetCurrent(fConfig);
00170   
00171   // Do the querry
00172   Registry r = d->Query();
00173   Set(r);
00174 
00175   // Clean up the dialog
00176   if (deleteDialog) { delete d; d = 0; }
00177 }
00178 
00179 void CfgPromptConfigurable::Set(const char* key, char val)
00180 { Registry r;  r.Set(key,val); Set(r); }
00181 
00182 
00183 void CfgPromptConfigurable::Set(const char* key, const char* val)
00184 { Registry r;  r.Set(key,val); Set(r); }
00185 
00186 
00187 
00188 void CfgPromptConfigurable::Set(const char* key, double val)
00189 { Registry r;  r.Set(key,val); Set(r); }
00190 
00191 
00192 void CfgPromptConfigurable::Set(const char* key, int val)
00193 { Registry r;  r.Set(key,val); Set(r); }
00194 
00195 
00196 void CfgPromptConfigurable::Set(const char* key, const Registry& val )
00197 { Registry r;  r.Set(key,val); Set(r); }
00198 
00199 
00200 void CfgPromptConfigurable::Set(const char* setstring)
00201 { 
00202   // Parse a whole string.
00203   
00204   // First, look for spaces to seperate entries.
00205   Registry r;
00206   string a,b;
00207   string line = setstring;
00208   bool split;
00209   do {
00210     split = Split(line,' ',a,b);
00211     
00212     // a contains the possible code.
00213     string key, val;
00214     if(a.size()>0) {
00215       if(Split(a,'=',key,val)) {
00216         Int_t i;
00217         Double_t f;
00218         if(IsInt(val,i)) {
00219           r.Set(key.c_str(),i);
00220         } else if(IsFloat(val,f)) {
00221           r.Set(key.c_str(),f);
00222         } else {
00223           r.Set(key.c_str(),val.c_str());
00224         };
00225         
00226         
00227       } else {
00228         MSG("Configurable",Msg::kWarning) << "Can't parse fragment: " << a << endl;
00229       }
00230     }
00231     
00232     line = b;
00233   } while ( split );
00234 
00235   // Add the data.
00236   Set(r);
00237 }
00238 
00239 
00240 // Granddaddy of set() routines:
00241 void CfgPromptConfigurable::Set(const Registry& stuff, Bool_t recursive)
00242 {
00243   if(SafeMerge(fConfig,stuff,recursive)) {
00244     // Something got changed, so allow user to change stuff:
00245     ConfigModified();
00246     fConfig.SetDirty(false);
00247   }
00248 }
00249 
00250 Bool_t CfgPromptConfigurable::SafeMerge(Registry& modify, 
00251                                      const Registry& stuff,
00252                                      Bool_t recursive )
00253 {
00258 
00259   // First, see if we're locked up too tight to set anything.
00260   if(modify.ValuesLocked()) {
00261     MSG("Configurable",Msg::kWarning) << "Configurable has values locked. Can't set:" << endl;
00262     MSG("Configurable",Msg::kWarning) << stuff << endl;
00263     return false;
00264   }
00265 
00266   
00267   bool modified = false;
00268   
00269   // Iterate through all the keys in stuff.
00270   Registry::RegistryKey keyitr = stuff.Key();
00271   const char* key;
00272   while( (key = keyitr()) ) {
00273                                                 
00274     // Does modify have this key?
00275     if(!modify.KeyExists(key)) {
00276       // Key doesn't exist. 
00277 
00278       if(modify.KeysLocked()) {
00279 
00280         // Keys are locked, so throw away with an error.
00281         MSG("Configurable",Msg::kWarning) << "Key " << key << " is not initialized in this Configurable. Skipping." << endl;
00282         MSG("Configurable",Msg::kInfo)    << "Current key/values are:" <<endl;
00283         if( MsgService::Instance()->IsActive("Configurable",Msg::kInfo) )
00284           modify.PrettyPrint(std::cout);
00285 
00286         MSG("Configurable",Msg::kFatal) << "\"" << key << "\" is an illegal key! Fix your script!" << endl;
00287         assert(0);
00288         continue;
00289 
00290       } else {
00291         // Key exists. Go on to save this one.
00292       }
00293 
00294     } else {
00295       // Key exists. 
00296 
00297       // Is the key the right type?
00298       if(modify.GetType(key)!=stuff.GetType(key)) {
00299         MSG("Configurable",Msg::kWarning) << "Key \"" << key << "\" is not initialized as type (" 
00300                                           << modify.GetType(key).name() 
00301                                           << ") but you've tried to set it to type (" 
00302                                           << stuff.GetType(key).name() 
00303                                           << ")" << endl;
00304         continue;
00305       }
00306       
00307       if( modify.GetValueAsString(key)==stuff.GetValueAsString(key) ) {
00308         // The values are identical. So save the work and skip it.
00309         continue;
00310       }
00311     }
00312 
00313     // Switch on type:
00314     int    vint;
00315     double vdouble;
00316     char   vchar;
00317     const char* vcharstar;
00318     Registry vregistry;
00319 
00320     const type_info& theType(modify.GetType(key));
00321 
00322     if((theType==typeid(char))&&(stuff.Get(key,vchar)))   modify.Set(key,vchar);
00323     if((theType==typeid(int))&&(stuff.Get(key,vint)))    modify.Set(key,vint);
00324     if((theType==typeid(double))&&(stuff.Get(key,vdouble))) modify.Set(key,vdouble);
00325     if((theType==typeid(const char*))&&(stuff.Get(key,vcharstar))) modify.Set(key,vcharstar);
00326     if(stuff.GetTypeAsString(key) == "Registry"){
00327       if(stuff.Get(key,vregistry)) {
00328         // Registries are harder. Merge using this function.
00329         if(recursive) {
00330 
00331           Registry old;
00332           if(modify.Get(key,old)) {
00333             Registry old;
00334             // Just for safety:
00335             old.UnLockValues();
00336             old.LockKeys();
00337             if(SafeMerge(old,vregistry)) modified = true;
00338             modify.Set(key,old);
00339           }
00340 
00341         } else {
00342           modify.Set(key,vregistry);
00343         }
00344       }
00345     }
00346 
00347     modified = true;
00348   };
00349 
00350   return modified;
00351 }
00352 

Generated on Mon Feb 15 11:06:31 2010 for loon by  doxygen 1.3.9.1