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 /* = true */)
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 // Deep copy constructor
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     // If we are already holding something - clear it.
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     // Do like copy ctor.
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 * /* option */)
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     // print (to cout) the registry
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* /* option */) 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     // FIXME!  Figure out how to correctly declare fIt to reflect
00199     // constness.
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 //REGISTRY_SET(bool)
00256 REGISTRY_SET(char)
00257 REGISTRY_SET(int)
00258 REGISTRY_SET(double)
00259 REGISTRY_SET(TDbiRegistry)
00260 #undef REGISTRY_SET
00261 
00262 
00263 // Must treat char* special
00264 bool TDbiRegistry::Set(const char* key, const char* val)
00265 {
00266     tRegMap::iterator mit = fMap.find(key);
00267     if (mit != fMap.end()) {    // Found it
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 {                      // didn't find it
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 //REGISTRY_GET(bool)
00319 REGISTRY_GET(char)
00320 REGISTRY_GET(TDbiRegistry)
00321 REGISTRY_GET(const char*)
00322 REGISTRY_GET(int)
00323 //REGISTRY_GET(double)
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     // try correct type
00329     TDbiRegistryItemXxx<double>* rixd =
00330         dynamic_cast<TDbiRegistryItemXxx<double>*>(mit->second);
00331     if (rixd) {
00332         val = *(rixd->Get());
00333         return true;
00334     }
00335     // try int
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 //REGISTRY_GET_TYPE(Bool, bool, bool)
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 //REGISTRY_GET_TYPE(TDbiRegistry, TDbiRegistry, TDbiRegistry)
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             // This is copied from Set(), bad programmer!
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         } // end reading in all TDbiRegistryItems
00437     } // isReading
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         // get the key
00506         string key = read_quoted_string(is);
00507         if (key == "") return bail(is);
00508 
00509         // skip the "="
00510         if (!is.get(c)) return bail(is);
00511 
00512         // get the "("
00513         if (!is.get(c) || c != '(') {
00514             is.putback(c);
00515             return bail(is);
00516         }
00517 
00518         // get the type
00519         string type;
00520         while (is.get(c)) {
00521             if (c == ')') break;
00522             type += c;
00523         }
00524 
00525         // factory:
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 

Generated on 11 Aug 2013 for SKDatabase by  doxygen 1.6.1