ATLAS Offline Software
Loading...
Searching...
No Matches
ExpatCoreParser.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include "ExpatCoreParser.h"
8
9#include <cstdio>
10#include <cstdlib>
11#include <cstring>
12#include <expat.h>
13
14#include <string>
15#include <vector>
16#include <iostream>
17#include <map>
18
19
20
22ExpatCoreParser::ExternalEntityMap ExpatCoreParser::s_entities;
23ExpatCoreParser::ExternalEntityMap ExpatCoreParser::s_text_entities;
24
26public:
27 static bool get_debug_state() {
28 return ::getenv ("XMLDEBUG") != 0;
29 }
30 static bool debug () {
31 static const bool debug_state = get_debug_state();
32 return debug_state;
33 }
34};
35
36
37
38#define BUFFSIZE 1000
39
40void
41ExpatCoreParser::start (void* user_data, const char* el, const char** attr){
42 auto& me = *reinterpret_cast<ExpatCoreParser*> (user_data);
43 me.do_start (el, attr);
44}
45
46void
47ExpatCoreParser::end (void* user_data, const char* el){
48 auto& me = *reinterpret_cast<ExpatCoreParser*> (user_data);
49 me.do_end (el);
50}
51
52void
53ExpatCoreParser::char_data (void* user_data, const XML_Char* s, int len){
54 auto& me = *reinterpret_cast<ExpatCoreParser*> (user_data);
55 me.do_char_data (s, len);
56}
57
58void
59ExpatCoreParser::default_handler (void* user_data, const XML_Char* s, int len){
60 auto& me = *reinterpret_cast<ExpatCoreParser*> (user_data);
61 me.do_default_handler (s, len);
62}
63
64void
65ExpatCoreParser::comment (void* user_data, const XML_Char* s){
66 auto& me = *reinterpret_cast<ExpatCoreParser*> (user_data);
67 me.do_comment (s);
68}
69
70int
72 const XML_Char* context,
73 const XML_Char* /*base*/,
74 const XML_Char* systemId,
75 const XML_Char* /*publicId*/){
76 void* user_data = XML_GetUserData (parser);
77 auto& me = *reinterpret_cast<ExpatCoreParser*> (user_data);
78 return (me.do_external_entity (parser, context, systemId));
79}
80
81void
82ExpatCoreParser::register_external_entity (const std::string& name, const std::string& file_name) {
84 std::cout << "ExpatCoreParser::register_external_entity> name=" << name
85 << " file_name=" << file_name << std::endl;
86 }
87 lock_t lock (s_mutex);
88 s_entities[name] = file_name;
89}
90
91void
92ExpatCoreParser::register_text_entity (const std::string& name, const std::string& text) {
94 std::cout << "ExpatCoreParser::register_text_entity> name=" << name
95 << std::endl;
96 }
97 lock_t lock (s_mutex);
98 s_text_entities[name] = text;
99}
100
101void
102ExpatCoreParser::entity (void* /*userData*/,
103 const XML_Char* entityName,
104 int is_parameter_entity,
105 const XML_Char* value,
106 int value_length,
107 const XML_Char* base,
108 const XML_Char* systemId,
109 const XML_Char* publicId,
110 const XML_Char* /*notationName*/){
111 if (!base) base = "none";
112 if (!systemId) systemId = "none";
113 if (!publicId) publicId = "none";
114 std::string temp = "none";
115 if (value) {
116 temp.assign (value, strnlen(value, value_length));
117 }
118
120 std::cout << "ExpatCoreParser::entity[" << 0 << "]> " << entityName;
121 std::cout << " is_parameter=" << is_parameter_entity;
122 std::cout << " value=[" << temp << "]";
123 std::cout << " base=[" << base << "]";
124 std::cout << " systemId=[" << systemId << "]";
125 std::cout << " publicId=[" << publicId << "]";
126 std::cout << std::endl;
127 }
128}
129
130std::unique_ptr<XMLCoreNode>
132 return std::move(m_top);
133}
134
135ExpatCoreParser::ExpatCoreParser (const std::string& prefix)
136 : m_top (nullptr),
137 m_last (nullptr),
138 m_prefix (prefix){
139}
140
142ExpatCoreParser::add_node (std::unique_ptr<XMLCoreNode> node)
143{
144 if (!m_top){
145 m_top = std::make_unique<XMLCoreNode> (XMLCoreNode::DOCUMENT_NODE);
146 m_last = m_top.get();
147 }
148
149 return m_last->add_child (std::move(node));
150}
151
152void
153ExpatCoreParser::do_start (const char* el, const char** attr){
154 auto node = std::make_unique<XMLCoreNode> (XMLCoreNode::ELEMENT_NODE, el);
155
157 std::cout << "ExpatCoreParser::do_start> el=" << el << " top=" << m_top.get() << " last=" << m_last << " node=" << node << std::endl;
158 }
159 for (int i = 0; attr[i]; i += 2) {
160 const char* name = attr[i];
161 const char* value = attr[i+1];
162 node->set_attrib (name, value);
163 }
164
165 m_last = add_node (std::move(node));
166}
167
168void
169ExpatCoreParser::do_end (const char* el){
171 std::cout << "ExpatCoreParser::do_end> el=" << el << std::endl;
172 }
173 m_last = m_last->get_parent();
174}
175
176void
177ExpatCoreParser::do_char_data (const XML_Char* s, int len){
178 if (len == 0) return;
179 while ((len > 0) && (s[len-1] == '\n')) len--;
180 if (len == 0) return;
181 std::string temp (s, len);
183 std::cout << "ExpatCoreParser::do_char_data> [" << temp << "]" << std::endl;
184 }
185
186 auto node = std::make_unique<XMLCoreNode> (XMLCoreNode::TEXT_NODE, "", temp);
187 add_node (std::move(node));
188}
189
190void
191ExpatCoreParser::do_default_handler (const XML_Char* s, int len){
192 if (len == 0) return;
193 while ((len > 0) && (s[len-1] == '\n')) len--;
194 if (len == 0) return;
195 std::string temp (s, len);
197 std::cout << "ExpatCoreParser::do_default_handler> [" << temp << "]" << std::endl;
198 }
199}
200
201void
202ExpatCoreParser::do_comment (const XML_Char* s){
203 auto node = std::make_unique<XMLCoreNode> (XMLCoreNode::COMMENT_NODE, "", s);
205 std::cout << "ExpatCoreParser::do_comment> s=" << s << " top=" << m_top.get() << " last=" << m_last << " node=" << node << std::endl;
206 }
207
208 add_node (std::move(node));
209}
210
211int
212ExpatCoreParser::generic_parse (XML_Parser p, const std::string& file_name){
213 FILE* docfd;
215 std::cout << "ExpatCoreParser::generic_parse> file_name=" << file_name << " prefix=" << m_prefix << std::endl;
216 }
217
218 std::string temp_name = file_name;
219 docfd = fopen (temp_name.c_str (), "r");
220 if (!docfd){
221 temp_name = m_prefix + "/" + file_name;
222 docfd = fopen (temp_name.c_str (), "r");
223 }
224
225 if (docfd == 0){
226 const char* xmlpathenv = ::getenv ("XMLPATH");
227 if (xmlpathenv == 0) return (0);
228 std::string xmlpath = xmlpathenv;
229 std::string::size_type pos = 0;
230 while (pos != std::string::npos){
231 std::string::size_type sep = xmlpath.find (":", pos);
232 if (sep == std::string::npos){
233 temp_name = xmlpath.substr (pos);
234 pos = std::string::npos;
235 } else {
236 temp_name = xmlpath.substr (pos, sep - pos);
237 pos = sep + 1;
238 }
239 if (temp_name.empty()) continue;
240 std::string last_temp_name = temp_name;
241 temp_name += "/";
242 temp_name += file_name;
244 std::cout << "ExpatCoreParser::generic_parse> file_name=" << file_name
245 << " xmlpath=" << xmlpath
246 << " temp_name=" << temp_name
247 << std::endl;
248 }
249
250 docfd = fopen (temp_name.c_str (), "r");
251 if (docfd != 0) break;
252 // Test whether prefix is a relative path and if so use it
253 if (m_prefix != "" && '/' != m_prefix[0]) {
254 temp_name = std::move(last_temp_name);
255 temp_name += "/";
256 temp_name += m_prefix;
257 temp_name += "/";
258 temp_name += file_name;
260 std::cout << "ExpatCoreParser::generic_parse> file_name=" << file_name
261 << " xmlpath=" << xmlpath
262 << " temp_name=" << temp_name
263 << std::endl;
264 }
265 docfd = fopen (temp_name.c_str (), "r");
266 if (docfd != 0) break;
267 }
268 }
269 }
270
271 if (docfd == 0){
272 return (0);
273 }
274 int result = 1;
275 XML_SetParamEntityParsing (p, XML_PARAM_ENTITY_PARSING_ALWAYS);
276 XML_SetElementHandler (p, start, end);
277 XML_SetCharacterDataHandler (p, char_data);
278 XML_SetExternalEntityRefHandler (p, external_entity);
279 XML_SetCommentHandler (p, comment);
280 XML_SetUserData (p, this);
282 std::cout << "ExpatCoreParser::generic_parse> starting" << std::endl;
283 }
284 for (;;) {
285 int items;
286 char* buff = (char*) XML_GetBuffer (p, BUFFSIZE + 1);
287 items = fread (buff, 1, BUFFSIZE, docfd);
288 if (ferror (docfd)){
289 std::cout << "Read error" << std::endl;
290 result = 0;
291 break;
292 }
293 int done = feof (docfd);
294 buff[items] = 0;
295 if (XML_ParseBuffer (p, BUFFSIZE, done) == XML_STATUS_ERROR) {
296 if (!done) {
297 std::cout << "ExpatCoreParser::Parse error at line " << XML_GetCurrentLineNumber(p)
298 << " of file " << file_name
299 << ":" << std::endl
300 << XML_ErrorString (XML_GetErrorCode(p)) << std::endl;
301 result = 0;
302 }
303 /* handle parse error */
304 }
305 if (done) break;
306 }
307 fclose (docfd);
308 return (result);
309}
310
311int
312ExpatCoreParser::generic_text_parse (XML_Parser p, const std::string& text){
314 std::cout << "ExpatCoreParser::generic_text_parse> " << std::endl;
315 }
316 int result = 1;
317 XML_SetParamEntityParsing (p, XML_PARAM_ENTITY_PARSING_ALWAYS);
318 XML_SetElementHandler (p, start, end);
319 XML_SetCharacterDataHandler (p, char_data);
320 XML_SetExternalEntityRefHandler (p, external_entity);
321 XML_SetCommentHandler (p, comment);
322 XML_SetUserData (p, this);
324 std::cout << "ExpatCoreParser::generic_text_parse> starting" << std::endl;
325 }
326 {
327 char* buff = (char*) XML_GetBuffer (p, text.size() + 1);
328 strcpy (buff, text.c_str ());
329 int done = 1;
330 if (XML_ParseBuffer (p, text.size(), done) == XML_STATUS_ERROR) {
331 std::cout << "ExpatCoreParser::Parse error at line " << XML_GetCurrentLineNumber(p)
332 << ":" << std::endl
333 << XML_ErrorString (XML_GetErrorCode(p)) << std::endl;
334 result = 0;
335 /* handle parse error */
336 }
337 }
338 return (result);
339}
340
341int
343 const XML_Char* context,
344 const XML_Char* systemId){
345 std::string context_str;
346 if (context == 0) context_str = "none";
347 else context_str = context;
348 bool done = false;
349 int status = 0;
350 if (context != 0) {
351 std::string replacement = find_text_entity (context_str);
352 if (replacement != "") {
354 std::cout << "ExpatCoreParser::do_external_entity> "
355 << " context=[" << context_str << "]"
356 << " replacement=[" << replacement << "]"
357 << std::endl;
358 }
359 XML_Parser p = XML_ExternalEntityParserCreate (parser, context, NULL);
360 status = generic_text_parse (p, replacement);
361 XML_ParserFree (p);
362 done = true;
363 }
364 }
365 if (!done) {
366 std::string replacement = find_external_entity (context_str);
367 if (replacement == "NULL") {
368 return (1);
369 }
370 if (replacement != "") {
371 systemId = replacement.c_str ();
372 }
373
375 std::cout << "ExpatCoreParser::do_external_entity> "
376 << " context=[" << context_str << "]"
377 << " systemId=[" << systemId << "]"
378 << " replacement=[" << replacement << "]"
379 << std::endl;
380 }
381 XML_Parser p = XML_ExternalEntityParserCreate (parser, context, NULL);
382 status = generic_parse (p, systemId);
383 XML_ParserFree (p);
384 }
385 return (status);
386}
387
388const std::string&
389ExpatCoreParser::find_external_entity (const std::string& name){
390 lock_t lock (s_mutex);
391 ExternalEntityMap::const_iterator it = s_entities.find (name);
392 if (it == s_entities.end ()) {
393 static const std::string empty;
394 return (empty);
395 } else {
396 return ((*it).second);
397 }
398}
399
400const std::string&
401ExpatCoreParser::find_text_entity (const std::string& name){
402 lock_t lock (s_mutex);
403 ExternalEntityMap::const_iterator it = s_text_entities.find (name);
404 if (it == s_text_entities.end ()) {
405 static const std::string empty;
406 return (empty);
407 } else {
408 return ((*it).second);
409 }
410}
411
412std::unique_ptr<XMLCoreNode>
413ExpatCoreParser::parse (const std::string& file_name){
414 std::string name = file_name;
415 std::string::size_type pos = file_name.rfind ('/');
416 std::string prefix;
417 if (pos != std::string::npos){
418 prefix = file_name.substr (0, pos);
419 name = file_name.substr (pos + 1);
420 }
421 ExpatCoreParser me (prefix);
422 XML_Parser p = XML_ParserCreate (NULL);
423 if (!p) {
424 std::cout << "ExpatCoreParser::Couldn't allocate memory for parser" << std::endl;
425 std::abort();
426 }
427 int result = me.generic_parse (p, name);
428 XML_ParserFree (p);
429 if (result == 0) return nullptr;
430 return me.get_document ();
431}
432
433
434std::unique_ptr<XMLCoreNode>
435ExpatCoreParser::parse_string (const std::string& text){
436 ExpatCoreParser me ("");
437 XML_Parser p = XML_ParserCreate (NULL);
438 if (!p) {
439 std::cout << "ExpatCoreParser::Couldn't allocate memory for parser" << std::endl;
440 std::abort();
441 }
442 int result = me.generic_text_parse (p, text);
443 XML_ParserFree (p);
444 if (result == 0) return nullptr;
445 return me.get_document ();
446}
447
#define BUFFSIZE
static const Attributes_t empty
int generic_text_parse(XML_Parser p, const std::string &text)
void do_start(const char *el, const char **attr)
static void register_text_entity(const std::string &name, const std::string &text)
void do_default_handler(const XML_Char *s, int len)
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 *)
std::string m_prefix
XMLCoreNode * add_node(std::unique_ptr< XMLCoreNode > node)
static void char_data(void *, const XML_Char *s, int len)
static int external_entity(XML_Parser parser, const XML_Char *context, const XML_Char *, const XML_Char *systemId, const XML_Char *)
std::lock_guard< std::mutex > lock_t
int generic_parse(XML_Parser p, const std::string &file_name)
static void start(void *, const char *el, const char **attr)
static std::unique_ptr< XMLCoreNode > parse(const std::string &file_name)
void do_end(const char *el)
static void default_handler(void *, const XML_Char *s, int len)
std::unique_ptr< XMLCoreNode > get_document()
void do_comment(const XML_Char *s)
void do_char_data(const XML_Char *s, int len)
XMLCoreNode * m_last
static const std::string & find_external_entity(const std::string &name)
static std::unique_ptr< XMLCoreNode > parse_string(const std::string &text)
static void register_external_entity(const std::string &name, const std::string &file_name)
std::unique_ptr< XMLCoreNode > m_top
static const std::string & find_text_entity(const std::string &name)
static void comment(void *, const XML_Char *s)
std::map< std::string, std::string > ExternalEntityMap
int do_external_entity(XML_Parser parser, const XML_Char *context, const XML_Char *systemId)
static void end(void *, const char *el)
ExpatCoreParser(const std::string &prefix)
static std::mutex s_mutex
Simple DOM-like node structure to hold the result of XML parsing.
Definition XMLCoreNode.h:45
Definition node.h:24
std::string base
Definition hcg.cxx:81