EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
FairRegistry.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file FairRegistry.cxx
1 #include <map>
2 #include <iomanip>
3 
4 #include "TBuffer.h"
5 #include "TObject.h"
6 
7 #include "FairRegistry.h"
8 #include "FairRegistryItem.h"
9 
10 #include <FairUtilStream.h>
11 
12 using namespace Util;
13 
14 
15 //#include <typeinfo>
16 #include <iostream>
17 #include <sstream>
18 #include <cassert>
19 
20 using namespace std;
21 
23 
24 
25 
26 //......................................................................
27 
28 FairRegistry::FairRegistry(bool readonly)
29  : TNamed(),
30  fValuesLocked(readonly),
31  fKeysLocked(false),
32  fErrorHandler(0),
33  fMap(),
34  fDirty(true)
35 {
36  this->SetDirty();
37 }
38 
39 // Deep copy constructor
41  : TNamed(rhs),
42  fValuesLocked(rhs.fValuesLocked),
43  fKeysLocked(rhs.fKeysLocked),
44  fErrorHandler(0),
45  fMap(),
46  fDirty(true)
47 {
48  FairRegistryKey rk = rhs.Key();
49  const char* s;
50 
51  while ( (s = rk()) ) { fMap[s] = rhs.fMap.find(s)->second->Dup(); }
52 
53  // fValuesLocked = rhs.fValuesLocked;
54  // fKeysLocked = rhs.fKeysLocked;
55  this->SetDirty();
56  this->SetName(rhs.GetName());
57 }
58 
60 {
61  if (this == &rhs) { return *this; }
62 
63  UnLockValues();
64  UnLockKeys();
65 
66  // If we are already holding something - clear it.
67  if (Size() != 0) { Clear(); }
68 
69  FairRegistryKey rk = rhs.Key();
70  const char* s;
71 
72  while ( (s = rk()) ) { fMap[s] = rhs.fMap.find(s)->second->Dup(); }
73 
76  this->SetDirty();
77  this->SetName(rhs.GetName());
78 
79  // Do like copy ctor.
80  return *this;
81 }
82 
84 {
85  if (this == &rhs) { return; }
86 
87  FairRegistryKey rk = rhs.Key();
88  const char* s;
89  while ( (s = rk()) ) {
90  tRegMap::iterator mit = fMap.find(s);
91  bool exists = mit != fMap.end();
92 
93  if (fKeysLocked && !exists) {
94 
95  cout << "Merge: can't, add new key " << s <<", keys locked."
96  << " merger=" << this->GetName()
97  << ", mergie=" << rhs.GetName() << endl;
98  continue;
99  }
100  if (exists && fValuesLocked) {
101 
102  cout<< "Merge: can't, merge key " << s <<", values locked."
103  << " merger=" << this->GetName()
104  << ", mergie=" << rhs.GetName() << endl;
105  continue;
106  }
107  if (exists) { delete mit->second; }
108  fMap[s] = rhs.fMap.find(s)->second->Dup();
109  }
110  this->SetDirty();
111 }
112 
113 bool FairRegistry::KeyExists(const char* key) const
114 {
115  return fMap.find(key) != fMap.end();
116 }
117 
118 void FairRegistry::RemoveKey(const char* key)
119 {
120  tRegMap::iterator dead = fMap.find(key);
121  if (dead == fMap.end()) { return; }
122  fMap.erase(dead);
123  delete dead->second;
124  this->SetDirty();
125 }
126 
127 void FairRegistry::Clear(Option_t* /* option */)
128 {
129  if (fValuesLocked || fKeysLocked) {
130 
131  cout << "Clear: can't, there are locks in \""
132  << this->GetName() << "\"\n";
133  return;
134  }
135 
136  tRegMap::iterator mit = fMap.begin();
137  while (mit != fMap.end()) {
138  delete mit->second;
139  ++mit;
140  }
141  fMap.clear();
142  this->SetDirty();
143 }
144 
145 void FairRegistry::Dump(void) const
146 {
147  this->TNamed::Dump();
148  tRegMap::const_iterator mit = fMap.begin();
149 
150  cout<< "FairRegistry: `" << this->GetName() << "', "
151  << this->Size() << " entries."
152  << " (Locks: [Keys|Values] `key', `value'):\n";
153  while (mit != fMap.end()) {
154 
155  cout<< " [" << (fKeysLocked ? 'L' : 'U') << "|"
156  << (fValuesLocked ? 'L' : 'U') << "] "
157  << "`" << mit->first << "', `";
158  mit->second->Dump();
159  cout << "'\n";
160  ++mit;
161  }
162 
163 }
164 
165 ostream& FairRegistry::PrettyPrint(ostream& os) const
166 {
167  static int print_depth = 0;
168 
169  // print (to cout) the registry
170  tRegMap::const_iterator mit = this->fMap.begin();
171  for(int i=0; i<print_depth; ++i) { os << " "; }
172  os << "\"" << this->GetName() << "\", "
173  << this->Size() << " entries."
174  << " keys " << (this->fKeysLocked ? "locked" : "unlocked")
175  << ", values " << (this->fValuesLocked ? "locked" : "unlocked")
176  << "\n";
177 
178  print_depth+=4;
179  while (mit != this->fMap.end()) {
180  for(int i=0; i<print_depth; ++i) { os << " "; }
181 
182  os << mit->first << " = ";
183  mit->second->PrintStream(os);
184  os << endl;
185  ++mit;
186  }
187  print_depth-=4;
188  return os;
189 }
190 
191 void FairRegistry::Print(Option_t* /* option */) const
192 {
193  this->PrettyPrint(cout);
194 }
195 
196 
198 {
199  tRegMap::iterator mit = fMap.begin();
200  while (mit != fMap.end()) {
201  delete mit->second;
202  ++mit;
203  }
204 }
205 
207  fReg(r),
208  fIt()
209 {
210  // FIXME! Figure out how to correctly declare fIt to reflect
211  // constness.
212  fIt = const_cast<FairRegistry*>(fReg)->fMap.begin();
213 }
214 
216  : fReg(),
217  fIt()
218 {
219 }
220 
222 {
223 }
224 
226 {
227  if (fIt == fReg->fMap.end()) { return 0; }
228  const char* s = fIt->first.c_str();
229  ++ fIt;
230  return s;
231 }
232 
234 {
235  return FairRegistryKey(this);
236 }
237 
238 #define REGISTRY_SET(TYPE) \
239 bool FairRegistry::Set(const char* key, TYPE val) \
240 { \
241  tRegMap::iterator mit = fMap.find(key); \
242  if (mit != fMap.end()) { \
243  if (fValuesLocked) { \
244  cout \
245  << "Set: Values are locked - not overwriting \"" \
246  << key << "\" with \"" << val << "\" in registry \"" << this->GetName() << "\"\n";\
247  return false; \
248  } \
249  if (!dynamic_cast<FairRegistryItemXxx<TYPE>*>(mit->second)) { \
250  cout \
251  << "Set: attempt to overwrite old value for key \"" \
252  << key << "\" with different type value " \
253  << val << " in registry \"" << this->GetName() << "\"\n";\
254  return false; \
255  } \
256  delete mit->second; \
257  fMap.erase(mit); \
258  } \
259  else { \
260  if (fKeysLocked) { \
261  cout \
262  << "Set: Keys are locked - not adding `" \
263  << key << "' to registry \"" << this->GetName() << "\"\n";\
264  return false; \
265  } \
266  } \
267  FairRegistryItem* ri = new FairRegistryItemXxx< TYPE >(new TYPE (val)); \
268  fMap[key] = ri; \
269  this->SetDirty(); \
270  return true; \
271 }
272 REGISTRY_SET(char)
273 REGISTRY_SET(int)
274 REGISTRY_SET(double)
276 #undef REGISTRY_SET
277 
278 
279 // Must treat char* special
280 bool FairRegistry::Set(const char* key, const char* val)
281 {
282  tRegMap::iterator mit = fMap.find(key);
283  if (mit != fMap.end()) { // Found it
284  if (fValuesLocked) {
285 
286  cout << "Set: Values are locked - not overwriting `"
287  << key << "\" with \"" << val << "\" in registry \"" << this->GetName() << "\"\n";
288  return false;
289  }
290  if (! dynamic_cast<FairRegistryItemXxx<const char*>*>(mit->second) ) {
291 
292  cout << "Set: attempt to overwrite old value for key \""
293  << key << "\" with different type value "
294  << val << " in registry \"" << this->GetName() << "\"\n";
295  return false;
296  }
297  delete mit->second;
298  fMap.erase(mit);
299  } else { // didn't find it
300  if (fKeysLocked) {
301 
302  cout << "FairRegistry::Set: Keys are locked - not adding `"
303  << key << "' in registry \"" << this->GetName() << "\"\n";
304  return false;
305  }
306  }
307 
308  char** cpp = new char*;
309  (*cpp) = new char [strlen(val)+1];
310  strcpy(*cpp,val);
311  const char** ccpp = const_cast<const char**>(cpp);
313  fMap[key] = ri;
314  this->SetDirty();
315  return true;
316 }
317 
318 
319 #define REGISTRY_GET(TYPE) \
320 bool FairRegistry::Get(const char* key, TYPE & val) const \
321 { \
322  tRegMap::const_iterator mit = fMap.find(key); \
323  if (mit == fMap.end()) return false; \
324  FairRegistryItemXxx<TYPE>* rix = \
325  dynamic_cast<FairRegistryItemXxx<TYPE>*>(mit->second); \
326  if (rix == 0){ \
327  cout << "Key " << key \
328  << " does not have type " \
329  << #TYPE << " as required" \
330  << endl; \
331  return false; \
332  } \
333  val = *(rix->Get()); \
334  return true; \
335 }
336 REGISTRY_GET(char)
338 REGISTRY_GET(const char*)
339 REGISTRY_GET(int)
340 
341 bool FairRegistry::Get(const char* key, double& val) const
342 {
343  tRegMap::const_iterator mit = fMap.find(key);
344  if (mit == fMap.end()) { return false; }
345  // try correct type
347  dynamic_cast<FairRegistryItemXxx<double>*>(mit->second);
348  if (rixd) {
349  val = *(rixd->Get());
350  return true;
351  }
352  // try int
354  dynamic_cast<FairRegistryItemXxx<int>*>(mit->second);
355  if (rixi) {
356  val = *(rixi->Get());
357  return true;
358  }
359  cout << "Key " << key
360  << " does not have type double or int"
361  << " as required" << endl;
362  return false;
363 }
364 
365 #define REGISTRY_GET_TYPE(NAME, RETTYPE, TYPE) \
366 RETTYPE FairRegistry::Get##NAME(const char* key) const \
367 { \
368  TYPE retval = 0; \
369  if (Get(key,retval)) return retval; \
370  if (fErrorHandler) { fErrorHandler(); return 0; } \
371  else { \
372  cout \
373  << "\nFairRegistry::GetTYPE: failed to get value for key \"" \
374  << key << "\" from FairRegistry \"" << this->GetName() \
375  << "\". Aborting\n\n"; \
376  bool must_get_a_value = false; \
377  assert(must_get_a_value); \
378  return 0; \
379  } \
380 }
381 
382 REGISTRY_GET_TYPE(Char, char, char)
383 REGISTRY_GET_TYPE(CharString, const char*, const char*)
384 REGISTRY_GET_TYPE(Int, int, int)
385 REGISTRY_GET_TYPE(Double, double, double)
386 #undef REGISTRY_GET_TYPE
388 {
389  FairRegistry retval;
390  if (Get(key,retval)) { return retval; }
391  if (fErrorHandler) { fErrorHandler(); return retval; }
392  else {
393 
394  cout<< "\nFairRegistry::GetTYPE: failed to get value for key \""
395  << key << "\" from FairRegistry \"" << this->GetName()
396  << "\". Aborting\n\n";
397  bool must_get_a_value = false;
398  assert(must_get_a_value);
399  return retval;
400  }
401 }
402 
403 const type_info& FairRegistry::GetType(const char* key) const
404 {
405  tRegMap::const_iterator mit = fMap.find(key);
406  if (mit == fMap.end()) { return typeid(void); }
407  return mit->second->GetType();
408 }
409 string FairRegistry::GetTypeAsString(const char* key) const
410 {
411  tRegMap::const_iterator mit = fMap.find(key);
412  if (mit == fMap.end()) { return "void"; }
413  return mit->second->GetTypeAsString();
414 }
415 
416 string FairRegistry::GetValueAsString(const char* key) const
417 {
418  ostringstream os;
419  tRegMap::const_iterator mit = fMap.find(key);
420  if (mit == fMap.end()) { return ""; }
421  mit->second->PrintStream(os);
422  return os.str();
423 }
424 
425 void FairRegistry::Streamer(TBuffer& b)
426 {
427  int nobjects;
428 
429  if (b.IsReading()) {
430  Version_t v = b.ReadVersion();
431  if (v) {}
432  TNamed::Streamer(b);
433 
434  b >> nobjects;
435 
436  for (int i = 0; i < nobjects; ++i) {
437 
438  char tmp[1024];
439  b >> tmp;
440  string key(tmp);
441 
442  FairRegistryItem* ri;
443  b >> ri;
444 
445  // This is copied from Set(), bad programmer!
446  tRegMap::iterator mit = fMap.find(key);
447  if (mit != fMap.end()) {
448  delete mit->second;
449  fMap.erase(mit);
450  }
451  fMap[key] = ri;
452 
453  } // end reading in all FairRegistryItems
454  } // isReading
455  else {
456  b.WriteVersion(FairRegistry::IsA());
457  TNamed::Streamer(b);
458 
459  nobjects = fMap.size();
460  b << nobjects;
461 
462 
463  cout << "Streamer, Writing "<< nobjects <<" objects\n";
464 
465  tRegMap::iterator mit = fMap.begin();
466  while (mit != fMap.end()) {
467  b << mit->first.c_str();
468 
469 
470  cout << mit->first.c_str() << endl;
471 
472  b << mit->second;
473 
474  ++mit;
475  }
476  }
477 }
478 
479 
480 std::ostream& FairRegistry::PrintStream(std::ostream& os) const
481 {
482  os << "['" << this->GetName() << "'";
483 
484  tRegMap::const_iterator mit, done = fMap.end();
485  for (mit = fMap.begin(); mit != done; ++mit) {
486  os << " '" << mit->first << "'=(";
487  os << mit->second->GetTypeAsString();
488  os << ")";
489  mit->second->PrintStream(os);
490  }
491 
492  os << "]";
493  return os;
494 }
495 
496 
497 static std::istream& bail(std::istream& is)
498 {
499 
500  cout << "FairRegistry::Read(istream&) stream corrupted\n";
501  return is;
502 }
503 
504 std::istream& FairRegistry::ReadStream(std::istream& is)
505 {
506  FairRegistry reg;
507 
508  char c;
509  if (!is.get(c)) { return bail(is); }
510  if (c != '[') {
511  is.putback(c);
512  return bail(is);
513  }
514  string name = Util::read_quoted_string(is);
515  reg.SetName(name.c_str());
516 
517  while (is.get(c)) {
518  if (isspace(c)) { continue; }
519  if (c == ']') {
520  *this = reg;
521  return is;
522  }
523  is.putback(c);
524 
525  // get the key
526  string key = read_quoted_string(is);
527  if (key == "") { return bail(is); }
528 
529  // skip the "="
530  if (!is.get(c)) { return bail(is); }
531 
532  // get the "("
533  if (!is.get(c) || c != '(') {
534  is.putback(c);
535  return bail(is);
536  }
537 
538  // get the type
539  string type;
540  while (is.get(c)) {
541  if (c == ')') { break; }
542  type += c;
543  }
544 
545  // factory:
546  FairRegistryItem* ri = 0;
547  if (type == "char") {
548  ri = new FairRegistryItemXxx<char>();
549  } else if (type == "int") {
550  ri = new FairRegistryItemXxx<int>();
551  } else if (type == "double") {
552  ri = new FairRegistryItemXxx<double>();
553  } else if (type == "string") {
555  } else if (type == "FairRegistry") {
557  } else { return bail(is); }
558 
559  ri->ReadStream(is);
560  reg.fMap[key] = ri;
561  }
562  return is;
563 
564 }