GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: tmp_project/FileParser/src/DicoValue.cpp Lines: 168 175 96.0 %
Date: 2024-12-09 15:41:43 Branches: 224 253 88.5 %

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
1322
DicoValue::DicoValue(){
12
13
1322
}
14
15
///Copy Constructor of class DicoValue
16
/**	@param other : DicoValue we want ot copy
17
*/
18
781
DicoValue::DicoValue(const DicoValue & other){
19
781
	copyDicoValue(other);
20
781
}
21
22
///Destructor of class DicoValue
23
4206
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
526
DicoValue & DicoValue::operator = (const DicoValue & other){
32
526
	copyDicoValue(other);
33
526
	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
///Create a DicoValue from a std::string
61
/**	@param content : content to be parsed
62
 * 	@return true on success, false otherwise
63
*/
64
bool DicoValue::fromString(const std::string & content){
65
	PFileParser parser;
66
	parser.setFileContent(content);
67
	return loadParser(parser);
68
}
69
70
///Convert the DicoValue into a string
71
/**	@param indentation : indentation of the current DicoValue
72
 * 	@param isAfterDash : true if the toString is performed after a dash, false otherwise
73
 * 	@return string
74
*/
75
368
std::string DicoValue::toString(const std::string & indentation, int isAfterDash) const{
76
1104
	std::string out(""), newIndentation(indentation), currentIndentation(indentation);
77
368
	if(isAfterDash > 0){
78
80
		currentIndentation = "";
79
	}
80
368
	if(p_key != ""){
81
326
		newIndentation = indentation + "\t";
82
	}
83
368
	if(p_mapChild.size() != 0lu){
84

74
		if(p_key != ""){out += currentIndentation + p_key + ":\n";}
85
400
		for(MapDicoValue::const_iterator it(p_mapChild.begin()); it != p_mapChild.end(); ++it){
86
326
			out += it->second.toString(newIndentation, isAfterDash);
87
		}
88
294
	}else if(p_vecChild.size() != 0lu){
89
44
		std::string dash("- ");
90
22
		if(p_key != ""){
91
22
			out += currentIndentation + p_key + ":\n";
92
		}
93
58
		for(VecDicoValue::const_iterator it(p_vecChild.begin()); it != p_vecChild.end(); ++it){
94

36
			out += newIndentation + dash + it->toString(newIndentation, 2);
95
		}
96
	}else{
97
272
		if(p_key != ""){
98

248
			out += indentation + p_key + ": "+p_value+"\n";
99
		}else{
100
24
			out += p_value + "\n";
101
		}
102
	}
103
368
	--isAfterDash;
104
736
	return out;
105
}
106
107
///Print the DicoValue
108
6
void DicoValue::print() const{
109

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

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

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

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




63
	while(!parser.isEndOfFile() && !parser.isMatch("}") && isRunning){
321
47
		DicoValue dv;
322
47
		if(dv.parseDicoValue(parser, isRunning)){
323
47
			if(dv.p_key != ""){	//It is a dico entry
324
// 				std::cerr << "DicoValue::parseListOrMap : loadParser add DicoValue with key '"<<dv.p_key<<"'" << std::endl;
325
26
				p_mapChild[dv.p_key] = dv;
326
			}else{	//It is a value
327
21
				p_vecChild.push_back(dv);
328
			}
329
		}else{
330
			errorAt(parser, isRunning, "Cannot parse dico value");
331
		}
332

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

19
		else if(parser.isMatchRewind("}")){}
334
		else{
335
4
			return errorAt(parser, isRunning, "Expect ',' or '}' after value");
336
		}
337
	}
338
339
16
	return true;
340
}
341
342
///Parse a string
343
/**	@param[out] parser : parser to be used
344
 * 	@return true on success, false otherwise
345
*/
346
66
std::string DicoValue::parseString(PFileParser & parser){
347

66
	if(parser.isMatch("\"")){
348
16
		return parser.getUntilKeyWithoutPatern("\"");
349

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

9
		if(p_key != ""){out += "\n" + indentation +p_key + ": {";}
379
18
		std::string comma("");
380
34
		for(MapDicoValue::const_iterator it(p_mapChild.begin()); it != p_mapChild.end(); ++it){
381
25
			out += comma;
382
25
			out += it->second.saveRecurse(newIndentation);
383
25
			comma = ",";
384
		}
385

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

6
		if(p_key != ""){out += "\n" + indentation + p_key + ": {";}
388
12
		std::string comma("");
389
24
		for(VecDicoValue::const_iterator it(p_vecChild.begin()); it != p_vecChild.end(); ++it){
390
18
			out += comma;
391
18
			out += it->saveRecurse(newIndentation);
392
18
			comma = ", ";
393
		}
394

6
		if(p_key != ""){out += "}";}
395
	}else{
396
74
		std::string valueToSave(p_value);
397

37
		if(findCharsInString(p_value, " \t\n':/")){
398
3
			valueToSave = "\"" + p_value + "\"";
399
		}
400


37
		if(p_key != ""){out += "\n" + indentation + p_key + ": "+valueToSave;}
401
21
		else{out += valueToSave;}
402
	}
403
404
104
	return out;
405
}
406
407