ATLAS Offline Software
Loading...
Searching...
No Matches
ExpatCoreParser.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 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 ExpatCoreParser& me = *reinterpret_cast<ExpatCoreParser*> (user_data);
43 me.do_start (el, attr);
44}
45
46void
47ExpatCoreParser::end (void* user_data, const char* el){
48 ExpatCoreParser& 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 ExpatCoreParser& 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 ExpatCoreParser& 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 ExpatCoreParser& 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 ExpatCoreParser& 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<CoreParser::DOMNode>
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
141void
142ExpatCoreParser::do_start (const char* el, const char** attr){
143 int i;
144 std::map <std::string, std::string> a;
145 if (!m_top){
146 m_top = std::make_unique<CoreParser::DOMNode> ();
147 m_last = m_top.get();
148 }
151 std::cout << "ExpatCoreParser::do_start> el=" << el << " top=" << m_top.get() << " last=" << m_last << " node=" << node << std::endl;
152 }
153 m_last = node;
154 for (i = 0; attr[i]; i += 2) {
155 const char* name = attr[i];
156 const char* value = attr[i+1];
157 node->m_attributes[name] = value;
158 }
159}
160
161void
162ExpatCoreParser::do_end (const char* el){
164 std::cout << "ExpatCoreParser::do_end> el=" << el << std::endl;
165 }
166 m_last = m_last->m_parent;
167}
168
169void
170ExpatCoreParser::do_char_data (const XML_Char* s, int len){
171 if (len == 0) return;
172 while ((len > 0) && (s[len-1] == '\n')) len--;
173 if (len == 0) return;
174 std::string temp (s, len);
176 std::cout << "ExpatCoreParser::do_char_data> [" << temp << "]" << std::endl;
177 }
178}
179
180void
181ExpatCoreParser::do_default_handler (const XML_Char* s, int len){
182 if (len == 0) return;
183 while ((len > 0) && (s[len-1] == '\n')) len--;
184 if (len == 0) return;
185 std::string temp (s, len);
187 std::cout << "ExpatCoreParser::do_default_handler> [" << temp << "]" << std::endl;
188 }
189}
190
191void
192ExpatCoreParser::do_comment (const XML_Char* s){
193 if (!m_top) {
194 m_top = std::make_unique<CoreParser::DOMNode> ();
195 m_last = m_top.get();
196 }
199 std::cout << "ExpatCoreParser::do_comment> s=" << s << " top=" << m_top.get() << " last=" << m_last << " node=" << node << std::endl;
200 }
201 // Node is owned by m_last.
202 // cppcheck-suppress memleak
203 node = nullptr;
204}
205
206int
207ExpatCoreParser::generic_parse (XML_Parser p, const std::string& file_name){
208 FILE* docfd;
210 std::cout << "ExpatCoreParser::generic_parse> file_name=" << file_name << " prefix=" << m_prefix << std::endl;
211 }
212
213 std::string temp_name = file_name;
214 docfd = fopen (temp_name.c_str (), "r");
215 if (!docfd){
216 temp_name = m_prefix + "/" + file_name;
217 docfd = fopen (temp_name.c_str (), "r");
218 }
219
220 if (docfd == 0){
221 const char* xmlpathenv = ::getenv ("XMLPATH");
222 if (xmlpathenv == 0) return (0);
223 std::string xmlpath = xmlpathenv;
224 std::string::size_type pos = 0;
225 while (pos != std::string::npos){
226 std::string::size_type sep = xmlpath.find (":", pos);
227 if (sep == std::string::npos){
228 temp_name = xmlpath.substr (pos);
229 pos = std::string::npos;
230 } else {
231 temp_name = xmlpath.substr (pos, sep - pos);
232 pos = sep + 1;
233 }
234 if (temp_name.empty()) continue;
235 std::string last_temp_name = temp_name;
236 temp_name += "/";
237 temp_name += file_name;
239 std::cout << "ExpatCoreParser::generic_parse> file_name=" << file_name
240 << " xmlpath=" << xmlpath
241 << " temp_name=" << temp_name
242 << std::endl;
243 }
244
245 docfd = fopen (temp_name.c_str (), "r");
246 if (docfd != 0) break;
247 // Test whether prefix is a relative path and if so use it
248 if (m_prefix != "" && '/' != m_prefix[0]) {
249 temp_name = std::move(last_temp_name);
250 temp_name += "/";
251 temp_name += m_prefix;
252 temp_name += "/";
253 temp_name += file_name;
255 std::cout << "ExpatCoreParser::generic_parse> file_name=" << file_name
256 << " xmlpath=" << xmlpath
257 << " temp_name=" << temp_name
258 << std::endl;
259 }
260 docfd = fopen (temp_name.c_str (), "r");
261 if (docfd != 0) break;
262 }
263 }
264 }
265
266 if (docfd == 0){
267 return (0);
268 }
269 int result = 1;
270 XML_SetParamEntityParsing (p, XML_PARAM_ENTITY_PARSING_ALWAYS);
271 XML_SetElementHandler (p, start, end);
272 XML_SetCharacterDataHandler (p, char_data);
273 XML_SetExternalEntityRefHandler (p, external_entity);
274 XML_SetCommentHandler (p, comment);
275 XML_SetUserData (p, this);
277 std::cout << "ExpatCoreParser::generic_parse> starting" << std::endl;
278 }
279 for (;;) {
280 int items;
281 char* buff = (char*) XML_GetBuffer (p, BUFFSIZE + 1);
282 items = fread (buff, 1, BUFFSIZE, docfd);
283 if (ferror (docfd)){
284 std::cout << "Read error" << std::endl;
285 result = 0;
286 break;
287 }
288 int done = feof (docfd);
289 buff[items] = 0;
290 if (XML_ParseBuffer (p, BUFFSIZE, done) == XML_STATUS_ERROR) {
291 if (!done) {
292 std::cout << "ExpatCoreParser::Parse error at line " << XML_GetCurrentLineNumber(p)
293 << " of file " << file_name
294 << ":" << std::endl
295 << XML_ErrorString (XML_GetErrorCode(p)) << std::endl;
296 result = 0;
297 }
298 /* handle parse error */
299 }
300 if (done) break;
301 }
302 fclose (docfd);
303 return (result);
304}
305
306int
307ExpatCoreParser::generic_text_parse (XML_Parser p, const std::string& text){
309 std::cout << "ExpatCoreParser::generic_text_parse> " << std::endl;
310 }
311 int result = 1;
312 XML_SetParamEntityParsing (p, XML_PARAM_ENTITY_PARSING_ALWAYS);
313 XML_SetElementHandler (p, start, end);
314 XML_SetCharacterDataHandler (p, char_data);
315 XML_SetExternalEntityRefHandler (p, external_entity);
316 XML_SetCommentHandler (p, comment);
317 XML_SetUserData (p, this);
319 std::cout << "ExpatCoreParser::generic_text_parse> starting" << std::endl;
320 }
321 {
322 char* buff = (char*) XML_GetBuffer (p, text.size() + 1);
323 strcpy (buff, text.c_str ());
324 int done = 1;
325 if (XML_ParseBuffer (p, text.size(), done) == XML_STATUS_ERROR) {
326 std::cout << "ExpatCoreParser::Parse error at line " << XML_GetCurrentLineNumber(p)
327 << ":" << std::endl
328 << XML_ErrorString (XML_GetErrorCode(p)) << std::endl;
329 result = 0;
330 /* handle parse error */
331 }
332 }
333 return (result);
334}
335
336int
338 const XML_Char* context, const XML_Char* systemId){
339 std::string context_str;
340 if (context == 0) context_str = "none";
341 else context_str = context;
342 bool done = false;
343 int status = 0;
344 if (context != 0) {
345 std::string replacement = find_text_entity (context_str);
346 if (replacement != "") {
348 std::cout << "ExpatCoreParser::do_external_entity> "
349 << " context=[" << context_str << "]"
350 << " replacement=[" << replacement << "]"
351 << std::endl;
352 }
353 XML_Parser p = XML_ExternalEntityParserCreate (parser, context, NULL);
354 status = generic_text_parse (p, replacement);
355 XML_ParserFree (p);
356 done = true;
357 }
358 }
359 if (!done) {
360 std::string replacement = find_external_entity (context_str);
361 if (replacement == "NULL") {
362 return (1);
363 }
364 if (replacement != "") {
365 systemId = replacement.c_str ();
366 }
367
369 std::cout << "ExpatCoreParser::do_external_entity> "
370 << " context=[" << context_str << "]"
371 << " systemId=[" << systemId << "]"
372 << " replacement=[" << replacement << "]"
373 << std::endl;
374 }
375 XML_Parser p = XML_ExternalEntityParserCreate (parser, context, NULL);
376 status = generic_parse (p, systemId);
377 XML_ParserFree (p);
378 }
379 return (status);
380}
381
382const std::string&
383ExpatCoreParser::find_external_entity (const std::string& name){
384 lock_t lock (s_mutex);
385 ExternalEntityMap::const_iterator it = s_entities.find (name);
386 if (it == s_entities.end ()) {
387 static const std::string empty;
388 return (empty);
389 } else {
390 return ((*it).second);
391 }
392}
393
394const std::string&
395ExpatCoreParser::find_text_entity (const std::string& name){
396 lock_t lock (s_mutex);
397 ExternalEntityMap::const_iterator it = s_text_entities.find (name);
398 if (it == s_text_entities.end ()) {
399 static const std::string empty;
400 return (empty);
401 } else {
402 return ((*it).second);
403 }
404}
405
406std::unique_ptr<CoreParser::DOMNode>
407ExpatCoreParser::parse (const std::string& file_name){
408 std::string name = file_name;
409 std::string::size_type pos = file_name.rfind ('/');
410 std::string prefix;
411 if (pos != std::string::npos){
412 prefix = file_name.substr (0, pos);
413 name = file_name.substr (pos + 1);
414 }
415 ExpatCoreParser me (prefix);
416 XML_Parser p = XML_ParserCreate (NULL);
417 if (!p) {
418 std::cout << "ExpatCoreParser::Couldn't allocate memory for parser" << std::endl;
419 std::abort();
420 }
421 int result = me.generic_parse (p, name);
422 XML_ParserFree (p);
423 if (result == 0) return nullptr;
424 return me.get_document ();
425}
426
#define BUFFSIZE
static Double_t a
static const Attributes_t empty
int generic_text_parse(XML_Parser p, const std::string &text)
std::unique_ptr< CoreParser::DOMNode > get_document()
void do_start(const char *el, const char **attr)
std::unique_ptr< CoreParser::DOMNode > m_top
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
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)
void do_end(const char *el)
static void default_handler(void *, const XML_Char *s, int len)
CoreParser::DOMNode * m_last
void do_comment(const XML_Char *s)
static std::unique_ptr< CoreParser::DOMNode > parse(const std::string &file_name)
void do_char_data(const XML_Char *s, int len)
static const std::string & find_external_entity(const std::string &name)
static void register_external_entity(const std::string &name, const std::string &file_name)
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
Definition node.h:24
std::string base
Definition hcg.cxx:81