GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: tmp_project/FileParser/src/pxml_utils.cpp Lines: 174 195 89.2 %
Date: 2023-10-11 10:52:07 Branches: 246 368 66.8 %

Line Branch Exec Source
1
/***************************************
2
	Auteur : Pierre Aubert
3
	Mail : pierre.aubert@lapp.in2p3.fr
4
	Licence : CeCILL-C
5
****************************************/
6
7
///List of allowed char as balise name
8
#define ALLOWED_BALISE_CHAR "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:?!-"
9
10
///List of allowed char as attribute name
11
#define ALLOWED_ATTRIBUTE_CHAR "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:-"
12
13
#include "pxml_utils.h"
14
15
///Set the PFileParser for xml
16
/**	@param fileContent : content to be parsed
17
 * 	@param isSvg : true if the parsed file is a svg
18
 * 	@return PFileParser
19
*/
20
21
PFileParser pxml_setXmlParser(const std::string & fileContent, bool isSvg){
21
21
	PFileParser parser;
22
21
	parser.setSeparator("<>\"=");
23
21
	if(isSvg){
24
8
		parser.setWhiteSpace("");
25
	}else{
26
13
		parser.setWhiteSpace("\t\n ");
27
	}
28
21
	parser.setFileContent(fileContent);
29
21
	return parser;
30
}
31
32
///Parse a PXml with a file
33
/**	@param[out] xml : PXml to be initialised
34
 * 	@param fileName : name of the intialisation file
35
 * 	@param isSvg : true if the parsed file is a svg
36
 * 	@return true on success, false otherwise
37
*/
38
9
bool pxml_parserFile(PXml & xml, const std::string & fileName, bool isSvg){
39
9
	return pxml_parserContent(xml, getFileContent(fileName), isSvg);
40
}
41
42
///Parse a PXml with a file content
43
/**	@param[out] xml : PXml to be initialised
44
 * 	@param fileContent : file content
45
 * 	@param isSvg : true if the parsed file is a svg
46
 * 	@return true on success, false otherwise
47
*/
48
21
bool pxml_parserContent(PXml & xml, const std::string & fileContent, bool isSvg){
49
42
	PFileParser parser(pxml_setXmlParser(fileContent, isSvg));
50
21
	xml.setName("root");
51
52
42
	return pxml_parserXmlContent(xml, parser, true);
53
54
// 	return pxml_parserVecXml(xml.getVecChild(), parser, isSvg);
55
}
56
57
///Say if it is the end of the attribute definition of the current balise
58
/**	@param[out] parent : xml parent in wich to set the isCompact attribute
59
 * 	@param[out] parser : parser to be used
60
 * 	@return true if the attribute end is reached, false if not
61
*/
62
83
bool pxml_isAttributeEnd(PXml & parent, PFileParser & parser){
63

83
	if(parser.isMatch("/>")){
64
1
		parent.setIsCompact(true);
65
1
		return true;
66

82
	}else if(parser.isMatch(">")){
67
72
		parent.setIsCompact(false);
68
72
		return true;
69
	}else{
70
10
		return false;
71
	}
72
}
73
74
///Parse the attribute of a xml balise
75
/**	@param[out] parent : xml parent in wich to put the attribute
76
 * 	@param[out] parser : parser to be used
77
 * 	@return true on success, false otherwise
78
*/
79
73
bool pxml_parserXmlAttribute(PXml & parent, PFileParser & parser){
80
73
	parser.setWhiteSpace(" \t\n");
81

83
	while(!pxml_isAttributeEnd(parent, parser) && !parser.isEndOfFile()){
82
20
		std::string attributeName(parser.getStrComposedOf(ALLOWED_ATTRIBUTE_CHAR));
83
10
		if(attributeName == ""){
84
			std::cerr << "pxml_parserXmlAttribute : error at : " << parser.getLocation() << std::endl;
85
			std::cerr << "\tcannot parse the attributes name as '"<<parser.getNextToken()<<"'" << std::endl;
86
			return false;
87
		}
88

10
		if(!parser.isMatch("=")){
89
			std::cerr << "pxml_parserXmlAttribute : error at : " << parser.getLocation() << std::endl;
90
			std::cerr << "\texpected '=' after attribute '"<<attributeName<<"'" << std::endl;
91
			return false;
92
		}
93

10
		if(!parser.isMatch("\"")){
94
			std::cerr << "pxml_parserXmlAttribute : error at : " << parser.getLocation() << std::endl;
95
			std::cerr << "\texpected '\"' after attribute '"<<attributeName<<"='" << std::endl;
96
			return false;
97
		}
98
30
		std::string attributeValue(parser.getUntilKeyWithoutPatern("\""));
99
20
		PXmlAttr tmpAttribute;
100
10
		tmpAttribute.setName(attributeName);
101
10
		tmpAttribute.setValue(attributeValue);
102
10
		parent.getVecAttr().push_back(tmpAttribute);
103
	}
104
73
	parser.setWhiteSpace("");
105
73
	return true;
106
}
107
108
109
///Parse the content of an xml balise
110
/**	@param[out] parent : xml parent in wich to put the content
111
 * 	@param[out] parser : parser to be used
112
 * 	@param isMainBalise : true if the parent balise if the main one, false otherwise
113
 * 	@return true on success, false otherwise
114
*/
115
93
bool pxml_parserXmlContent(PXml & parent, PFileParser & parser, bool isMainBalise){
116
93
	parser.setSeparator("<>\"=");
117
93
	parser.setWhiteSpace("");
118
186
	std::string balisePartialEnd("/" + parent.getName() + ">");
119
186
	std::string baliseEnd("<" + balisePartialEnd);
120
186
	PXml text;
121
93
	text.setIsText(true);
122


167
	while(!parser.isMatch(baliseEnd) && !parser.isEndOfFile()){
123
306
		std::string textString(parser.getUntilKeyWithoutPatern("<"));
124
153
		if(textString != ""){	//If the next token is not a < it is a text
125
117
			text.getValue() += textString;
126
117
			if(parent.getVecChild().size() == 0lu){
127
71
				if(parser.isMatch(balisePartialEnd)){
128
40
					parent.setValue(text.getValue());
129
40
					return true;
130
				}else{
131
31
					parent.getVecChild().push_back(text);
132
				}
133
			}else{
134
46
				parent.getVecChild().push_back(text);
135
			}
136
77
			text.setValue("");	//Reset value for next one
137
		}
138
113
		if(parser.isEndOfFile()){
139
14
			if(isMainBalise){
140
13
				return true;
141
			}else{
142

1
				std::cerr << "pxml_parserXmlContent : error at : " << parser.getLocation() << std::endl;
143

1
				std::cerr << "\tunexpected end of file. We are supposed to be in the balise '"<<parent.getName()<<"'" << std::endl;
144
1
				return false;
145
			}
146
		}
147
99
		if(parser.isMatch(balisePartialEnd)){	//We find the end of the balise
148
24
			return true;
149
		}else{	//Or it can be another balise
150
150
			std::string childBaliseName(parser.getStrComposedOf(ALLOWED_BALISE_CHAR));
151
75
			if(childBaliseName != ""){	//We find a new balise
152
75
				PXml xml;
153
75
				xml.setName(childBaliseName);
154
75
				if(childBaliseName == "!--"){
155
1
					parser.getUntilKeyWithoutPatern("-->");	//Skip the comment
156
74
				}else if(childBaliseName == "?xml"){
157
1
					parser.getUntilKeyWithoutPatern("?>");	//Skip the svg balise
158
				}else{
159
73
					if(!pxml_parserXmlAttribute(xml, parser)){	//Let's parse the attribute
160
						std::cerr << "pxml_parserXmlContent : error at : " << parser.getLocation() << std::endl;
161
						std::cerr << "\tcannot parse the attributes of balise '"<<childBaliseName<<"'" << std::endl;
162
						return false;
163
					}
164
73
					if(!xml.getIsCompact()){
165
						//Let's parse the content
166
72
						if(!pxml_parserXmlContent(xml, parser, false)){
167

1
							std::cerr << "pxml_parserXmlContent : error at : " << parser.getLocation() << std::endl;
168

1
							std::cerr << "\tcannot parse balise '"<<childBaliseName<<"'" << std::endl;
169
1
							return false;
170
						}
171
					}
172
72
					parent.getVecChild().push_back(xml);
173
				}
174
			}else if(parser.isMatch("/")){
175
				std::cerr << "pxml_parserXmlContent : in balise '"<<parent.getName()<<"' unexpected '</' at : " << parser.getLocation() << std::endl;
176
				return false;
177
			}else{	//It was just a text <
178
				text.getValue() += "<";
179
			}
180
		}
181
	}
182
14
	return true;
183
}
184
185
186
187
188
189
190
191
///Get the vector of childs with given name if exist
192
/**	@param[out] vecMatch : vector of matched childs
193
 * 	@param xml : xml input
194
 * 	@param childName : name of the searched childs
195
 * 	@return true if the childs exist, false otherwise
196
*/
197
7
bool pxml_getVecChildIfExist(PVecXml & vecMatch, const PXml & xml, const std::string & childName){
198
7
	bool isFound(false);
199
7
	const PVecXml & vecChild = xml.getVecChild();
200
48
	for(PVecXml::const_iterator it(vecChild.begin()); it != vecChild.end(); ++it){
201
41
		if(it->getName() == childName){
202
17
			vecMatch.push_back(*it);
203
17
			isFound = true;
204
		}
205
	}
206
7
	return isFound;
207
}
208
209
///Get the child with given name if exist
210
/**	@param[out] match : matched child
211
 * 	@param xml : xml input
212
 * 	@param childName : name of the searched child
213
 * 	@return true if the child exist, false otherwise
214
*/
215
11
bool pxml_getChildIfExist(PXml & match, const PXml & xml, const std::string & childName){
216
11
	bool isSearched(true);
217
11
	const PVecXml & vecChild = xml.getVecChild();
218
11
	PVecXml::const_iterator it(vecChild.begin());
219

29
	while(it != vecChild.end() && isSearched){
220
18
		if(it->getName() == childName){
221
2
			match = *it;
222
2
			isSearched = false;
223
		}
224
18
		++it;
225
	}
226
11
	return !isSearched;
227
}
228
229
///Get the child with given name if exist
230
/**	@param xml : xml input
231
 * 	@param childName : name of the searched child
232
 * 	@return pointer to the existing child, NULL otherwise
233
*/
234
7
PXml * pxml_getChildPtr(PXml & xml, const std::string & childName){
235
7
	PXml * out = NULL;
236
7
	PVecXml & vecChild = xml.getVecChild();
237

14
	for(PVecXml::iterator it(vecChild.begin()); it != vecChild.end() && out == NULL; ++it){
238
7
		if(it->getName() == childName){
239
7
			out = &(*it);
240
		}
241
	}
242
7
	return out;
243
}
244
245
///Get the attribute with given name if exist
246
/**	@param[out] attr : vector of matched child
247
 * 	@param xml : xml input
248
 * 	@param attrName : name of the searched child
249
 * 	@return true if the attribute exists, false otherwise
250
*/
251
17
bool pxml_getAttrIfExist(PXmlAttr & attr, const PXml & xml, const std::string & attrName){
252
17
	bool isSearched(true);
253
17
	const PVecXmlAttr & vecAttr = xml.getVecAttr();
254
17
	PVecXmlAttr::const_iterator it(vecAttr.begin());
255

22
	while(it != vecAttr.end() && isSearched){
256
5
		if(it->getName() == attrName){
257
5
			attr = *it;
258
5
			isSearched = false;
259
		}
260
5
		++it;
261
	}
262
17
	return !isSearched;
263
}
264
265
///Set a value to an attribute
266
/**	@param[out] xml : xml to be modified
267
 * 	@param nameAttr : name of the attribute
268
 * 	@param valueAttr : value of the attribute
269
*/
270
1
void pxml_setAttr(PXml & xml, const std::string & nameAttr, const std::string & valueAttr){
271
1
	bool isSearched(true);
272
1
	PVecXmlAttr & vecAttr = xml.getVecAttr();
273
1
	PVecXmlAttr::iterator it(vecAttr.begin());
274

1
	while(it != vecAttr.end() && isSearched){
275
		if(it->getName() == nameAttr){
276
			it->setValue(valueAttr);
277
			isSearched = false;
278
		}
279
		++it;
280
	}
281
1
}
282
283
///Erase the childs of the current xml if it has childName as name
284
/**	@param xml : current input
285
 * 	@param childName : name of the childs to be erased
286
 * 	@return output xml without childs named childName
287
*/
288
1
PXml pxml_eraseVecChild(const PXml & xml, const std::string & childName){
289
1
	PXml out;
290
1
	out.setName(xml.getName());
291
1
	out.setValue(xml.getValue());
292
1
	out.setVecAttr(xml.getVecAttr());
293
1
	const PVecXml & vecXml = xml.getVecChild();
294
7
	for(PVecXml::const_iterator it(vecXml.begin()); it != vecXml.end(); ++it){
295
6
		if(it->getName() != childName){
296
			out.getVecChild().push_back(*it);
297
		}
298
	}
299
1
	return out;
300
}
301
302
///Save a xml in a file
303
/**	@param fileName : name of the output file
304
 * 	@param xml : xml to be saved
305
 * 	@param isSvg : say if the output xml has to be SVG like (with no space between chevron and newline between attribute
306
 * 	@return true on success, false otherwise
307
*/
308
4
bool pxml_saveFile(const std::string & fileName, const PXml & xml, bool isSvg){
309
8
	std::string body(pxml_baliseStr(xml, isSvg));
310
8
	return saveFileContent(fileName, body);
311
}
312
313
///Convert xml in string
314
/**	@param xml : xml to be converted into string
315
 * 	@param isSvg : say if the output xml has to be SVG like (with no space between chevron and newline between attribute
316
 * 	@return output string
317
*/
318
157
std::string pxml_baliseStr(const PXml & xml, bool isSvg){
319
471
	std::string body(""), name(xml.getName());
320
314
	std::string baseXmlNewLine("\n");
321
157
	if(isSvg){
322
23
		baseXmlNewLine = "";
323
	}
324
157
	if(xml.getIsText()){
325
69
		body += xml.getValue();
326
	}else{
327
88
		if(name != ""){
328
84
			body += "<";
329
84
			body += name;
330
84
			body += pxml_vecAttrStr(xml.getVecAttr(), isSvg);
331
332

84
			if(name == "?xml"){body += " ?>\n";}
333

84
			else if(name == "!--"){body += " -->\n";}
334
84
			else if(xml.getIsCompact()){
335
1
				body += " />"+baseXmlNewLine;
336
			}else{
337
83
				body += ">"+baseXmlNewLine;
338
83
				body += pxml_vecXmlStr(xml.getVecChild(), isSvg);
339
83
				body += xml.getValue();
340

83
				body += "</"+ name + ">" + baseXmlNewLine;
341
			}
342
		}else{
343
344
4
			body += pxml_vecXmlStr(xml.getVecChild(), isSvg);
345
		}
346
	}
347
314
	return body;
348
}
349
350
///Convert a vecto of xml in string
351
/**	@param vecXml : vecor of xml to be converted into string
352
 * 	@param isSvg : say if the output xml has to be SVG like (with no space between chevron and newline between attribute
353
 * 	@return output string
354
*/
355
94
std::string pxml_vecXmlStr(const PVecXml & vecXml, bool isSvg){
356
94
	std::string body("");
357
234
	for(PVecXml::const_iterator it(vecXml.begin()); it != vecXml.end(); ++it){
358
140
		body += pxml_baliseStr(*it, isSvg);
359
	}
360
94
	return body;
361
}
362
363
///Convert attribute in string
364
/**	@param xmlAttr : xml attribute to be converted into string
365
 * 	@param isSvg : say if the output xml has to be SVG like (with no space between chevron and newline between attribute
366
 * 	@return output string
367
*/
368
10
std::string pxml_attrStr(const PXmlAttr & xmlAttr, bool isSvg){
369
10
	std::string body(" ");
370

10
	body += xmlAttr.getName() + "=\"" + xmlAttr.getValue() + "\"";
371
10
	if(isSvg){
372
3
		body += "\n\t";
373
	}
374
10
	return body;
375
}
376
377
///Convert attributes in string
378
/**	@param vecXmlAttr : xml attributes to be converted into string
379
 * 	@param isSvg : say if the output xml has to be SVG like (with no space between chevron and newline between attribute
380
 * 	@return output string
381
*/
382
84
std::string pxml_vecAttrStr(const PVecXmlAttr & vecXmlAttr, bool isSvg){
383
84
	if(vecXmlAttr.size() == 0lu){return "";}
384
20
	std::string body("");
385
20
	for(PVecXmlAttr::const_iterator it(vecXmlAttr.begin()); it != vecXmlAttr.end(); ++it){
386
10
		body += pxml_attrStr(*it, isSvg);
387
	}
388
10
	return body;
389
}
390
391
///Get the content of the PXml (children or value)
392
/**	@param xml : PXml to be used
393
 * 	@return content of the PXml (children or value)
394
*/
395
58
std::string pxml_getFullContent(const PXml & xml){
396
58
	const PVecXml & vecXml = xml.getVecChild();
397
58
	if(vecXml.size() != 0lu){
398
7
		return pxml_vecXmlStr(vecXml);
399
	}else{
400
51
		return xml.getValue();
401
	}
402
}
403
404