Config.cpp

Go to the documentation of this file.
00001 
00002 #include "cafe/Config.hpp"
00003 
00004 #include "TEnv.h"
00005 #include "TOrdCollection.h"
00006 #include "TObjArray.h"
00007 #include "TString.h"
00008 #include "TObjString.h"
00009 #include "THashList.h"
00010 #include "TDirectory.h"
00011 #include "TSystem.h"
00012 
00013 #include <memory>
00014 #include <iostream>
00015 #include <set>
00016 #include <cstdlib>
00017 #include <cstring>
00018 #include <stdexcept>
00019 
00020 namespace cafe {
00021 
00023     std::set<std::string> Config::s_accessed;
00024 
00025     Config::Config(const std::string& name)
00026         : _name(name)
00027     {}
00028 
00029     Config::~Config()
00030     {}
00031 
00032     std::string Config::replace(TEnv *env, const std::string& input)
00033     {
00034         using namespace std;
00035         string result(input);
00036 
00037         string::size_type pos = result.find("%{");
00038         if(pos != string::npos) {
00039             string::size_type end = result.find('}', pos);
00040             if(end != string::npos && result.find('.', pos) < end) {
00041                 string newkey   = result.substr(pos + 2, end - pos - 2);
00042                 s_accessed.insert(newkey);
00043                 string newvalue = env->GetValue(newkey.c_str(), "");
00044                 if (newvalue == "") { 
00045                     throw std::runtime_error("No value for " + newkey + " defined in the config files."); 
00046                 }
00047                 result.replace(pos, end - pos + 1, newvalue);
00048 
00049                 // recursive replace if the new string doesn't point back to itself.
00050                 if ( newvalue.find(newkey) == string::npos ) {
00051                     result = replace(env, result);
00052                 }
00053             }
00054             pos = end;
00055         }
00056         return result;  
00057     }
00058 
00059     std::string Config::get(const std::string& key, const std::string& def)
00060     {
00061         return get(key, def.c_str());
00062     }
00063 
00064     
00065     std::string Config::get(const std::string& key, const char *def)
00066     {
00067         std::string full = _name + '.' + key;
00068         s_accessed.insert(full);
00069         return getEnv().GetValue(full.c_str(), def);
00070     }
00071 
00072     int Config::get(const std::string& key, int def)
00073     {
00074         std::string full = _name + '.' + key;
00075         s_accessed.insert(full);
00076         return getEnv().GetValue(full.c_str(), def);
00077     }
00078     
00079     double Config::get(const std::string& key, double def)
00080     {
00081         std::string full = _name + '.' + key;
00082         s_accessed.insert(full);
00083         return getEnv().GetValue(full.c_str(), def);        
00084     }
00085     
00086     bool Config::get(const std::string& key, bool def)
00087     {
00088         std::string full = _name + '.' + key;
00089         s_accessed.insert(full);
00090         return getEnv().GetValue(full.c_str(), def);
00091     }
00092 
00093     std::vector<std::string> Config::getVString(const std::string& key, const std::string& delim)
00094     {
00095         s_accessed.insert(_name + '.' + key);
00096 
00097         TString s(get(key, "").c_str());
00098         std::vector<std::string> result;
00099         TObjArray *tokens = s.Tokenize(delim.c_str());
00100         {
00101             TIter iter(tokens);
00102             while(TObject *p = iter.Next()) {
00103                 TObjString *item = (TObjString*)p;
00104                 result.push_back(item->GetString().Data());
00105             }
00106         }
00107         delete tokens;
00108         return result;
00109     }
00110 
00111     std::vector<float> Config::getVFloat(const std::string& key, const std::string& delim)
00112     {
00113         s_accessed.insert(_name + '.' + key);
00114         
00115         TString s(get(key, "").c_str());
00116         std::vector<float> result;
00117         TObjArray *tokens = s.Tokenize(delim.c_str());
00118         TIter iter(tokens);
00119         while(TObject *p = iter.Next()) {
00120             TObjString *item = (TObjString*)p;
00121             result.push_back(atof(item->GetString().Data()));
00122         }
00123         delete tokens;
00124         return result;
00125      }
00126 
00127      std::vector<int> Config::getVInt(const std::string& key, const std::string& delim)
00128      {
00129         s_accessed.insert(_name + '.' + key);
00130 
00131         TString s(get(key, "").c_str());
00132         std::vector<int> result;
00133         TObjArray *tokens = s.Tokenize(delim.c_str());
00134         TIter iter(tokens);
00135         while(TObject *p = iter.Next()) {
00136             TObjString *item = (TObjString*)p;
00137             result.push_back(strtol(item->GetString().Data(),0,0));
00138         }
00139         delete tokens;
00140         return result;
00141      }
00142 
00143     void Config::set(const std::string& key, const std::string& value)
00144     {
00145         getEnv().SetValue(key.c_str(), value.c_str());
00146     }
00147 
00148     void Config::dumpConfig(std::ostream& stream)
00149     {
00150       TIter next(getEnv().GetTable());
00151       TEnvRec *er;
00152       static const char *lc[] = { "Global", "User", "Local", "Changed" };
00153 
00154       stream << "cafe::Config: Dumping configuration settings" << std::endl;
00155       while ((er = (TEnvRec*) next()))
00156         stream << Form("%-25s: %-30s [%s]",
00157                        er->GetName(),er->GetValue(),lc[er->GetLevel()]) << std::endl;
00158       stream << "cafe::Config: End of configuration settings" << std::endl;
00159 
00160       return;
00161     }
00162 
00163     void Config::dumpConfig(TDirectory* const dir, std::string const name)
00164     {
00165       if (dir) {
00166         TObjArray array(getEnv().GetTable()->GetSize());
00167         array.SetOwner(kTRUE);
00168 
00169         TIter next(getEnv().GetTable());
00170         TEnvRec *er;
00171         static const char *lc[] = { "Global", "User", "Local", "Changed" };
00172 
00173         size_t index = 0;
00174         while ((er = (TEnvRec*) next())) {
00175           TObjString* str = new TObjString(Form("%-25s: %-30s [%s]",
00176                                                 er->GetName(),
00177                                                 er->GetValue(),
00178                                                 lc[er->GetLevel()]));
00179           array[index] = str;
00180           ++index;
00181         } // while
00182 
00183         dir->cd();
00184         array.Write(name.c_str(),TObject::kSingleKey);
00185         //      array.Write();
00186       }
00187 
00188       return;
00189     }
00190 
00191     namespace {
00192         std::auto_ptr<TEnv> _cleanup;
00193     }
00194     
00195     TEnv& Config::getEnv()
00196     {
00197         static TEnv *_env;
00198         
00199         if(_env == 0) {
00200             // Search order:
00201             //   $CAFE_CONFIG  (putenv() by main routine if set on command line !
00202             //   ./cafe.config
00203             //   $SRT_PRIVATE_CONTEXT/cafe.config
00204             //
00205             if(const char *filename = gSystem->Getenv("CAFE_CONFIG")) {
00206                 std::cout << "Reading configuration file: " << filename << std::endl;
00207 
00208                 // We can't default construct TEnv, instead we have to pass
00209                 // a string that we think nobody uses for a config file name.
00210                 _env = new TEnv("!@#$%^&");
00211                 _env->ReadFile(filename, kEnvLocal);
00212                 if(_env->GetTable()->GetSize() == 0) {
00213                     delete _env;
00214                     _env = 0;
00215                     throw std::runtime_error(std::string("Config: specified configfile not found: ") + filename);
00216                 }
00217             }
00218             
00219             if(_env == 0) {
00220                 _env = new TEnv("!@#$%^&");
00221                 _env->ReadFile("./cafe.config", kEnvLocal);
00222                 if(_env->GetTable()->GetSize() == 0) {
00223                     delete _env;
00224                     _env = 0;
00225                 }
00226             }
00227 
00228             if(_env == 0) {
00229                 std::string ctx;
00230                 if(const char *c = getenv("SRT_PRIVATE_CONTEXT")) {
00231                     ctx += c;
00232                 }
00233                 ctx += "./cafe.config";
00234                 _env = new TEnv("!@#$%^&");
00235                 _env->ReadFile(ctx.c_str(), kEnvLocal);
00236             }
00237 
00238             // now load all include files
00239 
00240             // the files we have already seen
00241             std::set<std::string> _files_included;
00242             
00243             bool add_more = false;
00244             do {
00245                 add_more = false;
00246                 TString s(_env->GetValue("cafe.Include", "")) ;
00247                 std::auto_ptr<TObjArray> includes(s.Tokenize(" ,\t"));
00248                 TIter iter(includes.get());
00249                 while(TObject *p = iter.Next()) {
00250                     std::string filename(((TObjString*)p)->GetString().Data());
00251                     if(_files_included.count(filename) > 0) continue;
00252                     if(gSystem->AccessPathName(filename.c_str(), kReadPermission)) {
00253                         throw std::runtime_error("Include file does not exist: " + filename);
00254                     }
00255                     std::cout << "Including configuration file: " << filename << std::endl;
00256                     _env->ReadFile((filename).c_str(), kEnvLocal);
00257                     _files_included.insert(filename);
00258                     add_more = true;
00259                 }
00260             } while(add_more);
00261 
00262             s_accessed.insert("cafe.Include");
00263             _cleanup = std::auto_ptr<TEnv>(_env);
00264 
00265         }
00266         return *_env;
00267     }
00268 
00269     void Config::resolve()
00270     {
00271         TEnv& env(getEnv());
00272         TIter next(env.GetTable());
00273         while(TEnvRec *rec = (TEnvRec *)next()) {
00274             const char *str = rec->GetValue();
00275             if(strstr(str, "%{")) {
00276                 std::string new_value = replace(&env, str);
00277                 env.SetValue(rec->GetName(), new_value.c_str());
00278             }
00279             // remove space in the end of the config parameter
00280             std::string st = rec->GetValue() ;
00281             if (st.rfind(" ") == st.size()-1) {
00282               std::string::size_type pos ;
00283               while((pos = st.rfind(" ")) == st.size()-1 && st.size() > 0) 
00284                 st.erase(pos) ;
00285               env.SetValue(rec->GetName(), st.c_str());
00286             }
00287         }
00288     }
00289 
00290     std::vector<std::string> Config::checkConfiguration()
00291     {
00292         std::set<std::string> processors;
00293         
00294         // Pass 1, find all Processor 'P'
00295         for(std::set<std::string>::iterator it = s_accessed.begin();
00296             it != s_accessed.end();
00297             ++it) {
00298             std::string::size_type dot = (*it).find('.');
00299             if(dot != std::string::npos) {
00300                 std::string processor_name = (*it).substr(0, dot);
00301                 processors.insert(processor_name);
00302                 
00303             } // else ignore anything without a '.'
00304         }
00305 
00306         // Pass 2, 
00307         std::vector<std::string> result;
00308 
00309         TIter next(getEnv().GetTable());
00310         while (TEnvRec *rec = (TEnvRec*) next()) {
00311             std::string name(rec->GetName());
00312             std::string::size_type dot = name.find('.');
00313             if(dot != std::string::npos) {
00314                 if(processors.find(name.substr(0, dot)) != processors.end()) {
00315                     if(s_accessed.find(name) == s_accessed.end()) {
00316                         result.push_back(name);
00317                     }
00318                 }
00319             }
00320         }
00321 
00322         return result;
00323     }
00324 
00325 
00326   std::vector<std::string> Config::variables(const std::string& name) 
00327   {
00328         
00329     std::vector<std::string> result;
00330     
00331     TIter next(getEnv().GetTable());
00332     while (TEnvRec *rec = (TEnvRec*) next()) {
00333       std::string pname(rec->GetName());
00334       std::string::size_type dot = pname.find('.');
00335       if(dot != std::string::npos &&
00336          name ==pname.substr(0, dot))
00337         result.push_back(pname.substr(dot+1));
00338     }                    
00339     return result ;
00340   }
00341 
00342 }
00343 

Generated on Thu Apr 3 04:14:22 2008 for CAF by doxygen 1.3.4