ATLAS Offline Software
ExpatCoreParser.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 
6 
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <expat.h>
11 
12 #include <string>
13 #include <vector>
14 #include <iostream>
15 #include <map>
16 
18 
19 #include "ExpatCoreParser.h"
20 
22 ExpatCoreParser::ExternalEntityMap ExpatCoreParser::s_entities;
23 ExpatCoreParser::ExternalEntityMap ExpatCoreParser::s_text_entities;
24 
26 {
27 public:
28  static bool get_debug_state()
29  {
30  return ::getenv ("XMLDEBUG") != 0;
31  }
32  static bool debug ()
33  {
34  static const bool debug_state = get_debug_state();
35  return debug_state;
36  }
37 };
38 
39 
40 
41 #define BUFFSIZE 1000
42 
43 void ExpatCoreParser::start (void* user_data, const char* el, const char** attr)
44 {
45  ExpatCoreParser& me = *reinterpret_cast<ExpatCoreParser*> (user_data);
46  me.do_start (el, attr);
47 }
48 
49 void ExpatCoreParser::end (void* user_data, const char* el)
50 {
51  ExpatCoreParser& me = *reinterpret_cast<ExpatCoreParser*> (user_data);
52  me.do_end (el);
53 }
54 
55 void ExpatCoreParser::char_data (void* user_data, const XML_Char* s, int len)
56 {
57  ExpatCoreParser& me = *reinterpret_cast<ExpatCoreParser*> (user_data);
58  me.do_char_data (s, len);
59 }
60 
61 void ExpatCoreParser::default_handler (void* user_data, const XML_Char* s, int len)
62 {
63  ExpatCoreParser& me = *reinterpret_cast<ExpatCoreParser*> (user_data);
64  me.do_default_handler (s, len);
65 }
66 
67 void ExpatCoreParser::comment (void* user_data, const XML_Char* s)
68 {
69  ExpatCoreParser& me = *reinterpret_cast<ExpatCoreParser*> (user_data);
70  me.do_comment (s);
71 }
72 
74  const XML_Char* context,
75  const XML_Char* /*base*/,
76  const XML_Char* systemId,
77  const XML_Char* /*publicId*/)
78 {
79  void* user_data = XML_GetUserData (parser);
80  ExpatCoreParser& me = *reinterpret_cast<ExpatCoreParser*> (user_data);
81  return (me.do_external_entity (parser, context, systemId));
82 }
83 
84 void ExpatCoreParser::register_external_entity (const std::string& name, const std::string& file_name)
85 {
87  {
88  std::cout << "ExpatCoreParser::register_external_entity> name=" << name
89  << " file_name=" << file_name << std::endl;
90  }
91 
92  lock_t lock (s_mutex);
93  s_entities[name] = file_name;
94 }
95 
96 void ExpatCoreParser::register_text_entity (const std::string& name, const std::string& text)
97 {
99  {
100  std::cout << "ExpatCoreParser::register_text_entity> name=" << name
101  << std::endl;
102  }
103 
104  lock_t lock (s_mutex);
105  s_text_entities[name] = text;
106 }
107 
108 void ExpatCoreParser::entity (void* /*userData*/,
109  const XML_Char* entityName,
110  int is_parameter_entity,
111  const XML_Char* value,
112  int value_length,
113  const XML_Char* base,
114  const XML_Char* systemId,
115  const XML_Char* publicId,
116  const XML_Char* /*notationName*/)
117 {
118  if (!base) base = "none";
119  if (!systemId) systemId = "none";
120  if (!publicId) publicId = "none";
121 
122  std::string temp = "none";
123 
124  if (value)
125  {
126  char* t = (char*) malloc (value_length + 1);
127  strncpy (t, value, value_length);
128  t[value_length] = 0;
129 
130  temp = (const char*) t;
131 
132  free (t);
133  }
134 
136  {
137  //XML_Parser p = (XML_Parser) userData;
138 
139  //int ln = XML_GetCurrentLineNumber (p);
140 
141  std::cout << "ExpatCoreParser::entity[" << 0 << "]> " << entityName;
142  std::cout << " is_parameter=" << is_parameter_entity;
143  std::cout << " value=[" << temp << "]";
144  std::cout << " base=[" << base << "]";
145  std::cout << " systemId=[" << systemId << "]";
146  std::cout << " publicId=[" << publicId << "]";
147  std::cout << std::endl;
148  }
149 }
150 
151 std::unique_ptr<CoreParser::DOMNode> ExpatCoreParser::get_document ()
152 {
153  return std::move(m_top);
154 }
155 
157  : m_top (nullptr),
158  m_last (nullptr),
159  m_prefix (prefix)
160 {
161 }
162 
163 void ExpatCoreParser::do_start (const char* el, const char** attr)
164 {
165  int i;
166 
167  std::map <std::string, std::string> a;
168 
169  if (!m_top)
170  {
171  m_top = std::make_unique<CoreParser::DOMNode> ();
172  m_last = m_top.get();
173  }
174 
176 
178  {
179  std::cout << "ExpatCoreParser::do_start> el=" << el << " top=" << m_top.get() << " last=" << m_last << " node=" << node << std::endl;
180  }
181 
182  m_last = node;
183 
184  for (i = 0; attr[i]; i += 2)
185  {
186  const char* name = attr[i];
187  const char* value = attr[i+1];
188 
189  node->m_attributes[name] = value;
190  }
191 }
192 
193 void ExpatCoreParser::do_end (const char* el)
194 {
196  {
197  std::cout << "ExpatCoreParser::do_end> el=" << el << std::endl;
198  }
199 
201 }
202 
203 void ExpatCoreParser::do_char_data (const XML_Char* s, int len)
204 {
205  if (len == 0) return;
206 
207  while ((len > 0) && (s[len-1] == '\n')) len--;
208 
209  if (len == 0) return;
210 
211  char* temp = (char*) malloc (len + 1);
212  strncpy (temp, s, len);
213  temp[len] = 0;
214 
216  {
217  std::cout << "ExpatCoreParser::do_char_data> [" << temp << "]" << std::endl;
218  }
219 
220  free (temp);
221 }
222 
223 void ExpatCoreParser::do_default_handler (const XML_Char* s, int len)
224 {
225  if (len == 0) return;
226 
227  while ((len > 0) && (s[len-1] == '\n')) len--;
228 
229  if (len == 0) return;
230 
231  char* temp = (char*) malloc (len + 1);
232  strncpy (temp, s, len);
233  temp[len] = 0;
234 
236  {
237  std::cout << "ExpatCoreParser::do_default_handler> [" << temp << "]" << std::endl;
238  }
239 
240  free (temp);
241 }
242 
243 void ExpatCoreParser::do_comment (const XML_Char* s)
244 {
245  if (!m_top)
246  {
247  m_top = std::make_unique<CoreParser::DOMNode> ();
248  m_last = m_top.get();
249  }
250 
252 
254  {
255  std::cout << "ExpatCoreParser::do_comment> s=" << s << " top=" << m_top.get() << " last=" << m_last << " node=" << node << std::endl;
256  }
257 
258  // Node is owned by m_last.
259  // cppcheck-suppress memleak
260  node = nullptr;
261 }
262 
263 int ExpatCoreParser::generic_parse (XML_Parser p, const std::string& file_name)
264 {
265  FILE* docfd;
266 
268  {
269  std::cout << "ExpatCoreParser::generic_parse> file_name=" << file_name << " prefix=" << m_prefix << std::endl;
270  }
271 
272  std::string temp_name = file_name;
273 
274  docfd = fopen (temp_name.c_str (), "r");
275  if (!docfd)
276  {
277  temp_name = m_prefix + "/" + file_name;
278 
279  docfd = fopen (temp_name.c_str (), "r");
280  }
281 
282  if (docfd == 0)
283  {
284  const char* xmlpathenv = ::getenv ("XMLPATH");
285 
286  if (xmlpathenv == 0) return (0);
287 
288  std::string xmlpath = xmlpathenv;
289 
290  std::string::size_type pos = 0;
291 
292  while (pos != std::string::npos)
293  {
294  std::string::size_type sep = xmlpath.find (":", pos);
295 
296  if (sep == std::string::npos)
297  {
298  temp_name = xmlpath.substr (pos);
299  pos = std::string::npos;
300  }
301  else
302  {
303  temp_name = xmlpath.substr (pos, sep - pos);
304  pos = sep + 1;
305  }
306 
307  if (temp_name == "") continue;
308 
309  std::string last_temp_name = temp_name;
310 
311  temp_name += "/";
312  temp_name += file_name;
313 
315  {
316  std::cout << "ExpatCoreParser::generic_parse> file_name=" << file_name
317  << " xmlpath=" << xmlpath
318  << " temp_name=" << temp_name
319  << std::endl;
320  }
321 
322  docfd = fopen (temp_name.c_str (), "r");
323  if (docfd != 0) break;
324 
325  // Test whether prefix is a relative path and if so use it
326  if (m_prefix != "" && '/' != m_prefix[0]) {
327 
328  temp_name = last_temp_name;
329  temp_name += "/";
330  temp_name += m_prefix;
331  temp_name += "/";
332  temp_name += file_name;
333 
335  {
336  std::cout << "ExpatCoreParser::generic_parse> file_name=" << file_name
337  << " xmlpath=" << xmlpath
338  << " temp_name=" << temp_name
339  << std::endl;
340  }
341 
342  docfd = fopen (temp_name.c_str (), "r");
343  if (docfd != 0) break;
344  }
345  }
346  }
347 
348  if (docfd == 0)
349  {
350  return (0);
351  }
352 
353  int result = 1;
354 
355  XML_SetParamEntityParsing (p, XML_PARAM_ENTITY_PARSING_ALWAYS);
356  XML_SetElementHandler (p, start, end);
357  XML_SetCharacterDataHandler (p, char_data);
358  XML_SetExternalEntityRefHandler (p, external_entity);
359  XML_SetCommentHandler (p, comment);
360  XML_SetUserData (p, this);
361  //XML_SetDefaultHandlerExpand (p, default_handler);
362  //XML_SetEntityDeclHandler (p, entity);
363  //XML_UseParserAsHandlerArg (p);
364 
366  {
367  std::cout << "ExpatCoreParser::generic_parse> starting" << std::endl;
368  }
369 
370  for (;;)
371  {
372  int items;
373 
374  char* buff = (char*) XML_GetBuffer (p, BUFFSIZE + 1);
375 
376  items = fread (buff, 1, BUFFSIZE, docfd);
377 
378  if (ferror (docfd))
379  {
380  std::cout << "Read error" << std::endl;
381  result = 0;
382  break;
383  }
384 
385  int done = feof (docfd);
386 
387  buff[items] = 0;
388 
389  //std::cout << "2) read=" << items << " [" << buff << "] " << done << std::endl;
390 
391  if (XML_ParseBuffer (p, BUFFSIZE, done) == XML_STATUS_ERROR)
392  {
393  if (!done)
394  {
395  std::cout << "ExpatCoreParser::Parse error at line " << XML_GetCurrentLineNumber(p)
396  << " of file " << file_name
397  << ":" << std::endl
398  << XML_ErrorString (XML_GetErrorCode(p)) << std::endl;
399  result = 0;
400  }
401  /* handle parse error */
402  }
403  if (done) break;
404  }
405 
406  fclose (docfd);
407 
408  return (result);
409 }
410 
411 int ExpatCoreParser::generic_text_parse (XML_Parser p, const std::string& text)
412 {
414  {
415  std::cout << "ExpatCoreParser::generic_text_parse> " << std::endl;
416  }
417 
418  int result = 1;
419 
420  XML_SetParamEntityParsing (p, XML_PARAM_ENTITY_PARSING_ALWAYS);
421  XML_SetElementHandler (p, start, end);
422  XML_SetCharacterDataHandler (p, char_data);
423  XML_SetExternalEntityRefHandler (p, external_entity);
424  XML_SetCommentHandler (p, comment);
425  XML_SetUserData (p, this);
426  //XML_SetDefaultHandlerExpand (p, default_handler);
427  //XML_SetEntityDeclHandler (p, entity);
428  //XML_UseParserAsHandlerArg (p);
429 
431  {
432  std::cout << "ExpatCoreParser::generic_text_parse> starting" << std::endl;
433  }
434 
435  //for (;;)
436  {
437  char* buff = (char*) XML_GetBuffer (p, text.size() + 1);
438  strcpy (buff, text.c_str ());
439 
440  int done = 1;
441 
442  if (XML_ParseBuffer (p, text.size(), done) == XML_STATUS_ERROR)
443  {
444  std::cout << "ExpatCoreParser::Parse error at line " << XML_GetCurrentLineNumber(p)
445  << ":" << std::endl
446  << XML_ErrorString (XML_GetErrorCode(p)) << std::endl;
447  result = 0;
448  /* handle parse error */
449  }
450  //if (done) break;
451  }
452 
453  return (result);
454 }
455 
457  const XML_Char* context,
458  const XML_Char* systemId)
459 {
460  std::string context_str;
461 
462  if (context == 0) context_str = "none";
463  else context_str = context;
464 
465  bool done = false;
466  int status = 0;
467 
468  if (context != 0)
469  {
470  std::string replacement = find_text_entity (context_str);
471 
472  if (replacement != "")
473  {
475  {
476  std::cout << "ExpatCoreParser::do_external_entity> "
477  << " context=[" << context_str << "]"
478  << " replacement=[" << replacement << "]"
479  << std::endl;
480  }
481 
482  XML_Parser p = XML_ExternalEntityParserCreate (parser, context, NULL);
483 
484  status = generic_text_parse (p, replacement);
485 
486  XML_ParserFree (p);
487 
488  done = true;
489  }
490  }
491 
492  if (!done)
493  {
494  std::string replacement = find_external_entity (context_str);
495 
496  if (replacement == "NULL")
497  {
498  return (1);
499  }
500 
501  if (replacement != "")
502  {
503  systemId = replacement.c_str ();
504  }
505 
507  {
508  std::cout << "ExpatCoreParser::do_external_entity> "
509  << " context=[" << context_str << "]"
510  << " systemId=[" << systemId << "]"
511  << " replacement=[" << replacement << "]"
512  << std::endl;
513  }
514 
515  XML_Parser p = XML_ExternalEntityParserCreate (parser, context, NULL);
516 
518 
519  XML_ParserFree (p);
520  }
521 
522 
523  return (status);
524 }
525 
526 const std::string& ExpatCoreParser::find_external_entity (const std::string& name)
527 {
528  lock_t lock (s_mutex);
529  ExternalEntityMap::const_iterator it = s_entities.find (name);
530  if (it == s_entities.end ())
531  {
532  static const std::string empty;
533  return (empty);
534  }
535  else
536  {
537  return ((*it).second);
538  }
539 }
540 
541 const std::string& ExpatCoreParser::find_text_entity (const std::string& name)
542 {
543  lock_t lock (s_mutex);
544  ExternalEntityMap::const_iterator it = s_text_entities.find (name);
545  if (it == s_text_entities.end ())
546  {
547  static const std::string empty;
548  return (empty);
549  }
550  else
551  {
552  return ((*it).second);
553  }
554 }
555 
556 std::unique_ptr<CoreParser::DOMNode>
557 ExpatCoreParser::parse (const std::string& file_name)
558 {
559  std::string name = file_name;
560 
561  std::string::size_type pos = file_name.rfind ('/');
562  std::string prefix;
563  if (pos != std::string::npos)
564  {
565  prefix = file_name.substr (0, pos);
566  name = file_name.substr (pos + 1);
567  }
568 
569  ExpatCoreParser me (prefix);
570  XML_Parser p = XML_ParserCreate (NULL);
571 
572  if (!p)
573  {
574  std::cout << "ExpatCoreParser::Couldn't allocate memory for parser" << std::endl;
575  std::abort();
576  }
577 
578  me.generic_parse (p, name);
579 
580  XML_ParserFree (p);
581 
582  return me.get_document ();
583 }
584 
ExpatCoreParser::external_entity
static int external_entity(XML_Parser parser, const XML_Char *context, const XML_Char *, const XML_Char *systemId, const XML_Char *)
Definition: ExpatCoreParser.cxx:73
base
std::string base
Definition: hcg.cxx:78
python.CaloScaleNoiseConfig.parser
parser
Definition: CaloScaleNoiseConfig.py:75
get_hdefs.buff
buff
Definition: get_hdefs.py:64
ExpatCoreParser::find_external_entity
static const std::string & find_external_entity(const std::string &name)
Definition: ExpatCoreParser.cxx:526
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
get_generator_info.result
result
Definition: get_generator_info.py:21
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
BUFFSIZE
#define BUFFSIZE
Definition: ExpatCoreParser.cxx:41
ExpatCoreParser::do_end
void do_end(const char *el)
Definition: ExpatCoreParser.cxx:193
BeamSpot::mutex
std::mutex mutex
Definition: InDetBeamSpotVertex.cxx:18
ExpatCoreParser::do_external_entity
int do_external_entity(XML_Parser parser, const XML_Char *context, const XML_Char *systemId)
Definition: ExpatCoreParser.cxx:456
ExpatCoreParser::find_text_entity
static const std::string & find_text_entity(const std::string &name)
Definition: ExpatCoreParser.cxx:541
skel.it
it
Definition: skel.GENtoEVGEN.py:423
ExpatCoreParser::lock_t
std::lock_guard< std::mutex > lock_t
Definition: ExpatCoreParser.h:71
ExpatCoreParser::entity
static void entity(void *userData, const XML_Char *entityName, int is_parameter_entity, const XML_Char *value, int value_length, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId, const XML_Char *)
Definition: ExpatCoreParser.cxx:108
athena.value
value
Definition: athena.py:122
CoreParser::DOMNode
Definition: DOMNode.h:21
ExpatCoreParser::ExternalEntityMap
std::map< std::string, std::string > ExternalEntityMap
Definition: ExpatCoreParser.h:19
ExpatCoreParser::do_char_data
void do_char_data(const XML_Char *s, int len)
Definition: ExpatCoreParser.cxx:203
ExpatCoreParser::m_prefix
std::string m_prefix
Definition: ExpatCoreParser.h:68
ExpatCoreParserDebugger
Definition: ExpatCoreParser.cxx:26
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
XMLCoreParser.h
empty
bool empty(TH1 *h)
Definition: computils.cxx:294
ExpatCoreParser::end
static void end(void *, const char *el)
Definition: ExpatCoreParser.cxx:49
ExpatCoreParser.h
ExpatCoreParser::ExpatCoreParser
ExpatCoreParser(const std::string &prefix)
Definition: ExpatCoreParser.cxx:156
ExpatCoreParser
Definition: ExpatCoreParser.h:16
physics_parameters.file_name
string file_name
Definition: physics_parameters.py:32
ExpatCoreParserDebugger::get_debug_state
static bool get_debug_state()
Definition: ExpatCoreParser.cxx:28
CoreParser::DOMNode::COMMENT_NODE
@ COMMENT_NODE
Definition: DOMNode.h:27
lumiFormat.i
int i
Definition: lumiFormat.py:92
ExpatCoreParser::register_text_entity
static void register_text_entity(const std::string &name, const std::string &text)
Definition: ExpatCoreParser.cxx:96
CoreParser::DOMNode::ELEMENT_NODE
@ ELEMENT_NODE
Definition: DOMNode.h:26
ExpatCoreParser::do_comment
void do_comment(const XML_Char *s)
Definition: ExpatCoreParser.cxx:243
checkCorrelInHIST.prefix
dictionary prefix
Definition: checkCorrelInHIST.py:391
ExpatCoreParser::m_last
CoreParser::DOMNode * m_last
Definition: ExpatCoreParser.h:67
plotIsoValidation.el
el
Definition: plotIsoValidation.py:197
CaloCondBlobAlgs_fillNoiseFromASCII.systemId
systemId
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:108
ExpatCoreParser::do_default_handler
void do_default_handler(const XML_Char *s, int len)
Definition: ExpatCoreParser.cxx:223
TrigInDetValidation_Base.malloc
malloc
Definition: TrigInDetValidation_Base.py:129
ExpatCoreParser::generic_parse
int generic_parse(XML_Parser p, const std::string &file_name)
Definition: ExpatCoreParser.cxx:263
PyPoolBrowser.node
node
Definition: PyPoolBrowser.py:131
ExpatCoreParserDebugger::debug
static bool debug()
Definition: ExpatCoreParser.cxx:32
ExpatCoreParser::get_document
std::unique_ptr< CoreParser::DOMNode > get_document()
Definition: ExpatCoreParser.cxx:151
ExpatCoreParser::start
static void start(void *, const char *el, const char **attr)
Definition: ExpatCoreParser.cxx:43
grepfile.sep
sep
Definition: grepfile.py:38
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
ExpatCoreParser::char_data
static void char_data(void *, const XML_Char *s, int len)
Definition: ExpatCoreParser.cxx:55
ExpatCoreParser::default_handler
static void default_handler(void *, const XML_Char *s, int len)
Definition: ExpatCoreParser.cxx:61
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:79
ExpatCoreParser::do_start
void do_start(const char *el, const char **attr)
Definition: ExpatCoreParser.cxx:163
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
a
TList * a
Definition: liststreamerinfos.cxx:10
SCT_ConditionsAlgorithms::CoveritySafe::getenv
std::string getenv(const std::string &variableName)
get an environment variable
Definition: SCT_ConditionsUtilities.cxx:17
ExpatCoreParser::parse
static std::unique_ptr< CoreParser::DOMNode > parse(const std::string &file_name)
Definition: ExpatCoreParser.cxx:557
ExpatCoreParser::generic_text_parse
int generic_text_parse(XML_Parser p, const std::string &text)
Definition: ExpatCoreParser.cxx:411
ExpatCoreParser::s_mutex
static std::mutex s_mutex
Definition: ExpatCoreParser.h:70
ExpatCoreParser::comment
static void comment(void *, const XML_Char *s)
Definition: ExpatCoreParser.cxx:67
makeTransCanvas.text
text
Definition: makeTransCanvas.py:11
ExpatCoreParser::register_external_entity
static void register_external_entity(const std::string &name, const std::string &file_name)
Definition: ExpatCoreParser.cxx:84
merge.status
status
Definition: merge.py:17
CoreParser::DOMNode::m_parent
DOMNode * m_parent
Definition: DOMNode.h:52
ExpatCoreParser::m_top
std::unique_ptr< CoreParser::DOMNode > m_top
Definition: ExpatCoreParser.h:66
node
Definition: memory_hooks-stdcmalloc.h:74