μHAL (v2.8.17)
Part of the IPbus software repository
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
xml.cpp
Go to the documentation of this file.
1/*
2---------------------------------------------------------------------------
3
4 This file is part of uHAL.
5
6 uHAL is a hardware access library and programming framework
7 originally developed for upgrades of the Level-1 trigger of the CMS
8 experiment at CERN.
9
10 uHAL is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14
15 uHAL is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with uHAL. If not, see <http://www.gnu.org/licenses/>.
22
23
24 Andrew Rose, Imperial College, London
25 email: awr01 <AT> imperial.ac.uk
26
27 Marc Magrans de Abril, CERN
28 email: marc.magrans.de.abril <AT> cern.ch
29
30 Tom Williams, Rutherford Appleton Laboratory, Oxfordshire
31 email: tom.williams <AT> cern.ch
32
33---------------------------------------------------------------------------
34*/
35
37
38
39#include <ctype.h>
40#include <sstream>
41
42#include "pugixml.hpp"
43
45#include "uhal/log/log.hpp"
48
49
50
51// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
52namespace uhal
53{
54 namespace utilities
55 {
56
57 void PugiXMLParseResultPrettifier ( const pugi::xml_parse_result& aLoadResult , const boost::filesystem::path& aPath , const std::vector<uint8_t>& aFile )
58 {
59 log ( Error() , "Failed to parse file " , aPath.c_str() , ". PugiXML returned the following description " , Quote ( aLoadResult.description() ) , "." );
60 std::size_t lLineCounter ( 1 );
61 std::vector<uint8_t>::const_iterator lIt0 ( aFile.begin() );
62 std::vector<uint8_t>::const_iterator lIt1 ( aFile.begin() + aLoadResult.offset );
63 std::vector<uint8_t>::const_iterator lIt2 ( lIt1 );
64
65 for ( ; lIt0!=lIt1 ; ++lIt0 )
66 {
67 if ( *lIt0 == '\n' )
68 {
69 lLineCounter++;
70 }
71 }
72
73 for ( ; lIt1 != aFile.begin() ; --lIt1 )
74 {
75 if ( *lIt1 == '\n' )
76 {
77 ++lIt1;
78 break;
79 }
80 }
81
82 for ( ; lIt2 != aFile.end() ; ++lIt2 )
83 {
84 if ( *lIt2 == '\n' )
85 {
86 --lIt2;
87 break;
88 }
89 }
90
91 std::size_t lDist0 ( lIt0 - lIt1 );
92 std::size_t lDist1 ( lIt2 - lIt0 );
93 std::string lLine;
94 lLine.reserve ( lIt2 - lIt1 );
95
96 for ( ; lIt1 != lIt2 ; ++lIt1 )
97 {
98 if ( isprint ( *lIt1 ) || *lIt1==10 )
99 {
100 lLine += *lIt1;
101 }
102 else
103 {
104 lLine += '#';
105 }
106 }
107
108 log ( Error() , "Error occured at line number " , Integer ( lLineCounter ) ,
109 ", character " , Integer ( lDist0+1 ) , "\n"
110 "LINE : " , lLine , "\n"
111 "ERROR LOCATION : " , std::string ( lDist0 , '_' ) , "^" , std::string ( lDist1 , '_' ) );
112 }
113
114
115 template < bool DebugInfo >
116 bool GetXMLattribute ( const pugi::xml_node& aNode , const std::string& aAttrName , std::string& aTarget )
117 {
118 pugi::xml_attribute lAttr = aNode.attribute ( aAttrName.c_str() );
119
120 if ( ! lAttr.empty() )
121 {
122 aTarget = lAttr.value();
123 return true;
124 }
125 else
126 {
127 if ( DebugInfo )
128 {
129 log ( Error() , "Failed to get attribute " , Quote ( aAttrName ) , " from XML node." );
130 }
131
132 return false;
133 }
134 }
135
136 template bool GetXMLattribute<true>( const pugi::xml_node& aNode , const std::string& aAttrName , std::string& aTarget );
137 template bool GetXMLattribute<false>( const pugi::xml_node& aNode , const std::string& aAttrName , std::string& aTarget );
138
139
140 template < bool DebugInfo >
141 bool GetXMLattribute ( const pugi::xml_node& aNode , const std::string& aAttrName , int32_t& aTarget )
142 {
143 pugi::xml_attribute lAttr = aNode.attribute ( aAttrName.c_str() );
144
145 if ( ! lAttr.empty() )
146 {
147 std::string lAttrStr ( lAttr.value() );
148 std::stringstream ss;
149
150 //if string is of the form "x89abcdef" , "X89abcdef" , "0x89abcdef" , "0X89abcdef"
151 if ( lAttrStr.size() > 2 )
152 {
153 if ( ( lAttrStr[1] == 'x' ) || ( lAttrStr[1] == 'X' ) )
154 {
155 ss << std::hex << lAttrStr.substr ( 2 );
156 }
157 else
158 {
159 ss << lAttrStr;
160 }
161 }
162 else if ( lAttrStr.size() > 1 )
163 {
164 if ( ( lAttrStr[0] == 'x' ) || ( lAttrStr[0] == 'X' ) )
165 {
166 ss << std::hex << lAttrStr.substr ( 1 );
167 }
168 else
169 {
170 ss << lAttrStr;
171 }
172 }
173 else
174 {
175 ss << lAttrStr;
176 }
177
178 // ss >> aTarget;
179 // aTarget = lAttr.as_int();
180
181 if ( ss.str().size() > 10 )
182 {
183 exception::StringNumberWillNotFitInto32BitNumber lExc;
184 log ( lExc , "XML attribute " , Quote ( aAttrName ) , " has value " , Quote ( ss.str() ) , " which is too big to fit into 32-bit number" );
185 throw lExc;
186 }
187
188 int64_t lTarget;
189 ss >> lTarget;
190
191 if ( lTarget>>32 )
192 {
193 exception::StringNumberWillNotFitInto32BitNumber lExc;
194 log ( lExc , "XML attribute " , Quote ( aAttrName ) , " has value " , Quote ( ss.str() ) , " which is too big to fit into 32-bit number" );
195 throw lExc;
196 }
197
198 aTarget = ( int32_t ) ( lTarget );
199 return true;
200 }
201 else
202 {
203 if ( DebugInfo )
204 {
205 log ( Error() , "Failed to get attribute " , Quote ( aAttrName ) , " from XML node." );
206 }
207
208 return false;
209 }
210 }
211
212 template bool GetXMLattribute<true>( const pugi::xml_node& aNode , const std::string& aAttrName , int32_t& aTarget );
213 template bool GetXMLattribute<false>( const pugi::xml_node& aNode , const std::string& aAttrName , int32_t& aTarget );
214
215
216 template < bool DebugInfo >
217 bool GetXMLattribute ( const pugi::xml_node& aNode , const std::string& aAttrName , uint32_t& aTarget )
218 {
219 pugi::xml_attribute lAttr = aNode.attribute ( aAttrName.c_str() );
220
221 if ( ! lAttr.empty() )
222 {
223 std::string lAttrStr ( lAttr.value() );
224 std::stringstream ss;
225
226 size_t lBasePrefixLength = 0;
227
228 if ( lAttrStr.empty() )
229 throw exception::NodeAttributeIncorrectValue("XML attribute '" + aAttrName + "' is empty, so cannot be converted to uint32_t");
230
231 //if string is of the form "x89abcdef" , "X89abcdef" , "0x89abcdef" , "0X89abcdef"
232 if ( lAttrStr.size() > 2 )
233 {
234 if ( ( lAttrStr[0] == '0' ) and ( ( lAttrStr[1] == 'x' ) or ( lAttrStr[1] == 'X' ) ) )
235 {
236 lBasePrefixLength = 2;
237 ss << std::hex;
238 }
239 }
240
241 if ( lAttrStr.size() > 1 )
242 {
243 if ( ( lAttrStr[0] == 'x' ) || ( lAttrStr[0] == 'X' ) )
244 {
245 lBasePrefixLength = 1;
246 ss << std::hex;
247 }
248 }
249
250 if ( lAttrStr.find_first_not_of(lBasePrefixLength ? "0123456789abcdefABCDEF" : "0123456789", lBasePrefixLength) != std::string::npos )
251 throw exception::NodeAttributeIncorrectValue("XML attribute '" + aAttrName + "' has value '" + lAttrStr + "' that cannot be converted to uint32_t");
252
253 ss << lAttrStr.substr(lBasePrefixLength);
254
255
256 if ( ss.str().size() > 10 )
257 {
258 exception::StringNumberWillNotFitInto32BitNumber lExc;
259 log ( lExc , "XML attribute " , Quote ( aAttrName ) , " has value " , Quote ( ss.str() ) , " which is too big to fit into 32-bit number" );
260 throw lExc;
261 }
262
263 uint64_t lTarget;
264 ss >> lTarget;
265
266 if ( lTarget>>32 )
267 {
268 exception::StringNumberWillNotFitInto32BitNumber lExc;
269 log ( lExc , "XML attribute " , Quote ( aAttrName ) , " has value " , Quote ( ss.str() ) , " which is too big to fit into 32-bit number" );
270 throw lExc;
271 }
272
273 aTarget = ( uint32_t ) ( lTarget );
274 return true;
275 }
276 else
277 {
278 if ( DebugInfo )
279 {
280 log ( Error() , "Failed to get attribute " , Quote ( aAttrName ) , " from XML node." );
281 }
282
283 return false;
284 }
285 }
286
287 template bool GetXMLattribute<true>( const pugi::xml_node& aNode , const std::string& aAttrName , uint32_t& aTarget );
288 template bool GetXMLattribute<false>( const pugi::xml_node& aNode , const std::string& aAttrName , uint32_t& aTarget );
289
290
291 template < bool DebugInfo >
292 bool GetXMLattribute ( const pugi::xml_node& aNode , const std::string& aAttrName , double& aTarget )
293 {
294 pugi::xml_attribute lAttr = aNode.attribute ( aAttrName.c_str() );
295
296 if ( ! lAttr.empty() )
297 {
298 aTarget = lAttr.as_double();
299 return true;
300 }
301 else
302 {
303 if ( DebugInfo )
304 {
305 log ( Error() , "Failed to get attribute " , Quote ( aAttrName ) , " from XML node." );
306 }
307
308 return false;
309 }
310 }
311
312 template bool GetXMLattribute<true>( const pugi::xml_node& aNode , const std::string& aAttrName , double& aTarget );
313 template bool GetXMLattribute<false>( const pugi::xml_node& aNode , const std::string& aAttrName , double& aTarget );
314
315
316 template < bool DebugInfo >
317 bool GetXMLattribute ( const pugi::xml_node& aNode , const std::string& aAttrName , float& aTarget )
318 {
319 pugi::xml_attribute lAttr = aNode.attribute ( aAttrName.c_str() );
320
321 if ( ! lAttr.empty() )
322 {
323 aTarget = lAttr.as_float();
324 return true;
325 }
326 else
327 {
328 if ( DebugInfo )
329 {
330 log ( Error() , "Failed to get attribute " , Quote ( aAttrName ) , " from XML node." );
331 }
332
333 return false;
334 }
335 }
336
337 template bool GetXMLattribute<true>( const pugi::xml_node& aNode , const std::string& aAttrName , float& aTarget );
338 template bool GetXMLattribute<false>( const pugi::xml_node& aNode , const std::string& aAttrName , float& aTarget );
339
340
341 template < bool DebugInfo >
342 bool GetXMLattribute ( const pugi::xml_node& aNode , const std::string& aAttrName , bool& aTarget )
343 {
344 pugi::xml_attribute lAttr = aNode.attribute ( aAttrName.c_str() );
345
346 if ( ! lAttr.empty() )
347 {
348 aTarget = lAttr.as_bool();
349 return true;
350 }
351 else
352 {
353 if ( DebugInfo )
354 {
355 log ( Error() , "Failed to get attribute " , Quote ( aAttrName ) , " from XML node." );
356 }
357
358 return false;
359 }
360 }
361
362 template bool GetXMLattribute<true>( const pugi::xml_node& aNode , const std::string& aAttrName, bool& aTarget );
363 template bool GetXMLattribute<false>( const pugi::xml_node& aNode , const std::string& aAttrName, bool& aTarget );
364 }
365}
bool as_bool(bool def=false) const
Definition: pugixml.cpp:5195
float as_float(float def=0) const
Definition: pugixml.cpp:5190
bool empty() const
Definition: pugixml.cpp:5212
double as_double(double def=0) const
Definition: pugixml.cpp:5185
const char_t * value() const
Definition: pugixml.cpp:5222
xml_attribute attribute(const char_t *name) const
Definition: pugixml.cpp:5507
template bool GetXMLattribute< false >(const pugi::xml_node &aNode, const std::string &aAttrName, std::string &aTarget)
template bool GetXMLattribute< true >(const pugi::xml_node &aNode, const std::string &aAttrName, std::string &aTarget)
bool GetXMLattribute(const pugi::xml_node &aNode, const std::string &aAttrName, std::string &aTarget)
Helper function to retrieve a named attribute from a PugiXML node and cast it to the correct type.
Definition: xml.cpp:116
void PugiXMLParseResultPrettifier(const pugi::xml_parse_result &aLoadResult, const boost::filesystem::path &aPath, const std::vector< uint8_t > &aFile)
Helper function to make debugging failures when parsing XML files easier.
Definition: xml.cpp:57
_Quote< T > Quote(const T &aT)
_Integer< T, IntFmt<> > Integer(const T &aT)
Forward declare a function which creates an instance of the ultra-lightweight wrapper from an integer...
ErrorLevel Error
Definition: LogLevels.cpp:61
void log(FatalLevel &aFatal, const T0 &aArg0)
Function to add a log entry at Fatal level.
Definition: log.hxx:18
const char * description() const
Definition: pugixml.cpp:6819