EvtGen 2.2.0
Monte Carlo generator of particle decays, in particular the weak decays of heavy flavour particles such as B mesons.
Loading...
Searching...
No Matches
EvtParserXml.cpp
Go to the documentation of this file.
1
2/***********************************************************************
3* Copyright 1998-2020 CERN for the benefit of the EvtGen authors *
4* *
5* This file is part of EvtGen. *
6* *
7* EvtGen is free software: you can redistribute it and/or modify *
8* it under the terms of the GNU General Public License as published by *
9* the Free Software Foundation, either version 3 of the License, or *
10* (at your option) any later version. *
11* *
12* EvtGen is distributed in the hope that it will be useful, *
13* but WITHOUT ANY WARRANTY; without even the implied warranty of *
14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15* GNU General Public License for more details. *
16* *
17* You should have received a copy of the GNU General Public License *
18* along with EvtGen. If not, see <https://www.gnu.org/licenses/>. *
19***********************************************************************/
20
22
24
25#include <fstream>
26#include <sstream>
27#include <stdlib.h>
28#include <string.h>
29#include <vector>
30using namespace std;
31
32bool EvtParserXml::open( std::string filename )
33{
34 if ( !expandEnvVars( filename ) ) {
35 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
36 << "Error while expanding environment variables in file name '"
37 << filename.c_str() << "'" << endl;
38 return false;
39 }
40
41 m_fin.open( filename.c_str() );
42 if ( !m_fin ) {
43 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
44 << "Could not open file '" << filename.c_str() << "'" << endl;
45 return false;
46 }
47
48 return true;
49}
50
52{
53 m_fin.close();
54 return true;
55}
56
58{
59 if ( !processTagTree() ) {
60 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
61 << "Unexpected end tag " << m_tagTitle << " found near line "
62 << m_lineNo << endl;
63 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
64 << "Will terminate execution!" << endl;
65 return false;
66 } //first process the previous tag to find out where we are in the tag tree
67
68 while ( m_line.find( "<" ) ==
69 std::string::npos ) { //add lines until we find start of a tag
70 std::string addLine;
71 if ( !std::getline( m_fin, addLine ) )
72 return false;
73 m_lineNo++;
74 m_line += " ";
75 m_line += addLine;
76 }
77
78 unsigned int startTag;
79 unsigned int endTag;
80 unsigned int endTagTitle;
81
82 startTag = m_line.find( "<" );
83
84 if ( m_line[startTag + 1] ==
85 '?' ) { //XML header tag - ignore then read the next tag
86 while ( m_line.find( "?>", startTag ) == std::string::npos ) {
87 std::string addLine;
88 if ( !std::getline( m_fin, addLine ) )
89 return false;
90 m_lineNo++;
91 m_line += " ";
92 m_line += addLine;
93 }
94 endTag = m_line.find( "?>", startTag );
95 m_line = m_line.substr( endTag + 2 );
96 return readNextTag();
97 } else if ( m_line[startTag + 1] ==
98 '!' ) { //XML comment tag - ignore then read the next tag
99 while ( m_line.find( "-->", startTag ) == std::string::npos ) {
100 std::string addLine;
101 if ( !std::getline( m_fin, addLine ) )
102 return false;
103 m_lineNo++;
104 m_line += " ";
105 m_line += addLine;
106 }
107 endTag = m_line.find( "-->", startTag );
108 m_line = m_line.substr( endTag + 3 );
109 m_tagTitle = "";
110 m_tag = "";
111 return readNextTag();
112 } else { //parsable
113
114 while ( m_line.find( ">", startTag ) ==
115 std::string::npos ) { //find end of a tag
116 std::string addLine;
117 if ( !std::getline( m_fin, addLine ) )
118 return false;
119 m_lineNo++;
120 m_line += " ";
121 m_line += addLine;
122 }
123 endTag = m_line.find( ">", startTag );
124 m_inLineTag = false;
125 if ( m_line.find( "/>", startTag ) < endTag ) {
126 endTag--;
127 m_inLineTag = true;
128 }
129
130 if ( m_line.find( " ", startTag ) != std::string::npos &&
131 m_line.find( " ", startTag ) <
132 endTag ) { //find end of the first word in the tag
133 endTagTitle = m_line.find( " ", startTag );
134 } else {
135 endTagTitle = endTag;
136 }
137
138 m_tagTitle = m_line.substr( startTag + 1, endTagTitle - startTag - 1 );
139 m_tag = m_line.substr( startTag + 1, endTag - startTag - 1 );
140
141 //now we have the tag lets remove it from the line
142 if ( m_inLineTag ) {
143 m_line = m_line.substr( endTag + 2 );
144 } else {
145 m_line = m_line.substr( endTag + 1 );
146 }
147 return true;
148 }
149}
150
152{
153 if ( m_tagTree.empty() )
154 return "";
155 else
156 return m_tagTree.back();
157}
158
159std::string EvtParserXml::readAttribute( std::string attribute,
160 std::string defaultValue )
161{
162 std::string whitespace = " \t\n\v\f\r";
163 for ( unsigned int i = 0; i < whitespace.size(); i++ ) {
164 //find any whitespace followed by the attribute name followed by an '='
165 std::string attName = whitespace[i] + attribute + "=";
166 if ( m_tag.find( attName ) != std::string::npos ) {
167 int startAttri = m_tag.find( attName );
168 int startQuote = m_tag.find( "\"", startAttri + 1 );
169 int endQuote = m_tag.find( "\"", startQuote + 1 );
170 return m_tag.substr( startQuote + 1, endQuote - startQuote - 1 );
171 }
172 }
173 return defaultValue;
174}
175
176bool EvtParserXml::readAttributeBool( std::string attribute, bool defaultValue )
177{
178 std::string valStr = readAttribute( attribute );
179 if ( !defaultValue )
180 return ( valStr == "true" || valStr == "1" || valStr == "on" ||
181 valStr == "yes" );
182 else
183 return ( valStr != "false" && valStr != "0" && valStr != "off" &&
184 valStr != "no" );
185}
186
187int EvtParserXml::readAttributeInt( std::string attribute, int defaultValue )
188{
189 std::string valStr = readAttribute( attribute );
190 if ( valStr == "" )
191 return defaultValue;
192 std::istringstream valStream( valStr );
193 int retVal;
194 valStream >> retVal;
195 return retVal;
196}
197
198double EvtParserXml::readAttributeDouble( std::string attribute,
199 double defaultValue )
200{
201 std::string valStr = readAttribute( attribute );
202 if ( valStr == "" )
203 return defaultValue;
204 std::istringstream valStream( valStr );
205 double retVal;
206 valStream >> retVal;
207 return retVal;
208}
209
211{
212 if ( m_tagTitle == "" )
213 return true;
214 if ( m_tagTitle[0] == '/' ) {
215 if ( m_tagTitle.substr( 1 ) == m_tagTree.back() ) {
216 m_tagTree.pop_back();
217 } else {
218 return false;
219 }
220 } else if ( !m_inLineTag ) {
221 m_tagTree.push_back( m_tagTitle );
222 }
223 return true;
224}
225
226bool EvtParserXml::expandEnvVars( std::string& str )
227{
228 while ( str.find( '$' ) != std::string::npos ) {
229 size_t varStart = str.find( '$' );
230 size_t varNameLength;
231 std::string varName;
232
233 //if this is the last character then just remove the $
234 if ( varStart == str.length() - 1 ) {
235 str.erase( varStart );
236 return true;
237 }
238
239 if ( str[varStart + 1] == '{' ) {
240 //deal with environment variables in {}s
241 size_t braceStart = varStart + 1;
242 size_t braceEnd = str.find( '}', braceStart );
243
244 if ( braceEnd == std::string::npos ) {
245 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
246 << "Incomplete environment variable found in text: " << str
247 << endl;
248 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
249 << "Will terminate execution!" << endl;
250 return false;
251 }
252
253 varName = str.substr( braceStart + 1, braceEnd - braceStart - 1 );
254 varNameLength = braceEnd - varStart;
255
256 } else {
257 //deal with everything else
258 varNameLength = 0;
259
260 while ( varNameLength + varStart + 1 < str.length() &&
261 isAlphaNum( str[varStart + varNameLength + 1] ) ) {
262 ++varNameLength;
263 }
264
265 varName = str.substr( varStart + 1, varNameLength );
266 }
267
268 char* envVar = getenv( varName.c_str() );
269
270 if ( envVar )
271 str.replace( varStart, varNameLength + 1, envVar );
272 else {
273 EvtGenReport( EVTGEN_WARNING, "EvtGen" )
274 << "Undefined environment variable found in text: " << varName
275 << endl;
276 str.replace( varStart, varNameLength + 1, "" );
277 }
278 }
279 return true;
280}
281
283{
284 if ( c >= '0' && c <= '9' )
285 return true;
286 if ( c >= 'A' && c <= 'Z' )
287 return true;
288 if ( c >= 'a' && c <= 'z' )
289 return true;
290 if ( c == '_' )
291 return true;
292 return false;
293}
std::ostream & EvtGenReport(EvtGenSeverity severity, const char *facility=nullptr)
Definition EvtReport.cpp:32
@ EVTGEN_WARNING
Definition EvtReport.hh:50
@ EVTGEN_ERROR
Definition EvtReport.hh:49
std::string readAttribute(std::string attribute, std::string defaultValue="")
bool processTagTree()
bool open(std::string filename)
bool isAlphaNum(char c)
double readAttributeDouble(std::string attribute, double defaultValue=-1.)
bool readAttributeBool(std::string attribute, bool defaultValue=false)
std::string m_line
std::string m_tag
std::string getParentTagTitle()
std::string m_tagTitle
std::vector< std::string > m_tagTree
int readAttributeInt(std::string attribute, int defaultValue=-1)
bool expandEnvVars(std::string &str)
std::ifstream m_fin