DD4hep  1.30.0
Detector Description Toolkit for High Energy Physics
Elements.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // AIDA Detector description implementation
3 //--------------------------------------------------------------------------
4 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
5 // All rights reserved.
6 //
7 // For the licensing terms see $DD4hepINSTALL/LICENSE.
8 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
9 //
10 // Author : M.Frank
11 //
12 //==========================================================================
13 
14 // Framework include files
15 #include <JSON/Printout.h>
16 #include <JSON/Elements.h>
17 
18 // C/C++ include files
19 #include <iostream>
20 #include <stdexcept>
21 #include <cstdio>
22 #include <map>
23 
24 using namespace dd4hep::json;
25 static const size_t INVALID_NODE = ~0U;
26 
27 // Forward declarations
28 namespace dd4hep {
29  std::pair<int, double> _toInteger(const std::string& value);
30  std::pair<int, double> _toFloatingPoint(const std::string& value);
31  void _toDictionary(const std::string& name, const std::string& value, const std::string& typ);
32  std::string _getEnviron(const std::string& env);
33 }
34 // Static storage
35 namespace {
36  std::string _checkEnviron(const std::string& env) {
37  std::string r = dd4hep::_getEnviron(env);
38  return r.empty() ? env : r;
39  }
40 }
41 
42 namespace {
43 
44  // This should ensure we are not passing temporaries of std::string and then
45  // returning the "const char*" content calling .c_str()
46  const ptree::data_type& value_data(const ptree& entry) {
47  return entry.data();
48  }
49 
50  JsonElement* node_first(JsonElement* e, const char* tag) {
51  if ( e ) {
52  std::string t(tag);
53  if ( t == "*" ) {
54  ptree::iterator i = e->second.begin();
55  return i != e->second.end() ? &(*i) : 0;
56  }
57  ptree::assoc_iterator i = e->second.find(t);
58  return i != e->second.not_found() ? &(*i) : 0;
59  }
60  return 0;
61  }
62 
63  size_t node_count(JsonElement* e, const std::string& t) {
64  return e ? (t=="*" ? e->second.size() : e->second.count(t)) : 0;
65  }
66 
67  Attribute attribute_node(JsonElement* n, const char* t) {
68  if ( n ) {
69  auto i = n->second.find(t);
70  return i != n->second.not_found() ? &(*i) : 0;
71  }
72  return 0;
73  }
74 
75  const char* attribute_value(Attribute a) {
76  return value_data(a->second).c_str();
77  }
78 }
79 
81  if (attr)
82  return _toString(attribute_value(attr));
83  return "";
84 }
85 
86 template <typename T> static inline std::string __to_string(T value, const char* fmt) {
87  char text[128];
88  ::snprintf(text, sizeof(text), fmt, value);
89  return text;
90 }
91 
93 std::string dd4hep::json::_toString(const char* s) {
94  if ( !s || *s == 0 ) return "";
95  else if ( !(*s == '$' && *(s+1) == '{') ) return s;
96  return _checkEnviron(s);
97 }
98 
100 std::string dd4hep::json::_toString(const std::string& s) {
101  if ( s.length() < 3 || s[0] != '$' ) return s;
102  else if ( !(s[0] == '$' && s[1] == '{') ) return s;
103  return _checkEnviron(s);
104 }
105 
107 std::string dd4hep::json::_toString(unsigned long v, const char* fmt) {
108  return __to_string(v, fmt);
109 }
110 
112 std::string dd4hep::json::_toString(unsigned int v, const char* fmt) {
113  return __to_string(v, fmt);
114 }
115 
117 std::string dd4hep::json::_toString(int v, const char* fmt) {
118  return __to_string(v, fmt);
119 }
120 
122 std::string dd4hep::json::_toString(long v, const char* fmt) {
123  return __to_string(v, fmt);
124 }
125 
127 std::string dd4hep::json::_toString(float v, const char* fmt) {
128  return __to_string(v, fmt);
129 }
130 
132 std::string dd4hep::json::_toString(double v, const char* fmt) {
133  return __to_string(v, fmt);
134 }
135 
137 std::string dd4hep::json::_ptrToString(const void* v, const char* fmt) {
138  return __to_string(v, fmt);
139 }
140 
141 long dd4hep::json::_toLong(const char* value) {
142  return value ? (long)dd4hep::_toInteger(_toString(value)).second : -1L;
143 }
144 
145 int dd4hep::json::_toInt(const char* value) {
146  return value ? (int)dd4hep::_toInteger(_toString(value)).second : -1;
147 }
148 
149 bool dd4hep::json::_toBool(const char* value) {
150  if (value) {
151  std::string s = _toString(value);
152  return s == "true";
153  }
154  return false;
155 }
156 
157 float dd4hep::json::_toFloat(const char* value) {
158  return (float)(value ? dd4hep::_toFloatingPoint(_toString(value)).second : 0.0);
159 }
160 
161 double dd4hep::json::_toDouble(const char* value) {
162  return value ? dd4hep::_toFloatingPoint(_toString(value)).second : 0.0;
163 }
164 
165 void dd4hep::json::_toDictionary(const char* name, const char* value) {
166  dd4hep::_toDictionary(name, value, "number");
167 }
168 
169 template <typename T> void dd4hep::json::_toDictionary(const char* name, T value) {
170  dd4hep::_toDictionary(name, _toString(value), "number");
171 }
172 
173 template void dd4hep::json::_toDictionary(const char* name, const std::string& value);
174 template void dd4hep::json::_toDictionary(const char* name, unsigned long value);
175 template void dd4hep::json::_toDictionary(const char* name, unsigned int value);
176 template void dd4hep::json::_toDictionary(const char* name, unsigned short value);
177 template void dd4hep::json::_toDictionary(const char* name, int value);
178 template void dd4hep::json::_toDictionary(const char* name, long value);
179 template void dd4hep::json::_toDictionary(const char* name, short value);
180 template void dd4hep::json::_toDictionary(const char* name, float value);
181 template void dd4hep::json::_toDictionary(const char* name, double value);
182 
184 std::string dd4hep::json::getEnviron(const std::string& env) {
185  return dd4hep::_getEnviron(env);
186 }
187 
190  : m_tag(copy.m_tag), m_node(copy.m_node)
191 {
192  reset();
193 }
194 
196 NodeList::NodeList(JsonElement* node, const std::string& tag_value)
197  : m_tag(tag_value), m_node(node)
198 {
199  reset();
200 }
201 
204 }
205 
208  if ( m_tag == "*" )
209  m_ptr = std::make_pair(m_node->second.ordered_begin(), m_node->second.not_found());
210  else
211  m_ptr = m_node->second.equal_range(m_tag);
212  if ( m_ptr.first != m_ptr.second )
213  return &(*m_ptr.first);
214  return 0;
215 }
216 
219  if ( m_ptr.first != m_ptr.second ) {
220  m_ptr.first = ++m_ptr.first;
221  if ( m_ptr.first != m_ptr.second ) return &(*m_ptr.first);
222  }
223  return 0;
224 }
225 
228  if ( m_ptr.first != m_ptr.second ) {
229  m_ptr.first = --m_ptr.first;
230  if ( m_ptr.first != m_ptr.second ) return &(*m_ptr.first);
231  }
232  return 0;
233 }
234 
237  if ( this != &l ) {
238  m_tag = l.m_tag;
239  m_node = l.m_node;
240  reset();
241  }
242  return *this;
243 }
244 
246 const char* Handle_t::rawTag() const {
247  return m_node->first.c_str();
248 }
249 
251 const char* Handle_t::rawText() const {
252  return value_data(m_node->second).c_str();
253 }
254 
256 const char* Handle_t::rawValue() const {
257  return value_data(m_node->second).c_str();
258 }
259 
261 Attribute Handle_t::attr_nothrow(const char* tag_value) const {
262  return attribute_node(m_node, tag_value);
263 }
264 
266 bool Handle_t::hasAttr(const char* tag_value) const {
267  return m_node && 0 != node_first(m_node, tag_value);
268 }
269 
271 std::vector<Attribute> Handle_t::attributes() const {
272  std::vector < Attribute > attrs;
273  if (m_node) {
274  for(ptree::iterator i=m_node->second.begin(); i!=m_node->second.end(); ++i) {
275  Attribute a = &(*i);
276  attrs.emplace_back(a);
277  }
278  }
279  return attrs;
280 }
281 
282 size_t Handle_t::numChildren(const char* t, bool throw_exception) const {
283  size_t n = node_count(m_node, t);
284  if (n == INVALID_NODE && !throw_exception)
285  return 0;
286  else if (n != INVALID_NODE)
287  return n;
288  std::string msg = "Handle_t::numChildren: ";
289  if (m_node)
290  msg += "Element [" + tag() + "] has no children of type '" + _toString(t) + "'";
291  else
292  msg += "Element [INVALID] has no children of type '" + _toString(t) + "'";
293  throw std::runtime_error(msg);
294 }
295 
297 Handle_t Handle_t::child(const char* t, bool throw_exception) const {
298  Elt_t e = node_first(m_node, t);
299  if (e || !throw_exception)
300  return e;
301  std::string msg = "Handle_t::child: ";
302  if (m_node)
303  msg += "Element [" + tag() + "] has no child of type '" + _toString(t) + "'";
304  else
305  msg += "Element [INVALID]. Cannot remove child of type: '" + _toString(t) + "'";
306  throw std::runtime_error(msg);
307 }
308 
309 NodeList Handle_t::children(const char* tag_value) const {
310  return NodeList(m_node, tag_value);
311 }
312 
313 bool Handle_t::hasChild(const char* tag_value) const {
314  return node_first(m_node, tag_value) != 0;
315 }
316 
318 Attribute Handle_t::attr_ptr(const char* t) const {
319  Attribute a = attribute_node(m_node, t);
320  if (0 != a)
321  return a;
322  std::string msg = "Handle_t::attr_ptr: ";
323  if (m_node)
324  msg += "Element [" + tag() + "] has no attribute of type '" + _toString(t) + "'";
325  else
326  msg += "Element [INVALID] has no attribute of type '" + _toString(t) + "'";
327  throw std::runtime_error(msg);
328 }
329 
331 const char* Handle_t::attr_name(const Attribute a) const {
332  if (a) {
333  return a->first.c_str();
334  }
335  throw std::runtime_error("Attempt to access invalid XML attribute object!");
336 }
337 
339 const char* Handle_t::attr_value(const char* attr_tag) const {
340  return attribute_value(attr_ptr(attr_tag));
341 }
342 
344 const char* Handle_t::attr_value(const Attribute attr_val) const {
345  return attribute_value(attr_val);
346 }
347 
349 const char* Handle_t::attr_value_nothrow(const char* attr_tag) const {
350  Attribute a = attr_nothrow(attr_tag);
351  return a ? attribute_value(a) : 0;
352 }
353 
354 
357  if ( m_doc ) {
358  return m_doc;
359  }
360  throw std::runtime_error("Document::root: Invalid handle!");
361 }
362 
365  if ( m_doc ) {
366  printout(DEBUG,"DocumentHolder","+++ Release JSON document....");
367  delete m_doc;
368  }
369  m_doc = d;
370  return *this;
371 }
372 
375  assign(0);
376 }
377 
378 Attribute Element::getAttr(const char* name) const {
379  return m_element ? attribute_node(m_element, name) : 0;
380 }
381 
382 Collection_t::Collection_t(Handle_t element, const char* tag_value)
383  : m_children(element, tag_value) {
384  m_node = m_children.reset();
385 }
386 
389  : m_children(node_list) {
390  m_node = m_children.reset();
391 }
392 
395  m_node = m_children.reset();
396  return *this;
397 }
398 
400 size_t Collection_t::size() const {
401  return Handle_t(m_children.m_node).numChildren(m_children.m_tag.c_str(), false);
402 }
403 
406  if (m_node) {
407  throw std::runtime_error(std::string(e.what()) + "\n" + "dd4hep: Error interpreting XML nodes of type <" + tag() + "/>");
408  }
409  throw std::runtime_error(std::string(e.what()) + "\n" + "dd4hep: Error interpreting collections XML nodes.");
410 }
411 
413  while (m_node) {
414  m_node = m_children.next();
415  if (m_node && m_node->second.size() > 0 )
416  return;
417  }
418 }
419 
421  while (m_node) {
423  if (m_node && m_node->second.size() > 0 )
424  return;
425  }
426 }
427 
428 void Collection_t::operator++(int) const {
429  ++(*this);
430 }
431 
432 void Collection_t::operator--(int) const {
433  --(*this);
434 }
435 
437  dumpTree(elt.ptr());
438 }
439 
441  dumpTree(elt.ptr());
442 }
443 
445  struct Dump {
446  void operator()(const JsonElement* e, const std::string& tag) const {
447  std::string t = tag+" ";
448  printout(INFO,"DumpTree","+++ %s %s: %s",tag.c_str(), e->first.c_str(), e->second.data().c_str());
449  for(auto i=e->second.begin(); i!=e->second.end(); ++i)
450  (*this)(&(*i), t);
451  }
452  } _dmp;
453  _dmp(elt," ");
454 }
455 
dd4hep::json::Handle_t::attr_name
const char * attr_name(const Attribute attr) const
Access attribute name (throws exception if not present)
Definition: Elements.cpp:331
dd4hep::json::Element::m_element
Handle_t m_element
The underlying object holding the JsonElement pointer.
Definition: Elements.h:364
dd4hep::json::Collection_t::size
size_t size() const
Access the collection size. Avoid this call – sloooow!
Definition: Elements.cpp:400
dd4hep::json::Handle_t::Elt_t
JsonElement * Elt_t
Definition: Elements.h:138
dd4hep::json::Handle_t::Handle_t
Handle_t(Elt_t e=0)
Initializing constructor.
Definition: Elements.h:144
dd4hep::json::Collection_t::operator++
void operator++() const
Operator to advance the collection (pre increment)
Definition: Elements.cpp:412
dd4hep::json::_toInt
int _toInt(const char *value)
Conversion function from raw unicode string to int.
Definition: Elements.cpp:145
dd4hep::json::_toBool
bool _toBool(const char *value)
Conversion function from raw unicode string to bool.
Definition: Elements.cpp:149
dd4hep::json::Collection_t::Collection_t
Collection_t(Handle_t node, const char *tag)
Constructor over JsonElements with a given tag name.
Definition: Elements.cpp:382
dd4hep::json::DocumentHolder::assign
DocumentHolder & assign(DOC d)
Assign new document. Old document is dropped.
Definition: Elements.cpp:364
v
View * v
Definition: MultiView.cpp:28
dd4hep::json::_ptrToString
std::string _ptrToString(const void *p, const char *fmt="%p")
Format void pointer (64 bits) to string with arbitrary format.
Definition: Elements.cpp:137
dd4hep::json::NodeList::~NodeList
~NodeList()
Default destructor.
Definition: Elements.cpp:203
dd4hep::json::Collection_t::throw_loop_exception
void throw_loop_exception(const std::exception &e) const
Helper function to throw an exception.
Definition: Elements.cpp:405
dd4hep::json::Handle_t::tag
std::string tag() const
Text access to the element's tag.
Definition: Elements.h:158
dd4hep::exception
void exception(const std::string &src, const std::string &msg)
Definition: RootDictionary.h:69
dd4hep::json::Handle_t::m_node
Elt_t m_node
The pointer to the JsonElement.
Definition: Elements.h:141
dd4hep::json::Document::m_doc
DOC m_doc
Definition: Elements.h:299
dd4hep::_toDictionary
void _toDictionary(const std::string &name, const std::string &value)
Enter name value pair to the dictionary. "value" must be a numerical expression, which is evaluated.
Definition: Handle.cpp:240
dd4hep::json::Handle_t::attr_value
const char * attr_value(const Attribute attr) const
Access attribute value by the attribute (throws exception if not present)
Definition: Elements.cpp:344
dd4hep::json::_toString
std::string _toString(const Attribute attr)
Convert json attribute to STL string.
Definition: Elements.cpp:80
dd4hep::json::Attribute
const JsonAttr * Attribute
Definition: Elements.h:38
dd4hep::json::NodeList::operator=
NodeList & operator=(const NodeList &l)
Assignment operator.
Definition: Elements.cpp:236
dd4hep::json::Collection_t::reset
Collection_t & reset()
Reset the collection object to restart the iteration.
Definition: Elements.cpp:394
dd4hep::json::_toFloat
float _toFloat(const char *value)
Conversion function from raw unicode string to float.
Definition: Elements.cpp:157
dd4hep::json::NodeList::m_node
JsonElement * m_node
Definition: Elements.h:107
dd4hep::json::_toLong
long _toLong(const char *value)
Conversion function from raw unicode string to long.
Definition: Elements.cpp:141
dd4hep::json::NodeList::next
JsonElement * next() const
Advance to next element.
Definition: Elements.cpp:218
dd4hep::json::Handle_t::children
NodeList children(const char *tag) const
Access a group of children identified by the same tag name.
Definition: Elements.cpp:309
Elements.h
dd4hep::json::Handle_t::attr_nothrow
Attribute attr_nothrow(const char *tag) const
Access attribute pointer by the attribute's unicode name (no exception thrown if not present)
Definition: Elements.cpp:261
dd4hep::json::NodeList::reset
JsonElement * reset()
Reset the nodelist - e.g. restart iteration from beginning.
Definition: Elements.cpp:207
dd4hep::json::JsonElement
boost::property_tree::ptree::value_type JsonElement
Definition: config.h:33
dd4hep::json::NodeList::m_ptr
iter_t m_ptr
Definition: Elements.h:108
dd4hep::json::Handle_t::hasAttr
bool hasAttr(const char *t) const
Check for the existence of a named attribute.
Definition: Elements.cpp:266
dd4hep::json::Handle_t::rawText
const char * rawText() const
Unicode text access to the element's text.
Definition: Elements.cpp:251
dd4hep::_toInteger
std::pair< int, double > _toInteger(const std::string &value)
Definition: Handle.cpp:69
dd4hep::json::Element::getAttr
Attribute getAttr(const char *name) const
Access single attribute by its name.
Definition: Elements.cpp:378
dd4hep::json::Handle_t::rawValue
const char * rawValue() const
Unicode text access to the element's value.
Definition: Elements.cpp:256
dd4hep::json::Handle_t::ptr
Elt_t ptr() const
Direct access to the JsonElement by function.
Definition: Elements.h:150
dd4hep::json::Collection_t::m_children
NodeList m_children
Reference to the list of child nodes.
Definition: Elements.h:242
dd4hep::json::_toDouble
double _toDouble(const char *value)
Conversion function from raw unicode string to double.
Definition: Elements.cpp:161
dd4hep::json::Document::DOC
JsonElement * DOC
Definition: Elements.h:298
dd4hep::json
Namespace for the AIDA detector description toolkit supporting JSON utilities.
Definition: Factories.h:35
dd4hep::json::NodeList::m_tag
std::string m_tag
Definition: Elements.h:106
dd4hep::json::_toDictionary
void _toDictionary(const char *name, T value)
Helper function to populate the evaluator dictionary.
Definition: Elements.cpp:169
dd4hep::_toFloatingPoint
std::pair< int, double > _toFloatingPoint(const std::string &value)
Definition: Handle.cpp:62
dd4hep::json::NodeList
Class describing a list of JSON nodes.
Definition: Elements.h:103
dd4hep::_getEnviron
std::string _getEnviron(const std::string &env)
Evaluate string constant using environment stored in the evaluator.
Definition: Handle.cpp:281
dd4hep::json::NodeList::NodeList
NodeList(const NodeList &l)
Copy constructor.
Definition: Elements.cpp:189
dd4hep::json::Handle_t::numChildren
size_t numChildren(const char *tag, bool throw_exception) const
Access the number of children of this DOM element with a given tag name.
Definition: Elements.cpp:282
dd4hep::json::Handle_t::attributes
std::vector< Attribute > attributes() const
Retrieve a collection of all attributes of this DOM element.
Definition: Elements.cpp:271
dd4hep::json::DocumentHolder::~DocumentHolder
virtual ~DocumentHolder()
Standard destructor - releases the document.
Definition: Elements.cpp:374
Printout.h
dd4hep::json::Handle_t::rawTag
const char * rawTag() const
Unicode text access to the element's tag.
Definition: Elements.cpp:246
dd4hep::json::Handle_t::hasChild
bool hasChild(const char *tag) const
Check the existence of a child with a given tag name.
Definition: Elements.cpp:313
dd4hep::json::dumpTree
void dumpTree(Handle_t elt)
Definition: Elements.cpp:436
dd4hep::json::ptree
boost::property_tree::ptree ptree
Definition: config.h:30
dd4hep::json::Document::root
Handle_t root() const
Access the ROOT eleemnt of the DOM document.
Definition: Elements.cpp:356
dd4hep::json::Collection_t::operator--
void operator--() const
Operator to advance the collection (pre decrement)
Definition: Elements.cpp:420
dd4hep::json::DocumentHolder
Class supporting the basic functionality of an JSON document including ownership.
Definition: Elements.h:332
dd4hep
Namespace for the AIDA detector description toolkit.
Definition: AlignmentsCalib.h:28
dd4hep::json::Handle_t
Class to easily access the properties of single JsonElements.
Definition: Elements.h:135
dd4hep::json::Collection_t
Class to support the access to collections of JsonNodes (or JsonElements)
Definition: Elements.h:239
dd4hep::detail::tools::copy
void copy(Alignment from, Alignment to)
Copy alignment object from source object.
Definition: AlignmentTools.cpp:43
dd4hep::json::Handle_t::child
Handle_t child(const char *tag, bool throw_exception=true) const
Access a single child by its tag name (unicode)
Definition: Elements.cpp:297
dd4hep::json::Element::ptr
Elt_t ptr() const
Access to JsonElement pointer.
Definition: Elements.h:390
dd4hep::json::Element
User abstraction class to manipulate JSON elements within a document.
Definition: Elements.h:358
dd4hep::json::Handle_t::attr_value_nothrow
const char * attr_value_nothrow(const char *attr) const
Access attribute value by the attribute's unicode name (no exception thrown if not present)
Definition: Elements.cpp:349
dd4hep::json::getEnviron
std::string getEnviron(const std::string &env)
Helper function to lookup environment from the expression evaluator.
Definition: Elements.cpp:184
dd4hep::json::NodeList::previous
JsonElement * previous() const
Go back to previous element.
Definition: Elements.cpp:227
dd4hep::json::Handle_t::attr_ptr
Attribute attr_ptr(const char *attr) const
Access attribute pointer by the attribute's unicode name (throws exception if not present)
Definition: Elements.cpp:318