#include #include #include "TBuffer.h" #include "TObject.h" #include "IDbiRegistry.hxx" #include "IDbiRegistryItem.hxx" #include using namespace COMET::Util; #include #include using std::endl; #include #include #include #include using namespace std; ClassImp(COMET::IDbiRegistry) //...................................................................... COMET::IDbiRegistry::IDbiRegistry(bool readonly /* = true */) : fValuesLocked(readonly), fKeysLocked(false), fErrorHandler(0) { COMETTrace( "Creating IDbiRegistry at " << (void * ) this << " "); this->SetDirty(); } // Deep copy constructor COMET::IDbiRegistry::IDbiRegistry(const IDbiRegistry& rhs) : TNamed(rhs) { COMETTrace( "Creating IDbiRegistry at " << (void * ) this << " "); IDbiRegistryKey rk = rhs.Key(); const char* s; while ( (s = rk()) ) fMap[s] = rhs.fMap.find(s)->second->Dup(); fValuesLocked = rhs.fValuesLocked; fKeysLocked = rhs.fKeysLocked; this->SetDirty(); this->SetName(rhs.GetName()); } COMET::IDbiRegistry& COMET::IDbiRegistry::operator=(const IDbiRegistry& rhs) { if (this == &rhs) return *this; UnLockValues(); UnLockKeys(); // If we are already holding something - clear it. if (Size() != 0) Clear(); IDbiRegistryKey rk = rhs.Key(); const char* s; while ( (s = rk()) ) fMap[s] = rhs.fMap.find(s)->second->Dup(); fValuesLocked = rhs.fValuesLocked; fKeysLocked = rhs.fKeysLocked; this->SetDirty(); this->SetName(rhs.GetName()); // Do like copy ctor. return *this; } void COMET::IDbiRegistry::Merge(const IDbiRegistry& rhs) { if (this == &rhs) return; IDbiRegistryKey rk = rhs.Key(); const char* s; while ( (s = rk()) ) { tRegMap::iterator mit = fMap.find(s); bool exists = mit != fMap.end(); if (fKeysLocked && !exists) { COMETWarn( "Merge: can't, add new key " << s <<", keys locked." << " merger=" << this->GetName() << ", mergie=" << rhs.GetName() << " "); continue; } if (exists && fValuesLocked) { COMETWarn( "Merge: can't, merge key " << s <<", values locked." << " merger=" << this->GetName() << ", mergie=" << rhs.GetName() << " "); continue; } if (exists) delete mit->second; fMap[s] = rhs.fMap.find(s)->second->Dup(); } this->SetDirty(); } bool COMET::IDbiRegistry::KeyExists(const char* key) const { return fMap.find(key) != fMap.end(); } void COMET::IDbiRegistry::RemoveKey(const char* key) { tRegMap::iterator dead = fMap.find(key); if (dead == fMap.end()) return; fMap.erase(dead); delete dead->second; this->SetDirty(); } void COMET::IDbiRegistry::Clear(Option_t * /* option */) { if (fValuesLocked || fKeysLocked) { COMETWarn( "Clear: can't, there are locks in \"" << this->GetName() << "\"\n"); return; } tRegMap::iterator mit = fMap.begin(); while (mit != fMap.end()) { delete mit->second; ++mit; } fMap.clear(); this->SetDirty(); } void COMET::IDbiRegistry::Dump(void) const { this->TNamed::Dump(); tRegMap::const_iterator mit = fMap.begin(); COMETInfo( "IDbiRegistry: `" << this->GetName() << "', " << this->Size() << " entries." << " (Locks: [Keys|Values] `key', `value'):\n"); while (mit != fMap.end()) { COMETInfo( " [" << (fKeysLocked ? 'L' : 'U') << "|" << (fValuesLocked ? 'L' : 'U') << "] " << "`" << mit->first << "', `"); mit->second->Dump(); COMETInfo( "'\n"); ++mit; } } std::ostream& COMET::IDbiRegistry::PrettyPrint(std::ostream& os) const { static int print_depth = 0; // print (to cout) the registry tRegMap::const_iterator mit = this->fMap.begin(); for(int i=0; iGetName() << "\", " << this->Size() << " entries." << " keys " << (this->fKeysLocked ? "locked" : "unlocked") << ", values " << (this->fValuesLocked ? "locked" : "unlocked") << "\n"; print_depth+=4; while (mit != this->fMap.end()) { for(int i=0; ifirst << " = "; mit->second->PrintStream(os); os << endl; ++mit; } print_depth-=4; return os; } void COMET::IDbiRegistry::Print(Option_t* /* option */) const { this->PrettyPrint(cout); } COMET::IDbiRegistry::~IDbiRegistry() { tRegMap::iterator mit = fMap.begin(); while (mit != fMap.end()) { delete mit->second; ++mit; } } COMET::IDbiRegistry::IDbiRegistryKey::IDbiRegistryKey(const IDbiRegistry* r) : fReg(r) { // FIXME! Figure out how to correctly declare fIt to reflect // constness. fIt = const_cast(fReg)->fMap.begin(); } COMET::IDbiRegistry::IDbiRegistryKey::IDbiRegistryKey() { } COMET::IDbiRegistry::IDbiRegistryKey::~IDbiRegistryKey() { } const char* COMET::IDbiRegistry::IDbiRegistryKey::operator()(void) { if (fIt == fReg->fMap.end()) return 0; const char* s = fIt->first.c_str(); ++ fIt; return s; } COMET::IDbiRegistry::IDbiRegistryKey COMET::IDbiRegistry::Key(void) const { return COMET::IDbiRegistry::IDbiRegistryKey(this); } #define REGISTRY_SET(TYPE) \ bool COMET::IDbiRegistry::Set(const char* key, TYPE val) \ { \ tRegMap::iterator mit = fMap.find(key); \ if (mit != fMap.end()) { \ if (fValuesLocked) { \ COMETWarn( "Set: Values are locked - not overwriting \"" \ << key << "\" with \"" << val << "\" in registry \"" << this->GetName() << "\"\n");\ return false; \ } \ if (!dynamic_cast*>(mit->second)) { \ COMETWarn( "Set: attempt to overwrite old value for key \"" \ << key << "\" with different type value " \ << val << " in registry \"" << this->GetName() << "\"\n");\ return false; \ } \ delete mit->second; \ fMap.erase(mit); \ } \ else { \ if (fKeysLocked) { \ COMETWarn( "Set: Keys are locked - not adding `" \ << key << "' to registry \"" << this->GetName() << "\"\n");\ return false; \ } \ } \ IDbiRegistryItem* ri = new IDbiRegistryItemXxx< TYPE >(new TYPE (val)); \ fMap[key] = ri; \ this->SetDirty(); \ return true; \ } //REGISTRY_SET(bool) REGISTRY_SET(char) REGISTRY_SET(int) REGISTRY_SET(double) REGISTRY_SET(IDbiRegistry) #undef REGISTRY_SET // Must treat char* special bool COMET::IDbiRegistry::Set(const char* key, const char* val) { tRegMap::iterator mit = fMap.find(key); if (mit != fMap.end()) { // Found it if (fValuesLocked) { COMETWarn( "Set: Values are locked - not overwriting `" << key << "\" with \"" << val << "\" in registry \"" << this->GetName() << "\"\n"); return false; } if (! dynamic_cast*>(mit->second) ) { COMETWarn( "Set: attempt to overwrite old value for key \"" << key << "\" with different type value " << val << " in registry \"" << this->GetName() << "\"\n"); return false; } delete mit->second; fMap.erase(mit); } else { // didn't find it if (fKeysLocked) { COMETWarn( "COMET::IDbiRegistry::Set: Keys are locked - not adding `" << key << "' in registry \"" << this->GetName() << "\"\n"); return false; } } char** cpp = new char*; (*cpp) = new char [strlen(val)+1]; strcpy(*cpp,val); const char** ccpp = const_cast(cpp); IDbiRegistryItem* ri = new IDbiRegistryItemXxx< const char* >(ccpp); fMap[key] = ri; this->SetDirty(); return true; } #define REGISTRY_GET(TYPE) \ bool COMET::IDbiRegistry::Get(const char* key, TYPE & val) const \ { \ tRegMap::const_iterator mit = fMap.find(key); \ if (mit == fMap.end()) return false; \ IDbiRegistryItemXxx* rix = \ dynamic_cast*>(mit->second); \ if (rix == 0){ \ COMETSevere( "Key " << key \ << " does not have type " \ << #TYPE << " as required" \ << " "); \ return false; \ } \ val = *(rix->Get()); \ return true; \ } //REGISTRY_GET(bool) REGISTRY_GET(char) REGISTRY_GET(IDbiRegistry) REGISTRY_GET(const char*) REGISTRY_GET(int) //REGISTRY_GET(double) bool COMET::IDbiRegistry::Get(const char* key, double & val) const { tRegMap::const_iterator mit = fMap.find(key); if (mit == fMap.end()) return false; // try correct type IDbiRegistryItemXxx* rixd = dynamic_cast*>(mit->second); if (rixd) { val = *(rixd->Get()); return true; } // try int IDbiRegistryItemXxx* rixi = dynamic_cast*>(mit->second); if (rixi) { val = *(rixi->Get()); return true; } COMETSevere( "Key " << key << " does not have type double or int" << " as required" << " "); return false; } #define REGISTRY_GET_TYPE(NAME, RETTYPE, TYPE) \ RETTYPE COMET::IDbiRegistry::Get##NAME(const char* key) const \ { \ TYPE retval = 0; \ if (Get(key,retval)) return retval; \ if (fErrorHandler) { fErrorHandler(); return 0; } \ else { \ COMETWarn( "\nCOMET::IDbiRegistry::GetTYPE: failed to get value for key \"" \ << key << "\" from IDbiRegistry \"" << this->GetName() \ << "\". Aborting\n\n"); \ bool must_get_a_value = false; \ assert(must_get_a_value); \ return 0; \ } \ } //REGISTRY_GET_TYPE(Bool, bool, bool) REGISTRY_GET_TYPE(Char, char, char) REGISTRY_GET_TYPE(CharString, const char*, const char*) REGISTRY_GET_TYPE(Int, int, int) REGISTRY_GET_TYPE(Double, double, double) //REGISTRY_GET_TYPE(IDbiRegistry, IDbiRegistry, IDbiRegistry) #undef REGISTRY_GET_TYPE COMET::IDbiRegistry COMET::IDbiRegistry::GetTDbiRegistry(const char* key) const { IDbiRegistry retval; if (Get(key,retval)) return retval; if (fErrorHandler) { fErrorHandler(); return retval; } else { COMETWarn( "\nCOMET::IDbiRegistry::GetTYPE: failed to get value for key \"" << key << "\" from IDbiRegistry \"" << this->GetName() << "\". Aborting\n\n"); bool must_get_a_value = false; assert(must_get_a_value); return retval; } } const std::type_info& COMET::IDbiRegistry::GetType(const char* key) const { tRegMap::const_iterator mit = fMap.find(key); if (mit == fMap.end()) return typeid(void); return mit->second->GetType(); } string COMET::IDbiRegistry::GetTypeAsString(const char* key) const { tRegMap::const_iterator mit = fMap.find(key); if (mit == fMap.end()) return "void"; return mit->second->GetTypeAsString(); } string COMET::IDbiRegistry::GetValueAsString(const char* key) const { ostringstream os; tRegMap::const_iterator mit = fMap.find(key); if (mit == fMap.end()) return ""; mit->second->PrintStream(os); return os.str(); } void COMET::IDbiRegistry::Streamer(TBuffer& b) { int nobjects; if (b.IsReading()) { Version_t v = b.ReadVersion(); if (v) {} TNamed::Streamer(b); b >> nobjects; for (int i = 0; i < nobjects; ++i) { char tmp[1024]; b >> tmp; string key(tmp); IDbiRegistryItem *ri; b >> ri; // This is copied from Set(), bad programmer! tRegMap::iterator mit = fMap.find(key); if (mit != fMap.end()) { delete mit->second; fMap.erase(mit); } fMap[key] = ri; } // end reading in all TDbiRegistryItems } // isReading else { b.WriteVersion(COMET::IDbiRegistry::IsA()); TNamed::Streamer(b); nobjects = fMap.size(); b << nobjects; COMETDebug( "Streamer, Writing "<< nobjects <<" objects\n"); tRegMap::iterator mit = fMap.begin(); while (mit != fMap.end()) { b << mit->first.c_str(); COMETDebug( mit->first.c_str() << " "); b << mit->second; ++mit; } } } std::ostream& COMET::IDbiRegistry::PrintStream(std::ostream& os) const { os << "['" << this->GetName() << "'"; tRegMap::const_iterator mit, done = fMap.end(); for (mit = fMap.begin(); mit != done; ++mit) { os << " '" << mit->first << "'=("; os << mit->second->GetTypeAsString(); os << ")"; mit->second->PrintStream(os); } os << "]"; return os; } static std::istream& bail(std::istream& is) { COMETWarn( "COMET::IDbiRegistry::Read(istream&) stream corrupted\n"); return is; } std::istream& COMET::IDbiRegistry::ReadStream(std::istream& is) { IDbiRegistry reg; char c; if (!is.get(c)) return bail(is); if (c != '[') { is.putback(c); return bail(is); } string name = Util::read_quoted_string(is); reg.SetName(name.c_str()); while (is.get(c)) { if (isspace(c)) continue; if (c == ']') { *this = reg; return is; } is.putback(c); // get the key string key = read_quoted_string(is); if (key == "") return bail(is); // skip the "=" if (!is.get(c)) return bail(is); // get the "(" if (!is.get(c) || c != '(') { is.putback(c); return bail(is); } // get the type string type; while (is.get(c)) { if (c == ')') break; type += c; } // factory: IDbiRegistryItem* ri = 0; if (type == "char") ri = new IDbiRegistryItemXxx(); else if (type == "int") ri = new IDbiRegistryItemXxx(); else if (type == "double") ri = new IDbiRegistryItemXxx(); else if (type == "string") ri = new IDbiRegistryItemXxx(); else if (type == "IDbiRegistry") ri = new IDbiRegistryItemXxx(); else return bail(is); ri->ReadStream(is); reg.fMap[key] = ri; } return is; }