File indexing completed on 2025-01-18 09:13:41
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <JSON/Printout.h>
0016 #include <JSON/Elements.h>
0017
0018
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
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
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
0045
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
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
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
0107 std::string dd4hep::json::_toString(unsigned long v, const char* fmt) {
0108 return __to_string(v, fmt);
0109 }
0110
0111
0112 std::string dd4hep::json::_toString(unsigned int v, const char* fmt) {
0113 return __to_string(v, fmt);
0114 }
0115
0116
0117 std::string dd4hep::json::_toString(int v, const char* fmt) {
0118 return __to_string(v, fmt);
0119 }
0120
0121
0122 std::string dd4hep::json::_toString(long v, const char* fmt) {
0123 return __to_string(v, fmt);
0124 }
0125
0126
0127 std::string dd4hep::json::_toString(float v, const char* fmt) {
0128 return __to_string(v, fmt);
0129 }
0130
0131
0132 std::string dd4hep::json::_toString(double v, const char* fmt) {
0133 return __to_string(v, fmt);
0134 }
0135
0136
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
0184 std::string dd4hep::json::getEnviron(const std::string& env) {
0185 return dd4hep::_getEnviron(env);
0186 }
0187
0188
0189 NodeList::NodeList(const NodeList& copy)
0190 : m_tag(copy.m_tag), m_node(copy.m_node)
0191 {
0192 reset();
0193 }
0194
0195
0196 NodeList::NodeList(JsonElement* node, const std::string& tag_value)
0197 : m_tag(tag_value), m_node(node)
0198 {
0199 reset();
0200 }
0201
0202
0203 NodeList::~NodeList() {
0204 }
0205
0206
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
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
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
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
0246 const char* Handle_t::rawTag() const {
0247 return m_node->first.c_str();
0248 }
0249
0250
0251 const char* Handle_t::rawText() const {
0252 return value_data(m_node->second).c_str();
0253 }
0254
0255
0256 const char* Handle_t::rawValue() const {
0257 return value_data(m_node->second).c_str();
0258 }
0259
0260
0261 Attribute Handle_t::attr_nothrow(const char* tag_value) const {
0262 return attribute_node(m_node, tag_value);
0263 }
0264
0265
0266 bool Handle_t::hasAttr(const char* tag_value) const {
0267 return m_node && 0 != node_first(m_node, tag_value);
0268 }
0269
0270
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
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
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
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
0339 const char* Handle_t::attr_value(const char* attr_tag) const {
0340 return attribute_value(attr_ptr(attr_tag));
0341 }
0342
0343
0344 const char* Handle_t::attr_value(const Attribute attr_val) const {
0345 return attribute_value(attr_val);
0346 }
0347
0348
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
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
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
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
0388 Collection_t::Collection_t(NodeList node_list)
0389 : m_children(node_list) {
0390 m_node = m_children.reset();
0391 }
0392
0393
0394 Collection_t& Collection_t::reset() {
0395 m_node = m_children.reset();
0396 return *this;
0397 }
0398
0399
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
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