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

Registry.cxx

Go to the documentation of this file.
00001 #include <map>
00002 #include <iomanip>
00003 
00004 #include "TBuffer.h"
00005 #include "TObject.h"
00006 
00007 #include "Registry.h"
00008 #include "RegistryItem.h"
00009 
00010 #include <Util/UtilStream.h>
00011 using namespace Util;
00012 
00013 #include <MessageService/MsgService.h>
00014 CVSID("$Id: Registry.cxx,v 1.51 2008/09/25 13:06:57 bckhouse Exp $");
00015 
00016 #include <typeinfo>
00017 #include <iostream>
00018 #include <sstream>
00019 #include <cassert>
00020 using namespace std;
00021 
00022 ClassImp(Registry)
00023 
00024 
00025 
00026 //......................................................................
00027 
00028 Registry::Registry(bool readonly /* = true */) 
00029     : fValuesLocked(readonly), 
00030       fKeysLocked(false),
00031       fErrorHandler(0)
00032 {
00033     MSG("Registry",Msg::kVerbose) << "Creating Registry at " << (void * ) this << endl;
00034     this->SetDirty();
00035 }
00036 
00037 // Deep copy constructor
00038 Registry::Registry(const Registry& rhs) : TNamed(rhs)
00039 {
00040     MSG("Registry",Msg::kVerbose) << "Creating Registry at " << (void * ) this << endl;
00041     RegistryKey rk = rhs.Key();
00042     const char* s;
00043 
00044     while ( (s = rk()) ) fMap[s] = rhs.fMap.find(s)->second->Dup();
00045 
00046     fValuesLocked = rhs.fValuesLocked;
00047     fKeysLocked   = rhs.fKeysLocked;
00048     this->SetDirty();
00049     this->SetName(rhs.GetName());
00050 }
00051 
00052 Registry& Registry::operator=(const Registry& rhs)
00053 {
00054     if (this == &rhs) return *this;
00055 
00056     UnLockValues();
00057     UnLockKeys();
00058 
00059     // If we are already holding something - clear it.
00060     if (Size() != 0) Clear();
00061 
00062     RegistryKey rk = rhs.Key();
00063     const char* s;
00064 
00065     while ( (s = rk()) ) fMap[s] = rhs.fMap.find(s)->second->Dup();
00066 
00067     fValuesLocked = rhs.fValuesLocked;
00068     fKeysLocked   = rhs.fKeysLocked;
00069     this->SetDirty();
00070     this->SetName(rhs.GetName());
00071     
00072     // Do like copy ctor.
00073     return *this;
00074 }
00075 
00076 void Registry::Merge(const Registry& rhs)
00077 {
00078     if (this == &rhs) return;
00079 
00080     RegistryKey rk = rhs.Key();
00081     const char* s;
00082     while ( (s = rk()) ) {
00083         tRegMap::iterator mit = fMap.find(s);
00084         bool exists = mit != fMap.end();
00085         
00086         if (fKeysLocked && !exists) {
00087             MSG("Registry",Msg::kWarning) 
00088                 << "Merge: can't, add new key " << s <<", keys locked."
00089                 << "  merger=" << this->GetName() 
00090                 << ", mergie=" << rhs.GetName() << endl;
00091             continue;
00092         }        
00093         if (exists && fValuesLocked) {
00094             MSG("Registry",Msg::kWarning) 
00095                 << "Merge: can't, merge key " << s <<", values locked."
00096                 << "  merger=" << this->GetName() 
00097                 << ", mergie=" << rhs.GetName() << endl;
00098             continue;
00099         }
00100         if (exists) delete mit->second;
00101         fMap[s] = rhs.fMap.find(s)->second->Dup();
00102     }
00103     this->SetDirty();
00104 }
00105 
00106 bool Registry::KeyExists(const char* key) const
00107 {
00108     return fMap.find(key) != fMap.end();
00109 }
00110 
00111 void Registry::RemoveKey(const char* key)
00112 {
00113     tRegMap::iterator dead = fMap.find(key);
00114     if (dead == fMap.end()) return;
00115     fMap.erase(dead);
00116     delete dead->second;
00117     this->SetDirty();
00118 }
00119 
00120 void Registry::Clear(Option_t * /* option */)
00121 {
00122     if (fValuesLocked || fKeysLocked) {
00123         MSG("Registry",Msg::kWarning) 
00124             << "Clear: can't, there are locks in \""
00125             << this->GetName() << "\"\n";
00126         return;
00127     }
00128 
00129     tRegMap::iterator mit = fMap.begin();
00130     while (mit != fMap.end()) {
00131         delete mit->second;
00132         ++mit;
00133     }
00134     fMap.clear();
00135     this->SetDirty();
00136 }
00137 
00138 void Registry::Dump(void) const
00139 {
00140     this->TNamed::Dump();
00141     tRegMap::const_iterator mit = fMap.begin();
00142     MSG("Registry",Msg::kInfo) 
00143         << "Registry: `" << this->GetName() << "', "
00144         << this->Size() << " entries."
00145         << " (Locks: [Keys|Values] `key', `value'):\n";
00146     while (mit != fMap.end()) {
00147         MSG("Registry",Msg::kInfo) 
00148             << " [" << (fKeysLocked ? 'L' : 'U') << "|"
00149             << (fValuesLocked ? 'L' : 'U') << "] "
00150             << "`" << mit->first << "', `";
00151         mit->second->Dump();
00152         MSG("Registry",Msg::kInfo) << "'\n";
00153         ++mit;
00154     }
00155 
00156 }
00157 
00158 ostream& Registry::PrettyPrint(ostream& os) const
00159 {
00160     static int print_depth = 0;
00161 
00162     // print (to cout) the registry
00163     tRegMap::const_iterator mit = this->fMap.begin();
00164     for(int i=0; i<print_depth; ++i) os << " ";
00165     os << "\"" << this->GetName() << "\", "
00166        << this->Size() << " entries." 
00167        << " keys " << (this->fKeysLocked ? "locked" : "unlocked") 
00168        << ", values " << (this->fValuesLocked ? "locked" : "unlocked")
00169        << "\n";
00170 
00171     print_depth+=4;
00172     while (mit != this->fMap.end()) {
00173         for(int i=0; i<print_depth; ++i) os << " ";
00174 
00175         os << mit->first << " = ";
00176         mit->second->PrintStream(os);
00177         os << endl;
00178         ++mit;
00179     }
00180     print_depth-=4;
00181     return os;
00182 }
00183 
00184 void Registry::Print(Option_t* /* option */) const
00185 {
00186     this->PrettyPrint(cout);
00187 }
00188 
00189 
00190 Registry::~Registry() 
00191 {
00192     tRegMap::iterator mit = fMap.begin();
00193     while (mit != fMap.end()) {
00194         delete mit->second;
00195         ++mit;
00196     }
00197 }
00198 
00199 Registry::RegistryKey::RegistryKey(const Registry* r) :
00200     fReg(r)
00201 {
00202     // FIXME!  Figure out how to correctly declare fIt to reflect
00203     // constness.
00204     fIt = const_cast<Registry*>(fReg)->fMap.begin();
00205 }
00206 
00207 Registry::RegistryKey::RegistryKey()
00208 {
00209 }
00210 
00211 Registry::RegistryKey::~RegistryKey()
00212 {
00213 }
00214 
00215 const char* Registry::RegistryKey::operator()(void)
00216 {
00217     if (fIt == fReg->fMap.end()) return 0;
00218     const char* s = fIt->first.c_str();
00219     ++ fIt;
00220     return s;
00221 }
00222 
00223 Registry::RegistryKey Registry::Key(void) const
00224 {
00225     return RegistryKey(this);
00226 }
00227 
00228 #define REGISTRY_SET(TYPE)                                              \
00229 bool Registry::Set(const char* key, TYPE val)                           \
00230 {                                                                       \
00231     tRegMap::iterator mit = fMap.find(key);                             \
00232     if (mit != fMap.end()) {                                            \
00233         if (fValuesLocked) {                                            \
00234              MSG("Registry",Msg::kWarning)                              \
00235                << "Set: Values are locked - not overwriting \""         \
00236                << key << "\" with \"" << val << "\" in registry \"" << this->GetName() << "\"\n";\
00237             return false;                                               \
00238         }                                                               \
00239         if (!dynamic_cast<RegistryItemXxx<TYPE>*>(mit->second)) {       \
00240             MSG("Registry",Msg::kWarning)                               \
00241                 << "Set: attempt to overwrite old value for key \""     \
00242                 << key << "\" with different type value "               \
00243                 << val << " in registry \"" << this->GetName() << "\"\n";\
00244             return false;                                               \
00245         }                                                               \
00246         delete mit->second;                                             \
00247         fMap.erase(mit);                                                \
00248     }                                                                   \
00249     else {                                                              \
00250         if (fKeysLocked) {                                              \
00251             MSG("Registry",Msg::kWarning)                               \
00252                  << "Set: Keys are locked - not adding `"               \
00253                  << key << "' to registry \"" << this->GetName() << "\"\n";\
00254             return false;                                               \
00255         }                                                               \
00256     }                                                                   \
00257     RegistryItem* ri = new RegistryItemXxx< TYPE >(new TYPE (val));     \
00258     fMap[key] = ri;                                                     \
00259     this->SetDirty();                                                   \
00260     return true;                                                        \
00261 }
00262 //REGISTRY_SET(bool)
00263 REGISTRY_SET(char)
00264 REGISTRY_SET(int)
00265 REGISTRY_SET(double)
00266 REGISTRY_SET(Registry)
00267 #undef REGISTRY_SET
00268 
00269 
00270 // Must treat char* special
00271 bool Registry::Set(const char* key, const char* val)
00272 {
00273     tRegMap::iterator mit = fMap.find(key);
00274     if (mit != fMap.end()) {    // Found it
00275         if (fValuesLocked) {
00276             MSG("Registry",Msg::kWarning) 
00277                 << "Set: Values are locked - not overwriting `"
00278                 << key << "\" with \"" << val << "\" in registry \"" << this->GetName() << "\"\n";
00279             return false;
00280         }
00281         if (! dynamic_cast<RegistryItemXxx<const char*>*>(mit->second) ) {
00282             MSG("Registry",Msg::kWarning)
00283                 << "Set: attempt to overwrite old value for key \""
00284                 << key << "\" with different type value "
00285                 << val << " in registry \"" << this->GetName() << "\"\n";
00286             return false;
00287         }
00288         delete mit->second;
00289         fMap.erase(mit);
00290     }
00291     else {                      // didn't find it
00292         if (fKeysLocked) {
00293             MSG("Registry",Msg::kWarning) 
00294                 << "Registry::Set: Keys are locked - not adding `" 
00295                 << key << "' in registry \"" << this->GetName() << "\"\n";
00296             return false;
00297         }
00298     }
00299 
00300     char** cpp = new char*;
00301     (*cpp) = new char [strlen(val)+1];
00302     strcpy(*cpp,val);
00303     const char** ccpp = const_cast<const char**>(cpp);
00304     RegistryItem* ri = new RegistryItemXxx< const char* >(ccpp);
00305     fMap[key] = ri;
00306     this->SetDirty();
00307     return true;
00308 }
00309 
00310 
00311 #define REGISTRY_GET(TYPE)                                      \
00312 bool Registry::Get(const char* key, TYPE & val) const           \
00313 {                                                               \
00314     tRegMap::const_iterator mit = fMap.find(key);               \
00315     if (mit == fMap.end()) return false;                        \
00316     RegistryItemXxx<TYPE>* rix =                                \
00317         dynamic_cast<RegistryItemXxx<TYPE>*>(mit->second);      \
00318     if (rix == 0){                                              \
00319       MSG("Registry", Msg::kError) << "Key " << key             \
00320                                    << " does not have type "    \
00321                                    << #TYPE << " as required"   \
00322                                    << endl;                     \
00323       return false;                                             \
00324     }                                                           \
00325     val = *(rix->Get());                                        \
00326     return true;                                                \
00327 }
00328 //REGISTRY_GET(bool)
00329 REGISTRY_GET(char)
00330 REGISTRY_GET(Registry)
00331 REGISTRY_GET(const char*)
00332 REGISTRY_GET(int)
00333 //REGISTRY_GET(double)
00334 bool Registry::Get(const char* key, double & val) const           
00335 {                                                               
00336     tRegMap::const_iterator mit = fMap.find(key);
00337     if (mit == fMap.end()) return false;
00338     // try correct type
00339     RegistryItemXxx<double>* rixd =
00340         dynamic_cast<RegistryItemXxx<double>*>(mit->second);
00341     if (rixd) {
00342         val = *(rixd->Get());
00343         return true;
00344     }
00345     // try int
00346     RegistryItemXxx<int>* rixi =
00347         dynamic_cast<RegistryItemXxx<int>*>(mit->second);
00348     if (rixi) {
00349         val = *(rixi->Get());
00350         return true;
00351     }
00352     MSG("Registry", Msg::kError) << "Key " << key
00353                                  << " does not have type double or int"
00354                                  << " as required" << endl;
00355     return false;
00356 }
00357 
00358 #define REGISTRY_GET_TYPE(NAME, RETTYPE, TYPE)                            \
00359 RETTYPE Registry::Get##NAME(const char* key) const                        \
00360 {                                                                         \
00361     TYPE retval = 0;                                                      \
00362     if (Get(key,retval)) return retval;                                   \
00363     if (fErrorHandler) { fErrorHandler(); return 0; }                     \
00364     else {                                                                \
00365         MSG("Registry",Msg::kWarning)                                     \
00366             << "\nRegistry::GetTYPE: failed to get value for key \""      \
00367             << key << "\" from Registry \"" << this->GetName()            \
00368             << "\".  Aborting\n\n";                                       \
00369         bool must_get_a_value = false;                                    \
00370         assert(must_get_a_value);                                         \
00371         return 0;                                                         \
00372     }                                                                     \
00373 }
00374 
00375 //REGISTRY_GET_TYPE(Bool, bool, bool)
00376 REGISTRY_GET_TYPE(Char, char, char)
00377 REGISTRY_GET_TYPE(CharString, const char*, const char*)
00378 REGISTRY_GET_TYPE(Int, int, int)
00379 REGISTRY_GET_TYPE(Double, double, double)
00380 //REGISTRY_GET_TYPE(Registry, Registry, Registry)
00381 #undef REGISTRY_GET_TYPE
00382 Registry Registry::GetRegistry(const char* key) const
00383 {
00384     Registry retval;
00385     if (Get(key,retval)) return retval;
00386     if (fErrorHandler) { fErrorHandler(); return retval; }
00387     else {
00388         MSG("Registry",Msg::kWarning)
00389             << "\nRegistry::GetTYPE: failed to get value for key \""
00390             << key << "\" from Registry \"" << this->GetName()
00391             << "\".  Aborting\n\n";
00392         bool must_get_a_value = false;
00393         assert(must_get_a_value);
00394         return retval;
00395     }
00396 }
00397 
00398 const type_info& Registry::GetType(const char* key) const
00399 {
00400     tRegMap::const_iterator mit = fMap.find(key);
00401     if (mit == fMap.end()) return typeid(void);
00402     return mit->second->GetType();
00403 }
00404 string Registry::GetTypeAsString(const char* key) const
00405 {
00406     tRegMap::const_iterator mit = fMap.find(key);
00407     if (mit == fMap.end()) return "void";
00408     return mit->second->GetTypeAsString();
00409 }
00410 
00411 string Registry::GetValueAsString(const char* key) const
00412 {
00413     ostringstream os;
00414     tRegMap::const_iterator mit = fMap.find(key);
00415     if (mit == fMap.end()) return "";
00416     mit->second->PrintStream(os);
00417     return os.str();
00418 }
00419 
00420 void Registry::Streamer(TBuffer& b)
00421 {
00422     int nobjects;
00423 
00424     if (b.IsReading()) {
00425         Version_t v = b.ReadVersion();
00426         if (v) {}
00427         TNamed::Streamer(b);
00428 
00429         b >> nobjects;
00430 
00431         for (int i = 0; i < nobjects; ++i) {
00432 
00433             char tmp[1024];
00434             b >> tmp;
00435             string key(tmp);
00436 
00437             RegistryItem *ri;
00438             b >> ri;
00439 
00440             // This is copied from Set(), bad programmer!
00441             tRegMap::iterator mit = fMap.find(key);
00442             if (mit != fMap.end()) {
00443                 delete mit->second;
00444                 fMap.erase(mit);
00445             }
00446             fMap[key] = ri;
00447 
00448         } // end reading in all RegistryItems
00449     } // isReading
00450     else {
00451         b.WriteVersion(Registry::IsA());
00452         TNamed::Streamer(b);
00453 
00454         nobjects = fMap.size();
00455         b << nobjects;
00456 
00457         MSG("Registry",Msg::kDebug) 
00458             << "Streamer, Writing "<< nobjects <<" objects\n";
00459 
00460         tRegMap::iterator mit = fMap.begin();
00461         while (mit != fMap.end()) {
00462             b << mit->first.c_str();
00463 
00464             MSG("Registry",Msg::kDebug) 
00465                 << mit->first.c_str() << endl;
00466 
00467             b << mit->second;
00468 
00469             ++mit;
00470         }
00471     }
00472 }
00473 
00474 
00475 std::ostream& Registry::PrintStream(std::ostream& os) const
00476 {
00477     os << "['" << this->GetName() << "'";
00478     
00479     tRegMap::const_iterator mit, done = fMap.end();
00480     for (mit = fMap.begin(); mit != done; ++mit) {
00481         os << " '" << mit->first << "'=(";
00482         os << mit->second->GetTypeAsString();
00483         os << ")";
00484         mit->second->PrintStream(os);
00485     }
00486 
00487     os << "]";
00488     return os;
00489 }
00490 
00491 
00492 static std::istream& bail(std::istream& is)
00493 {
00494     MSG("Registry",Msg::kWarning)
00495         << "Registry::Read(istream&) stream corrupted\n";
00496     return is;
00497 }
00498 
00499 std::istream& Registry::ReadStream(std::istream& is) 
00500 {
00501     Registry reg;
00502 
00503     char c;
00504     if (!is.get(c)) return bail(is);
00505     if (c != '[') {
00506         is.putback(c);
00507         return bail(is);
00508     }
00509     string name = Util::read_quoted_string(is);
00510     reg.SetName(name.c_str());
00511 
00512     while (is.get(c)) {
00513         if (isspace(c)) continue;
00514         if (c == ']') {
00515             *this = reg;
00516             return is;
00517         }
00518         is.putback(c);
00519 
00520         // get the key
00521         string key = read_quoted_string(is);
00522         if (key == "") return bail(is);
00523 
00524         // skip the "="
00525         if (!is.get(c)) return bail(is);
00526 
00527         // get the "("
00528         if (!is.get(c) || c != '(') {
00529             is.putback(c);
00530             return bail(is);
00531         }
00532         
00533         // get the type
00534         string type;
00535         while (is.get(c)) {
00536             if (c == ')') break;
00537             type += c;
00538         }
00539         
00540         // factory:
00541         RegistryItem* ri = 0;
00542         if (type == "char") 
00543             ri = new RegistryItemXxx<char>();
00544         else if (type == "int")
00545             ri = new RegistryItemXxx<int>();
00546         else if (type == "double")
00547             ri = new RegistryItemXxx<double>();
00548         else if (type == "string")
00549             ri = new RegistryItemXxx<const char*>();
00550         else if (type == "Registry")
00551             ri = new RegistryItemXxx<Registry>();
00552         else return bail(is);
00553 
00554         ri->ReadStream(is);
00555         reg.fMap[key] = ri;
00556     }
00557     return is;
00558   
00559 }

Generated on Mon Feb 15 11:07:30 2010 for loon by  doxygen 1.3.9.1