GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
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 |
Generated by: GCOVR (Version 4.2) |