Line data Source code
1 : //--------------------------------------------------------------------------
2 : //
3 : // Environment:
4 : // This software is part of the EvtGen package developed jointly
5 : // for the BaBar and CLEO collaborations. If you use all or part
6 : // of it, please give an appropriate acknowledgement.
7 : //
8 : // Copyright Information: See EvtGen/COPYRIGHT
9 : // Copyright (C) 1998 Caltech, UCSB
10 : //
11 : // Module: EvtParserXml.cc
12 : //
13 : // Description: Reading the decay XML file.
14 : //
15 : // Modification history:
16 : //
17 : // DCC 24 October, 2011 Module created
18 : //
19 : //------------------------------------------------------------------------
20 : //
21 : #include "EvtGenBase/EvtPatches.hh"
22 : #include "EvtGenBase/EvtPatches.hh"
23 : #include <stdlib.h>
24 : #include <fstream>
25 : #include <sstream>
26 : #include <string.h>
27 : #include <vector>
28 : #include "EvtGenBase/EvtParserXml.hh"
29 : #include "EvtGenBase/EvtReport.hh"
30 : using namespace std;
31 :
32 0 : EvtParserXml::EvtParserXml(){
33 0 : _line = "";
34 0 : _lineNo=0;
35 0 : _tag = "";
36 0 : _tagTitle = "";
37 0 : }
38 :
39 0 : EvtParserXml::~EvtParserXml(){
40 :
41 :
42 0 : }
43 :
44 :
45 : bool EvtParserXml::open(std::string filename){
46 :
47 0 : if(!expandEnvVars(filename)) {
48 0 : report(Severity::Error,"EvtGen") << "Error while expanding environment variables in file name '"<<filename.c_str()<<"'"<<endl;
49 0 : return false;
50 : }
51 :
52 0 : _fin.open(filename.c_str());
53 0 : if (!_fin) {
54 0 : report(Severity::Error,"EvtGen") << "Could not open file '"<<filename.c_str()<<"'"<<endl;
55 0 : return false;
56 : }
57 :
58 0 : return true;
59 :
60 0 : }
61 :
62 : bool EvtParserXml::close() {
63 0 : _fin.close();
64 0 : return true;
65 : }
66 :
67 : bool EvtParserXml::readNextTag() {
68 0 : if(!processTagTree()) {
69 0 : report(Severity::Error,"EvtGen")
70 0 : << "Unexpected end tag "<<_tagTitle<<" found near line "<<_lineNo<<endl;
71 0 : report(Severity::Error,"EvtGen")
72 0 : << "Will terminate execution!"<<endl;
73 0 : return false;
74 : }//first process the previous tag to find out where we are in the tag tree
75 :
76 0 : while(_line.find("<") == std::string::npos) {//add lines until we find start of a tag
77 0 : std::string addLine;
78 0 : if(!std::getline(_fin, addLine)) return false;
79 0 : _lineNo++;
80 0 : _line += " ";
81 0 : _line += addLine;
82 0 : }
83 :
84 : unsigned int startTag;
85 : unsigned int endTag;
86 : unsigned int endTagTitle;
87 :
88 0 : startTag = _line.find("<");
89 :
90 0 : if(_line[startTag+1] =='?') { //XML header tag - ignore then read the next tag
91 0 : while(_line.find("?>", startTag) == std::string::npos) {
92 0 : std::string addLine;
93 0 : if(!std::getline(_fin, addLine)) return false;
94 0 : _lineNo++;
95 0 : _line += " ";
96 0 : _line += addLine;
97 0 : }
98 0 : endTag = _line.find("?>", startTag);
99 0 : _line = _line.substr(endTag + 2);
100 0 : return readNextTag();
101 0 : } else if(_line[startTag+1] == '!') { //XML comment tag - ignore then read the next tag
102 0 : while(_line.find("-->", startTag) == std::string::npos) {
103 0 : std::string addLine;
104 0 : if(!std::getline(_fin, addLine)) return false;
105 0 : _lineNo++;
106 0 : _line += " ";
107 0 : _line += addLine;
108 0 : }
109 0 : endTag = _line.find("-->", startTag);
110 0 : _line = _line.substr(endTag + 3);
111 0 : _tagTitle = "";
112 0 : _tag = "";
113 0 : return readNextTag();
114 : } else { //parsable
115 :
116 0 : while(_line.find(">", startTag) == std::string::npos) {//find end of a tag
117 0 : std::string addLine;
118 0 : if(!std::getline(_fin, addLine)) return false;
119 0 : _lineNo++;
120 0 : _line += " ";
121 0 : _line += addLine;
122 0 : }
123 0 : endTag = _line.find(">", startTag);
124 0 : _inLineTag = false;
125 0 : if(_line.find("/>", startTag) < endTag) {
126 0 : endTag--;
127 0 : _inLineTag = true;
128 0 : }
129 :
130 0 : if(_line.find(" ", startTag) != std::string::npos && _line.find(" ", startTag) < endTag) {//find end of the first word in the tag
131 0 : endTagTitle = _line.find(" ", startTag);
132 0 : } else {
133 : endTagTitle = endTag;
134 : }
135 :
136 0 : _tagTitle = _line.substr(startTag + 1, endTagTitle - startTag - 1);
137 0 : _tag = _line.substr(startTag + 1, endTag - startTag - 1);
138 :
139 : //now we have the tag lets remove it from the line
140 0 : if(_inLineTag) {
141 0 : _line = _line.substr(endTag+2);
142 0 : } else {
143 0 : _line = _line.substr(endTag+1);
144 : }
145 0 : return true;
146 : }
147 0 : }
148 :
149 : std::string EvtParserXml::getParentTagTitle() {
150 0 : if(_tagTree.empty()) return "";
151 0 : else return _tagTree.back();
152 0 : }
153 :
154 : std::string EvtParserXml::readAttribute(std::string attribute, std::string defaultValue) {
155 0 : std::string whitespace = " \t\n\v\f\r";
156 0 : for(unsigned int i=0; i<whitespace.size(); i++) {
157 : //find any whitespace followed by the attribute name followed by an '='
158 0 : std::string attName = whitespace[i] + attribute + "=";
159 0 : if (_tag.find(attName) != std::string::npos) {
160 0 : int startAttri = _tag.find(attName);
161 0 : int startQuote = _tag.find("\"", startAttri + 1);
162 0 : int endQuote = _tag.find("\"", startQuote + 1);
163 0 : return _tag.substr(startQuote + 1, endQuote - startQuote - 1);
164 : }
165 0 : }
166 0 : return defaultValue;
167 0 : }
168 :
169 : bool EvtParserXml::readAttributeBool(std::string attribute, bool defaultValue) {
170 0 : std::string valStr = readAttribute(attribute);
171 0 : if(!defaultValue) return (valStr == "true" || valStr == "1" || valStr == "on" || valStr == "yes");
172 0 : else return (valStr != "false" && valStr != "0" && valStr != "off" && valStr != "no");
173 0 : }
174 :
175 : int EvtParserXml::readAttributeInt(std::string attribute, int defaultValue) {
176 0 : std::string valStr = readAttribute(attribute);
177 0 : if (valStr == "") return defaultValue;
178 0 : std::istringstream valStream(valStr);
179 0 : int retVal;
180 0 : valStream >> retVal;
181 0 : return retVal;
182 0 : }
183 :
184 : double EvtParserXml::readAttributeDouble(std::string attribute, double defaultValue) {
185 0 : std::string valStr = readAttribute(attribute);
186 0 : if (valStr == "") return defaultValue;
187 0 : std::istringstream valStream(valStr);
188 0 : double retVal;
189 0 : valStream >> retVal;
190 0 : return retVal;
191 0 : }
192 :
193 : bool EvtParserXml::processTagTree() {
194 0 : if(_tagTitle == "") return true;
195 0 : if(_tagTitle[0] == '/') {
196 0 : if(_tagTitle.substr(1) == _tagTree.back()) {
197 0 : _tagTree.pop_back();
198 : } else {
199 0 : return false;
200 : }
201 0 : } else if(!_inLineTag) {
202 0 : _tagTree.push_back(_tagTitle);
203 0 : }
204 0 : return true;
205 0 : }
206 :
207 : bool EvtParserXml::expandEnvVars(std::string& str) {
208 0 : while(str.find('$') != std::string::npos) {
209 0 : size_t varStart = str.find('$');
210 : size_t varNameLength;
211 0 : std::string varName;
212 :
213 : //if this is the last character then just remove the $
214 0 : if(varStart == str.length()-1) {
215 0 : str.erase(varStart);
216 0 : return true;
217 : }
218 :
219 0 : if(str[varStart+1] == '{') {
220 : //deal with environment variables in {}s
221 : size_t braceStart = varStart+1;
222 0 : size_t braceEnd = str.find('}',braceStart);
223 :
224 0 : if(braceEnd == std::string::npos) {
225 0 : report(Severity::Error,"EvtGen")
226 0 : << "Incomplete environment variable found in text: "<<str<<endl;
227 0 : report(Severity::Error,"EvtGen")
228 0 : << "Will terminate execution!"<<endl;
229 0 : return false;
230 : }
231 :
232 0 : varName = str.substr(braceStart+1,braceEnd-braceStart-1);
233 0 : varNameLength = braceEnd-varStart;
234 :
235 0 : } else {
236 : //deal with everything else
237 : varNameLength=0;
238 :
239 0 : while(varNameLength + varStart + 1 < str.length() && isAlphaNum(str[varStart+varNameLength+1])) {
240 0 : ++varNameLength;
241 : }
242 :
243 0 : varName = str.substr(varStart+1,varNameLength);
244 : }
245 :
246 0 : char* envVar = getenv(varName.c_str());
247 :
248 0 : if(envVar) str.replace(varStart,varNameLength+1,envVar);
249 : else {
250 0 : report(Severity::Warning,"EvtGen")
251 0 : << "Undefined environment variable found in text: "<<varName<<endl;
252 0 : str.replace(varStart,varNameLength+1,"");
253 : }
254 0 : }
255 0 : return true;
256 0 : }
257 :
258 : bool EvtParserXml::isAlphaNum(char c) {
259 0 : if(c>='0' && c<='9') return true;
260 0 : if(c>='A' && c<='Z') return true;
261 0 : if(c>='a' && c<='z') return true;
262 0 : if(c=='_') return true;
263 0 : return false;
264 0 : }
|