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