Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:13:41

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : M.Frank
0011 //
0012 //==========================================================================
0013 
0014 // Framework include files
0015 #include <JSON/Printout.h>
0016 #include <JSON/Elements.h>
0017 
0018 // C/C++ include files
0019 #include <iostream>
0020 #include <stdexcept>
0021 #include <cstdio>
0022 #include <map>
0023 
0024 using namespace dd4hep::json;
0025 static const size_t INVALID_NODE = ~0U;
0026 
0027 // Forward declarations
0028 namespace dd4hep {
0029   std::pair<int, double> _toInteger(const std::string& value);
0030   std::pair<int, double> _toFloatingPoint(const std::string& value);
0031   void   _toDictionary(const std::string& name, const std::string& value, const std::string& typ);
0032   std::string _getEnviron(const std::string& env);
0033 }
0034 // Static storage
0035 namespace {
0036   std::string _checkEnviron(const std::string& env)  {
0037     std::string r = dd4hep::_getEnviron(env);
0038     return r.empty() ? env : r;
0039   }
0040 }
0041 
0042 namespace {
0043 
0044   // This should ensure we are not passing temporaries of std::string and then
0045   // returning the "const char*" content calling .c_str()
0046   const ptree::data_type& value_data(const ptree& entry)  {
0047     return entry.data();
0048   }
0049 
0050   JsonElement* node_first(JsonElement* e, const char* tag) {
0051     if ( e )  {
0052       std::string t(tag);
0053       if ( t == "*" )  {
0054         ptree::iterator i = e->second.begin();
0055         return i != e->second.end() ? &(*i) : 0;
0056       }
0057       ptree::assoc_iterator i = e->second.find(t);
0058       return i != e->second.not_found() ? &(*i) : 0;
0059     }
0060     return 0;
0061   }
0062 
0063   size_t node_count(JsonElement* e, const std::string& t) {
0064     return e ? (t=="*" ? e->second.size() : e->second.count(t)) : 0;
0065   }
0066 
0067   Attribute attribute_node(JsonElement* n, const char* t)  {
0068     if ( n )  {
0069       auto i = n->second.find(t);
0070       return i != n->second.not_found() ? &(*i) : 0;
0071     }
0072     return 0;
0073   }
0074 
0075   const char* attribute_value(Attribute a) {
0076     return value_data(a->second).c_str();
0077   }
0078 }
0079 
0080 std::string dd4hep::json::_toString(Attribute attr) {
0081   if (attr)
0082     return _toString(attribute_value(attr));
0083   return "";
0084 }
0085 
0086 template <typename T> static inline std::string __to_string(T value, const char* fmt) {
0087   char text[128];
0088   ::snprintf(text, sizeof(text), fmt, value);
0089   return text;
0090 }
0091 
0092 /// Do-nothing version. Present for completeness and argument interchangeability
0093 std::string dd4hep::json::_toString(const char* s) {
0094   if ( !s || *s == 0 ) return "";
0095   else if ( !(*s == '$' && *(s+1) == '{') ) return s;
0096   return _checkEnviron(s);
0097 }
0098 
0099 /// Do-nothing version. Present for completeness and argument interchangeability
0100 std::string dd4hep::json::_toString(const std::string& s) {
0101   if ( s.length() < 3 || s[0] != '$' ) return s;
0102   else if ( !(s[0] == '$' && s[1] == '{') ) return s;
0103   return _checkEnviron(s);
0104 }
0105 
0106 /// Format unsigned long integer to string with arbitrary format
0107 std::string dd4hep::json::_toString(unsigned long v, const char* fmt) {
0108   return __to_string(v, fmt);
0109 }
0110 
0111 /// Format unsigned integer (32 bits) to string with arbitrary format
0112 std::string dd4hep::json::_toString(unsigned int v, const char* fmt) {
0113   return __to_string(v, fmt);
0114 }
0115 
0116 /// Format signed integer (32 bits) to string with arbitrary format
0117 std::string dd4hep::json::_toString(int v, const char* fmt) {
0118   return __to_string(v, fmt);
0119 }
0120 
0121 /// Format signed long integer to string with arbitrary format
0122 std::string dd4hep::json::_toString(long v, const char* fmt)   {
0123   return __to_string(v, fmt);
0124 }
0125 
0126 /// Format single procision float number (32 bits) to string with arbitrary format
0127 std::string dd4hep::json::_toString(float v, const char* fmt) {
0128   return __to_string(v, fmt);
0129 }
0130 
0131 /// Format double procision float number (64 bits) to string with arbitrary format
0132 std::string dd4hep::json::_toString(double v, const char* fmt) {
0133   return __to_string(v, fmt);
0134 }
0135 
0136 /// Format pointer to string with arbitrary format
0137 std::string dd4hep::json::_ptrToString(const void* v, const char* fmt) {
0138   return __to_string(v, fmt);
0139 }
0140 
0141 long dd4hep::json::_toLong(const char* value) {
0142   return value ? (long)dd4hep::_toInteger(_toString(value)).second : -1L;
0143 }
0144 
0145 int dd4hep::json::_toInt(const char* value) {
0146   return value ? (int)dd4hep::_toInteger(_toString(value)).second : -1;
0147 }
0148 
0149 bool dd4hep::json::_toBool(const char* value) {
0150   if (value) {
0151     std::string s = _toString(value);
0152     return s == "true";
0153   }
0154   return false;
0155 }
0156 
0157 float dd4hep::json::_toFloat(const char* value) {
0158   return (float)(value ? dd4hep::_toFloatingPoint(_toString(value)).second : 0.0);
0159 }
0160 
0161 double dd4hep::json::_toDouble(const char* value) {
0162   return value ? dd4hep::_toFloatingPoint(_toString(value)).second : 0.0;
0163 }
0164 
0165 void dd4hep::json::_toDictionary(const char* name, const char* value) {
0166   dd4hep::_toDictionary(name, value, "number");
0167 }
0168 
0169 template <typename T> void dd4hep::json::_toDictionary(const char* name, T value)   {
0170   dd4hep::_toDictionary(name, _toString(value), "number");
0171 }
0172 
0173 template void dd4hep::json::_toDictionary(const char* name, const std::string& value);
0174 template void dd4hep::json::_toDictionary(const char* name, unsigned long value);
0175 template void dd4hep::json::_toDictionary(const char* name, unsigned int value);
0176 template void dd4hep::json::_toDictionary(const char* name, unsigned short value);
0177 template void dd4hep::json::_toDictionary(const char* name, int value);
0178 template void dd4hep::json::_toDictionary(const char* name, long value);
0179 template void dd4hep::json::_toDictionary(const char* name, short value);
0180 template void dd4hep::json::_toDictionary(const char* name, float value);
0181 template void dd4hep::json::_toDictionary(const char* name, double value);
0182 
0183 /// Evaluate string constant using environment stored in the evaluator
0184 std::string dd4hep::json::getEnviron(const std::string& env)   {
0185   return dd4hep::_getEnviron(env);
0186 }
0187 
0188 /// Copy constructor
0189 NodeList::NodeList(const NodeList& copy)
0190   : m_tag(copy.m_tag), m_node(copy.m_node)
0191 {
0192   reset();
0193 }
0194 
0195 /// Initializing constructor
0196 NodeList::NodeList(JsonElement* node, const std::string& tag_value)
0197   : m_tag(tag_value), m_node(node)
0198 {
0199   reset();
0200 }
0201 
0202 /// Default destructor
0203 NodeList::~NodeList() {
0204 }
0205 
0206 /// Reset the nodelist
0207 JsonElement* NodeList::reset() {
0208   if ( m_tag == "*" )
0209     m_ptr = std::make_pair(m_node->second.ordered_begin(), m_node->second.not_found());
0210   else
0211     m_ptr = m_node->second.equal_range(m_tag);
0212   if ( m_ptr.first != m_ptr.second )
0213     return &(*m_ptr.first);
0214   return 0;
0215 }
0216 
0217 /// Advance to next element
0218 JsonElement* NodeList::next() const {
0219   if ( m_ptr.first != m_ptr.second )  {
0220     m_ptr.first = ++m_ptr.first;
0221     if ( m_ptr.first != m_ptr.second ) return &(*m_ptr.first);
0222   }
0223   return 0;
0224 }
0225 
0226 /// Go back to previous element
0227 JsonElement* NodeList::previous() const {
0228   if ( m_ptr.first != m_ptr.second )  {
0229     m_ptr.first = --m_ptr.first;
0230     if ( m_ptr.first != m_ptr.second ) return &(*m_ptr.first);
0231   }
0232   return 0;
0233 }
0234 
0235 /// Assignment operator
0236 NodeList& NodeList::operator=(const NodeList& l) {
0237   if ( this != &l ) {
0238     m_tag  = l.m_tag;
0239     m_node = l.m_node;
0240     reset();
0241   }
0242   return *this;
0243 }
0244 
0245 /// Unicode text access to the element's tag. This must be wrong ....
0246 const char* Handle_t::rawTag() const {
0247   return m_node->first.c_str();
0248 }
0249 
0250 /// Unicode text access to the element's text
0251 const char* Handle_t::rawText() const {
0252   return value_data(m_node->second).c_str();
0253 }
0254 
0255 /// Unicode text access to the element's value
0256 const char* Handle_t::rawValue() const {
0257   return value_data(m_node->second).c_str();
0258 }
0259 
0260 /// Access attribute pointer by the attribute's unicode name (no exception thrown if not present)
0261 Attribute Handle_t::attr_nothrow(const char* tag_value) const {
0262   return attribute_node(m_node, tag_value);
0263 }
0264 
0265 /// Check for the existence of a named attribute
0266 bool Handle_t::hasAttr(const char* tag_value) const {
0267   return m_node && 0 != node_first(m_node, tag_value);
0268 }
0269 
0270 /// Retrieve a collection of all attributes of this DOM element
0271 std::vector<Attribute> Handle_t::attributes() const {
0272   std::vector < Attribute > attrs;
0273   if (m_node) {
0274     for(ptree::iterator i=m_node->second.begin(); i!=m_node->second.end(); ++i)  {
0275       Attribute a = &(*i);
0276       attrs.emplace_back(a);
0277     }
0278   }
0279   return attrs;
0280 }
0281 
0282 size_t Handle_t::numChildren(const char* t, bool throw_exception) const {
0283   size_t n = node_count(m_node, t);
0284   if (n == INVALID_NODE && !throw_exception)
0285     return 0;
0286   else if (n != INVALID_NODE)
0287     return n;
0288   std::string msg = "Handle_t::numChildren: ";
0289   if (m_node)
0290     msg += "Element [" + tag() + "] has no children of type '" + _toString(t) + "'";
0291   else
0292     msg += "Element [INVALID] has no children of type '" + _toString(t) + "'";
0293   throw std::runtime_error(msg);
0294 }
0295 
0296 /// Remove a single child node identified by its handle from the tree of the element
0297 Handle_t Handle_t::child(const char* t, bool throw_exception) const {
0298   Elt_t e = node_first(m_node, t);
0299   if (e || !throw_exception)
0300     return e;
0301   std::string msg = "Handle_t::child: ";
0302   if (m_node)
0303     msg += "Element [" + tag() + "] has no child of type '" + _toString(t) + "'";
0304   else
0305     msg += "Element [INVALID]. Cannot remove child of type: '" + _toString(t) + "'";
0306   throw std::runtime_error(msg);
0307 }
0308 
0309 NodeList Handle_t::children(const char* tag_value) const {
0310   return NodeList(m_node, tag_value);
0311 }
0312 
0313 bool Handle_t::hasChild(const char* tag_value) const {
0314   return node_first(m_node, tag_value) != 0;
0315 }
0316 
0317 /// Access attribute pointer by the attribute's unicode name (throws exception if not present)
0318 Attribute Handle_t::attr_ptr(const char* t) const {
0319   Attribute a = attribute_node(m_node, t);
0320   if (0 != a)
0321     return a;
0322   std::string msg = "Handle_t::attr_ptr: ";
0323   if (m_node)
0324     msg += "Element [" + tag() + "] has no attribute of type '" + _toString(t) + "'";
0325   else
0326     msg += "Element [INVALID] has no attribute of type '" + _toString(t) + "'";
0327   throw std::runtime_error(msg);
0328 }
0329 
0330 /// Access attribute name (throws exception if not present)
0331 const char* Handle_t::attr_name(const Attribute a) const {
0332   if (a) {
0333     return a->first.c_str();
0334   }
0335   throw std::runtime_error("Attempt to access invalid XML attribute object!");
0336 }
0337 
0338 /// Access attribute value by the attribute's unicode name (throws exception if not present)
0339 const char* Handle_t::attr_value(const char* attr_tag) const {
0340   return attribute_value(attr_ptr(attr_tag));
0341 }
0342 
0343 /// Access attribute value by the attribute  (throws exception if not present)
0344 const char* Handle_t::attr_value(const Attribute attr_val) const {
0345   return attribute_value(attr_val);
0346 }
0347 
0348 /// Access attribute value by the attribute's unicode name (no exception thrown if not present)
0349 const char* Handle_t::attr_value_nothrow(const char* attr_tag) const {
0350   Attribute a = attr_nothrow(attr_tag);
0351   return a ? attribute_value(a) : 0;
0352 }
0353 
0354 
0355 /// Access the ROOT eleemnt of the DOM document
0356 Handle_t Document::root() const   {
0357   if ( m_doc )   {
0358     return m_doc;
0359   }
0360   throw std::runtime_error("Document::root: Invalid handle!");
0361 }
0362 
0363 /// Assign new document. Old document is dropped.
0364 DocumentHolder& DocumentHolder::assign(DOC d)   {
0365   if ( m_doc )   {
0366     printout(DEBUG,"DocumentHolder","+++ Release JSON document....");
0367     delete m_doc;
0368   }
0369   m_doc = d;
0370   return *this;
0371 }
0372 
0373 /// Standard destructor - releases the document
0374 DocumentHolder::~DocumentHolder()   {
0375   assign(0);
0376 }
0377 
0378 Attribute Element::getAttr(const char* name) const {
0379   return m_element ? attribute_node(m_element, name) : 0;
0380 }
0381 
0382 Collection_t::Collection_t(Handle_t element, const char* tag_value)
0383   : m_children(element, tag_value) {
0384   m_node = m_children.reset();
0385 }
0386 
0387 /// Constructor over XmlElements in a node list
0388 Collection_t::Collection_t(NodeList node_list)
0389   : m_children(node_list) {
0390   m_node = m_children.reset();
0391 }
0392 
0393 /// Reset the collection object to restart the iteration
0394 Collection_t& Collection_t::reset() {
0395   m_node = m_children.reset();
0396   return *this;
0397 }
0398 
0399 /// Access the collection size. Avoid this call -- sloooow!
0400 size_t Collection_t::size() const {
0401   return Handle_t(m_children.m_node).numChildren(m_children.m_tag.c_str(), false);
0402 }
0403 
0404 /// Helper function to throw an exception
0405 void Collection_t::throw_loop_exception(const std::exception& e) const {
0406   if (m_node) {
0407     throw std::runtime_error(std::string(e.what()) + "\n" + "dd4hep: Error interpreting XML nodes of type <" + tag() + "/>");
0408   }
0409   throw std::runtime_error(std::string(e.what()) + "\n" + "dd4hep: Error interpreting collections XML nodes.");
0410 }
0411 
0412 void Collection_t::operator++() const {
0413   while (m_node) {
0414     m_node = m_children.next();
0415     if (m_node && m_node->second.size() > 0 )
0416       return;
0417   }
0418 }
0419 
0420 void Collection_t::operator--() const {
0421   while (m_node) {
0422     m_node = m_children.previous();
0423     if (m_node && m_node->second.size() > 0 )
0424       return;
0425   }
0426 }
0427 
0428 void Collection_t::operator++(int) const {
0429   ++(*this);
0430 }
0431 
0432 void Collection_t::operator--(int) const {
0433   --(*this);
0434 }
0435 
0436 void dd4hep::json::dumpTree(Handle_t elt)   {
0437   dumpTree(elt.ptr());
0438 }
0439 
0440 void dd4hep::json::dumpTree(Element elt)   {
0441   dumpTree(elt.ptr());
0442 }
0443 
0444 void dd4hep::json::dumpTree(const JsonElement* elt)   {
0445   struct Dump {
0446     void operator()(const JsonElement* e, const std::string& tag)   const  {
0447       std::string t = tag+"   ";
0448       printout(INFO,"DumpTree","+++ %s %s: %s",tag.c_str(), e->first.c_str(), e->second.data().c_str());
0449       for(auto i=e->second.begin(); i!=e->second.end(); ++i)
0450         (*this)(&(*i), t);
0451     }
0452   } _dmp;
0453   _dmp(elt," ");
0454 }
0455