GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: tmp_project/FileParser/src/DicoValue.cpp Lines: 168 171 98.2 %
Date: 2023-10-11 10:52:07 Branches: 225 247 91.1 %

Line Branch Exec Source
1
/***************************************
2
	Auteur : Pierre Aubert
3
	Mail : pierre.aubert@lapp.in2p3.fr
4
	Licence : CeCILL-C
5
****************************************/
6
7
#include <fstream>
8
#include "DicoValue.h"
9
10
///Constructor of class DicoValue
11
1116
DicoValue::DicoValue(){
12
13
1116
}
14
15
///Copy Constructor of class DicoValue
16
/**	@param other : DicoValue we want ot copy
17
*/
18
631
DicoValue::DicoValue(const DicoValue & other){
19
631
	copyDicoValue(other);
20
631
}
21
22
///Destructor of class DicoValue
23
3494
DicoValue::~DicoValue(){
24
25
}
26
27
///Operator = of class DicoValue
28
/**	@param other : DicoValue we want ot copy
29
 * 	@return copied class DicoValue
30
*/
31
435
DicoValue & DicoValue::operator = (const DicoValue & other){
32
435
	copyDicoValue(other);
33
435
	return *this;
34
}
35
36
///Load the DicoValue with a text file
37
/**	@param fileName : name of the file to be loaded
38
 * 	@return true on success, false otherwise
39
*/
40
19
bool DicoValue::load(const std::string & fileName){
41
38
	PFileParser parser;
42
19
	if(!parser.open(fileName)){
43

7
		std::cerr << "DicoValue::load : cannot load the file '"<<fileName<<"'" << std::endl;
44
7
		return false;
45
	}
46
12
	return loadParser(parser);
47
}
48
49
///Save the DicoValue with a text file
50
/**	@param fileName : name of the file to be saved
51
 * 	@return true on success, false otherwise
52
*/
53
9
bool DicoValue::save(const std::string & fileName) const{
54
18
	std::string out("\n{");
55
9
	out += saveRecurse("\t");
56
9
	out += "\n}\n\n";
57
18
	return saveFileContent(fileName, out);
58
}
59
60
///Convert the DicoValue into a string
61
/**	@param indentation : indentation of the current DicoValue
62
 * 	@param isAfterDash : true if the toString is performed after a dash, false otherwise
63
 * 	@return string
64
*/
65
415
std::string DicoValue::toString(const std::string & indentation, int isAfterDash) const{
66
1245
	std::string out(""), newIndentation(indentation), currentIndentation(indentation);
67
415
	if(isAfterDash > 0){
68
92
		currentIndentation = "";
69
	}
70
415
	if(p_key != ""){
71
322
		newIndentation = indentation + "\t";
72
	}
73
415
	if(p_mapChild.size() != 0lu){
74

102
		if(p_key != ""){out += currentIndentation + p_key + ":\n";}
75
424
		for(MapDicoValue::const_iterator it(p_mapChild.begin()); it != p_mapChild.end(); ++it){
76
322
			out += it->second.toString(newIndentation, isAfterDash);
77
		}
78
313
	}else if(p_vecChild.size() != 0lu){
79
56
		std::string dash("- ");
80
28
		if(p_key != ""){
81
27
			out += currentIndentation + p_key + ":\n";
82
		}
83
90
		for(VecDicoValue::const_iterator it(p_vecChild.begin()); it != p_vecChild.end(); ++it){
84

62
			out += newIndentation + dash + it->toString(newIndentation, 2);
85
		}
86
	}else{
87
285
		if(p_key != ""){
88

236
			out += indentation + p_key + ": "+p_value+"\n";
89
		}else{
90
49
			out += p_value + "\n";
91
		}
92
	}
93
415
	--isAfterDash;
94
830
	return out;
95
}
96
97
///Print the DicoValue
98
31
void DicoValue::print() const{
99

31
	std::cout << toString() << std::endl;
100
31
}
101
102
///Say if the DicoValue has a key
103
/**	@return true if the DicoValue has a key, false otherwise
104
*/
105
92
bool DicoValue::hasKey() const{return p_key != "";}
106
107
///Say if the DicoValue has a map of children
108
/**	@return true if the DicoValue has a map of children, false otherwise
109
*/
110
127
bool DicoValue::hasMap() const{return p_mapChild.size() != 0lu;}
111
112
///Say if the DicoValue has a vector of children
113
/**	@return true if the DicoValue has a vector of children, false otherwise
114
*/
115
99
bool DicoValue::hasVec() const{return p_vecChild.size() != 0lu;}
116
117
///Say if the given key exists in the map of children
118
/**	@param key : key to be checked
119
 * 	@return true if the given key exists in the map of children, false otherwise
120
*/
121
1
bool DicoValue::isKeyExist(const std::string & key) const{
122
1
	std::map<std::string, DicoValue>::const_iterator it(p_mapChild.find(key));
123
1
	return it != p_mapChild.end();
124
}
125
126
///Get a DicoValue in the map of the current one
127
/**	@param key : name of the DicoValue to get
128
 * 	@return pointer to the found DicoValue if it exists, NULL otherwise
129
*/
130
324
const DicoValue * DicoValue::getMap(const std::string & key) const{
131
324
	std::map<std::string, DicoValue>::const_iterator it(p_mapChild.find(key));
132
324
	if(it != p_mapChild.end()){
133
260
		return &(it->second);
134
	}else{
135
64
		return NULL;
136
	}
137
}
138
139
///Get a DicoValue in the map of the current one
140
/**	@param key : name of the DicoValue to get
141
 * 	@return pointer to the found DicoValue if it exists, NULL otherwise
142
*/
143
69
DicoValue * DicoValue::getMap(const std::string & key){
144
69
	std::map<std::string, DicoValue>::const_iterator it(p_mapChild.find(key));
145
69
	if(it != p_mapChild.end()){
146
68
		return (DicoValue *)&(it->second);
147
	}else{
148
1
		return NULL;
149
	}
150
}
151
152
///Sets the value of the DicoValue
153
/**	@param value : value of the DicoValue
154
*/
155
444
void DicoValue::setValue(const std::string & value){
156
444
	p_value = value;
157
444
}
158
159
///Sets the key of the DicoValue
160
/**	@param key : key of the DicoValue
161
*/
162
467
void DicoValue::setKey(const std::string & key){
163
467
	p_key = key;
164
467
}
165
166
///Sets the vecChild of the DicoValue
167
/**	@param vecChild : vecChild of the DicoValue
168
*/
169
1
void DicoValue::setVecChild(const std::vector<DicoValue> & vecChild){
170
1
	p_vecChild = vecChild;
171
1
}
172
173
///Sets the mapChild of the DicoValue
174
/**	@param mapChild : mapChild of the DicoValue
175
*/
176
1
void DicoValue::setMapChild(const std::map<std::string, DicoValue> & mapChild){
177
1
	p_mapChild = mapChild;
178
1
}
179
180
///Gets the value of the DicoValue
181
/**	@return value of the DicoValue
182
*/
183
129
const std::string & DicoValue::getValue() const{
184
129
	return p_value;
185
}
186
187
///Gets the value of the DicoValue
188
/**	@return value of the DicoValue
189
*/
190
53
std::string & DicoValue::getValue(){
191
53
	return p_value;
192
}
193
194
///Get a string value without the first and/or last quote or double quote in there are some
195
/**	@return value without the first and/or last quote or double quote in there are some
196
*/
197
260
std::string DicoValue::getString() const{
198
260
	return eraseFirstLastChars(p_value, "\"\'");
199
}
200
201
///Gets the key of the DicoValue
202
/**	@return key of the DicoValue
203
*/
204
43
const std::string & DicoValue::getKey() const{
205
43
	return p_key;
206
}
207
208
///Gets the key of the DicoValue
209
/**	@return key of the DicoValue
210
*/
211
311
std::string & DicoValue::getKey(){
212
311
	return p_key;
213
}
214
215
///Gets the vecChild of the DicoValue
216
/**	@return vecChild of the DicoValue
217
*/
218
43
const std::vector<DicoValue> & DicoValue::getVecChild() const{
219
43
	return p_vecChild;
220
}
221
222
///Gets the vecChild of the DicoValue
223
/**	@return vecChild of the DicoValue
224
*/
225
95
std::vector<DicoValue> & DicoValue::getVecChild(){
226
95
	return p_vecChild;
227
}
228
229
///Gets the mapChild of the DicoValue
230
/**	@return mapChild of the DicoValue
231
*/
232
4
const std::map<std::string, DicoValue> & DicoValue::getMapChild() const{
233
4
	return p_mapChild;
234
}
235
236
///Gets the mapChild of the DicoValue
237
/**	@return mapChild of the DicoValue
238
*/
239
497
std::map<std::string, DicoValue> & DicoValue::getMapChild(){
240
497
	return p_mapChild;
241
}
242
243
///Copy Function of class DicoValue
244
/**	@param other : DicoValue we want ot copy
245
*/
246
1066
void DicoValue::copyDicoValue(const DicoValue & other){
247
1066
	p_value = other.p_value;
248
1066
	p_key = other.p_key;
249
1066
	p_vecChild = other.p_vecChild;
250
1066
	p_mapChild = other.p_mapChild;
251
1066
}
252
253
///Load the DicoValue with a parser
254
/**	@param[out] parser : parser to be used
255
 * 	@return true on success, false otherwise
256
*/
257
12
bool DicoValue::loadParser(PFileParser & parser){
258
12
	parser.setEscapeChar('\\');
259
12
	parser.setWhiteSpace(" \t\n");
260
12
	parser.setSeparator(",:{}\"");
261
12
	bool isRunning(true);
262

25
	while(!parser.isEndOfFile() && isRunning){
263
13
		if(parseDicoValue(parser, isRunning)){
264
13
			parser.skipWhiteSpace();
265
		}else{
266
			errorAt(parser, isRunning, "Cannot parse dico value");
267
		}
268
	}
269
12
	return isRunning;
270
}
271
272
///Parse a DicoValue with a text file
273
/**	@param[out] parser : parser to be used
274
 * 	@param[out] isRunning : true to continue the parsing, false to stop it
275
 * 	@return true on success, false otherwise
276
*/
277
86
bool DicoValue::parseDicoValue(PFileParser & parser, bool & isRunning){
278
86
	if(parseListOrMap(parser, isRunning)){return true;}
279
	else{
280
66
		std::string nextKeyOrValue(parseString(parser));
281
66
		if(nextKeyOrValue == ""){
282
48
			nextKeyOrValue = parser.getStrComposedOf("abcdefghijklmnopqsrtuvwxyzABCDEFGHIJKLMNOPQSRTUVWXYZ0123456789._-");
283
48
			if(nextKeyOrValue == ""){
284
4
				return errorAt(parser, isRunning,
285
2
					"Expecting a string or a keywork composed of letters, number, underscore, slash or minus");
286
			}
287
		}
288

64
		if(parser.isMatch(":")){	//It was a key for a dictionnary
289
// 			std::cerr << "DicoValue::parseDicoValue : find key '"<<nextKeyOrValue<<"'" << std::endl;
290
26
			p_key = nextKeyOrValue;
291
26
			if(!parseDicoValue(parser, isRunning)){
292
				return errorAt(parser, isRunning, "Cannot parse value");
293
			}
294
		}else{			//It was a value
295
38
			p_value = nextKeyOrValue;
296
		}
297
64
		parser.skipWhiteSpace();
298
	}
299
64
	return true;
300
}
301
302
///Parse a list or a map
303
/**	@param[out] parser : parser to be used
304
 * 	@param[out] isRunning : true to continue the parsing, false to stop it
305
 * 	@return true on success, false otherwise
306
*/
307
86
bool DicoValue::parseListOrMap(PFileParser & parser, bool & isRunning){
308

86
	if(!parser.isMatch("{")){return false;}	//If this is not a {, then it is not a list or a map
309
310




63
	while(!parser.isEndOfFile() && !parser.isMatch("}") && isRunning){
311
47
		DicoValue dv;
312
47
		if(dv.parseDicoValue(parser, isRunning)){
313
47
			if(dv.p_key != ""){	//It is a dico entry
314
// 				std::cerr << "DicoValue::parseListOrMap : loadParser add DicoValue with key '"<<dv.p_key<<"'" << std::endl;
315
26
				p_mapChild[dv.p_key] = dv;
316
			}else{	//It is a value
317
21
				p_vecChild.push_back(dv);
318
			}
319
		}else{
320
			errorAt(parser, isRunning, "Cannot parse dico value");
321
		}
322

47
		if(parser.isMatch(",")){}
323

19
		else if(parser.isMatchRewind("}")){}
324
		else{
325
4
			return errorAt(parser, isRunning, "Expect ',' or '}' after value");
326
		}
327
	}
328
329
16
	return true;
330
}
331
332
///Parse a string
333
/**	@param[out] parser : parser to be used
334
 * 	@return true on success, false otherwise
335
*/
336
66
std::string DicoValue::parseString(PFileParser & parser){
337

66
	if(parser.isMatch("\"")){
338
16
		return parser.getUntilKeyWithoutPatern("\"");
339

50
	}else if(parser.isMatch("'")){
340
2
		return parser.getUntilKeyWithoutPatern("'");
341
	}
342
48
	return "";
343
}
344
345
///Print the parsing error
346
/**	@param[out] parser : parser to be used
347
 * 	@param[out] isRunning : true to continue the parsing, false to stop it
348
 * 	@param errorMsg : error message
349
 * 	@return true and stop the parsing with isRunning
350
*/
351
6
bool DicoValue::errorAt(PFileParser & parser, bool & isRunning, const std::string & errorMsg){
352
6
	isRunning = false;
353
6
	std::cerr << "DicoValue::errorAt : " << parser.getLocation() << std::endl;
354
6
	std::cerr << "\t" << errorMsg << std::endl;
355
6
	return true;
356
}
357
358
///Save the DicoValue with a text file
359
/**	@param indentation : indentation of the current DicoValue
360
 * 	@return file content
361
*/
362
52
std::string DicoValue::saveRecurse(const std::string & indentation) const{
363
156
	std::string out(""), newIndentation("");
364
52
	if(p_key != ""){
365
25
		newIndentation = indentation + "\t";
366
	}
367
52
	if(p_mapChild.size() != 0lu){
368

9
		if(p_key != ""){out += "\n" + indentation +p_key + ": {";}
369
18
		std::string comma("");
370
34
		for(MapDicoValue::const_iterator it(p_mapChild.begin()); it != p_mapChild.end(); ++it){
371
25
			out += comma;
372
25
			out += it->second.saveRecurse(newIndentation);
373
25
			comma = ",";
374
		}
375

9
		if(p_key != ""){out += "\n"+indentation+"}";}
376
43
	}else if(p_vecChild.size() != 0lu){
377

6
		if(p_key != ""){out += "\n" + indentation + p_key + ": {";}
378
12
		std::string comma("");
379
24
		for(VecDicoValue::const_iterator it(p_vecChild.begin()); it != p_vecChild.end(); ++it){
380
18
			out += comma;
381
18
			out += it->saveRecurse(newIndentation);
382
18
			comma = ", ";
383
		}
384

6
		if(p_key != ""){out += "}";}
385
	}else{
386
74
		std::string valueToSave(p_value);
387

37
		if(findCharsInString(p_value, " \t\n':/")){
388
3
			valueToSave = "\"" + p_value + "\"";
389
		}
390


37
		if(p_key != ""){out += "\n" + indentation + p_key + ": "+valueToSave;}
391
21
		else{out += valueToSave;}
392
	}
393
394
104
	return out;
395
}
396
397