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.48 2006/10/23 16:13:14 bv 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) return false;                                 \
00319     val = *(rix->Get());                                        \
00320     return true;                                                \
00321 }
00322 //REGISTRY_GET(bool)
00323 REGISTRY_GET(char)
00324 REGISTRY_GET(Registry)
00325 REGISTRY_GET(const char*)
00326 REGISTRY_GET(int)
00327 //REGISTRY_GET(double)
00328 bool Registry::Get(const char* key, double & val) const           
00329 {                                                               
00330     tRegMap::const_iterator mit = fMap.find(key);
00331     if (mit == fMap.end()) return false;
00332     // try correct type
00333     RegistryItemXxx<double>* rixd =
00334         dynamic_cast<RegistryItemXxx<double>*>(mit->second);
00335     if (rixd) {
00336         val = *(rixd->Get());
00337         return true;
00338     }
00339     // try int
00340     RegistryItemXxx<int>* rixi =
00341         dynamic_cast<RegistryItemXxx<int>*>(mit->second);
00342     if (rixi) {
00343         val = *(rixi->Get());
00344         return true;
00345     }
00346     return false;
00347 }
00348 
00349 #define REGISTRY_GET_TYPE(NAME, RETTYPE, TYPE)                            \
00350 RETTYPE Registry::Get##NAME(const char* key) const                        \
00351 {                                                                         \
00352     TYPE retval = 0;                                                      \
00353     if (Get(key,retval)) return retval;                                   \
00354     if (fErrorHandler) { fErrorHandler(); return 0; }                     \
00355     else {                                                                \
00356         MSG("Registry",Msg::kWarning)                                     \
00357             << "\nRegistry::GetTYPE: failed to get value for key \""      \
00358             << key << "\" from Registry \"" << this->GetName()            \
00359             << "\".  Aborting\n\n";                                       \
00360         bool must_get_a_value = false;                                    \
00361         assert(must_get_a_value);                                         \
00362         return 0;                                                         \
00363     }                                                                     \
00364 }
00365 
00366 //REGISTRY_GET_TYPE(Bool, bool, bool)
00367 REGISTRY_GET_TYPE(Char, char, char)
00368 REGISTRY_GET_TYPE(CharString, const char*, const char*)
00369 REGISTRY_GET_TYPE(Int, int, int)
00370 REGISTRY_GET_TYPE(Double, double, double)
00371 //REGISTRY_GET_TYPE(Registry, Registry, Registry)
00372 #undef REGISTRY_GET_TYPE
00373 Registry Registry::GetRegistry(const char* key) const
00374 {
00375     Registry retval;
00376     if (Get(key,retval)) return retval;
00377     if (fErrorHandler) { fErrorHandler(); return retval; }
00378     else {
00379         MSG("Registry",Msg::kWarning)
00380             << "\nRegistry::GetTYPE: failed to get value for key \""
00381             << key << "\" from Registry \"" << this->GetName()
00382             << "\".  Aborting\n\n";
00383         bool must_get_a_value = false;
00384         assert(must_get_a_value);
00385         return retval;
00386     }
00387 }
00388 
00389 const type_info& Registry::GetType(const char* key) const
00390 {
00391     tRegMap::const_iterator mit = fMap.find(key);
00392     if (mit == fMap.end()) return typeid(void);
00393     return mit->second->GetType();
00394 }
00395 string Registry::GetTypeAsString(const char* key) const
00396 {
00397     tRegMap::const_iterator mit = fMap.find(key);
00398     if (mit == fMap.end()) return "void";
00399     return mit->second->GetTypeAsString();
00400 }
00401 
00402 string Registry::GetValueAsString(const char* key) const
00403 {
00404     ostringstream os;
00405     tRegMap::const_iterator mit = fMap.find(key);
00406     if (mit == fMap.end()) return "";
00407     mit->second->PrintStream(os);
00408     return os.str();
00409 }
00410 
00411 void Registry::Streamer(TBuffer& b)
00412 {
00413     int nobjects;
00414 
00415     if (b.IsReading()) {
00416         Version_t v = b.ReadVersion();
00417         if (v) {}
00418         TNamed::Streamer(b);
00419 
00420         b >> nobjects;
00421 
00422         for (int i = 0; i < nobjects; ++i) {
00423 
00424             char tmp[1024];
00425             b >> tmp;
00426             string key(tmp);
00427 
00428             RegistryItem *ri;
00429             b >> ri;
00430 
00431             // This is copied from Set(), bad programmer!
00432             tRegMap::iterator mit = fMap.find(key);
00433             if (mit != fMap.end()) {
00434                 delete mit->second;
00435                 fMap.erase(mit);
00436             }
00437             fMap[key] = ri;
00438 
00439         } // end reading in all RegistryItems
00440     } // isReading
00441     else {
00442         b.WriteVersion(Registry::IsA());
00443         TNamed::Streamer(b);
00444 
00445         nobjects = fMap.size();
00446         b << nobjects;
00447 
00448         MSG("Registry",Msg::kDebug) 
00449             << "Streamer, Writing "<< nobjects <<" objects\n";
00450 
00451         tRegMap::iterator mit = fMap.begin();
00452         while (mit != fMap.end()) {
00453             b << mit->first.c_str();
00454 
00455             MSG("Registry",Msg::kDebug) 
00456                 << mit->first.c_str() << endl;
00457 
00458             b << mit->second;
00459 
00460             ++mit;
00461         }
00462     }
00463 }
00464 
00465 
00466 std::ostream& Registry::PrintStream(std::ostream& os) const
00467 {
00468     os << "['" << this->GetName() << "'";
00469     
00470     tRegMap::const_iterator mit, done = fMap.end();
00471     for (mit = fMap.begin(); mit != done; ++mit) {
00472         os << " '" << mit->first << "'=(";
00473         os << mit->second->GetTypeAsString();
00474         os << ")";
00475         mit->second->PrintStream(os);
00476     }
00477 
00478     os << "]";
00479     return os;
00480 }
00481 
00482 
00483 static std::istream& bail(std::istream& is)
00484 {
00485     MSG("Registry",Msg::kWarning)
00486         << "Registry::Read(istream&) stream corrupted\n";
00487     return is;
00488 }
00489 
00490 std::istream& Registry::ReadStream(std::istream& is) 
00491 {
00492     Registry reg;
00493 
00494     char c;
00495     if (!is.get(c)) return bail(is);
00496     if (c != '[') {
00497         is.putback(c);
00498         return bail(is);
00499     }
00500     string name = Util::read_quoted_string(is);
00501     reg.SetName(name.c_str());
00502 
00503     while (is.get(c)) {
00504         if (isspace(c)) continue;
00505         if (c == ']') {
00506             *this = reg;
00507             return is;
00508         }
00509         is.putback(c);
00510 
00511         // get the key
00512         string key = read_quoted_string(is);
00513         if (key == "") return bail(is);
00514 
00515         // skip the "="
00516         if (!is.get(c)) return bail(is);
00517 
00518         // get the "("
00519         if (!is.get(c) || c != '(') {
00520             is.putback(c);
00521             return bail(is);
00522         }
00523         
00524         // get the type
00525         string type;
00526         while (is.get(c)) {
00527             if (c == ')') break;
00528             type += c;
00529         }
00530         
00531         // factory:
00532         RegistryItem* ri = 0;
00533         if (type == "char") 
00534             ri = new RegistryItemXxx<char>();
00535         else if (type == "int")
00536             ri = new RegistryItemXxx<int>();
00537         else if (type == "double")
00538             ri = new RegistryItemXxx<double>();
00539         else if (type == "string")
00540             ri = new RegistryItemXxx<const char*>();
00541         else if (type == "Registry")
00542             ri = new RegistryItemXxx<Registry>();
00543         else return bail(is);
00544 
00545         ri->ReadStream(is);
00546         reg.fMap[key] = ri;
00547     }
00548     return is;
00549   
00550 }

Generated on Mon Jun 16 14:58:29 2008 for loon by  doxygen 1.3.9.1