PhoenixFileParser  1.0.0
Set of tools to ease file parsing
Loading...
Searching...
No Matches
DicoValue.cpp
Go to the documentation of this file.
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
14
16
19 copyDicoValue(other);
20}
21
26
28
32 copyDicoValue(other);
33 return *this;
34}
35
37
40bool DicoValue::load(const PPath & fileName){
41 PFileParser parser;
42 if(!parser.open(fileName)){return false;}
43 return loadParser(parser);
44}
45
47
53bool DicoValue::save(const PPath & fileName, const PString & valueDecorator, PString baseIndentation, PString baseNewLine) const{
54 PString out(toString(valueDecorator, baseIndentation, baseNewLine));
55 return fileName.saveFileContent(out);
56}
57
59
62bool DicoValue::fromString(const PString & content){
63 PFileParser parser;
64 parser.setEscapeChar('\\');
65 parser.setFileContent(content);
66 return loadParser(parser);
67}
68
70
75PString DicoValue::toString(const PString & valueDecorator, PString baseIndentation, PString baseNewLine) const{
76 PString out(baseNewLine+"{");
77 out += saveRecurse(baseIndentation, valueDecorator, baseIndentation, baseNewLine);
78 out += baseNewLine+"}"+baseNewLine;
79 return out;
80}
81
83void DicoValue::print() const{
84 std::cout << "{" << std::endl;
85 std::cout << saveRecurse("\t", "\"", "\t", "\n") << std::endl;
86 std::cout << "{" << std::endl;
87}
88
90
92bool DicoValue::hasKey() const{return p_key != "";}
93
95
97bool DicoValue::hasMap() const{return p_mapChild.size() != 0lu;}
98
100
102bool DicoValue::hasVec() const{return p_vecChild.size() != 0lu;}
103
105
108bool DicoValue::isKeyExist(const PString & key) const{
109 std::map<PString, DicoValue>::const_iterator it(p_mapChild.find(key));
110 return it != p_mapChild.end();
111}
112
114
117const DicoValue * DicoValue::getMap(const PString & key) const{
118 std::map<PString, DicoValue>::const_iterator it(p_mapChild.find(key));
119 if(it != p_mapChild.end()){
120 return &(it->second);
121 }else{
122 return NULL;
123 }
124}
125
127
130const DicoValue * DicoValue::getMap(const PVecString & vecKey) const{
131 if(vecKey.size() == 0lu){return NULL;}
132 const DicoValue * tmpDico = this;
133 for(PVecString::const_iterator itAddress(vecKey.begin()); itAddress != vecKey.end() && tmpDico != NULL; ++itAddress){
134 if(tmpDico->hasMap()){
135 const DicoValue * key = tmpDico->getMap(*itAddress);
136 tmpDico = key;
137 }else{
138 tmpDico = NULL;
139 }
140 }
141 return tmpDico;
142}
143
145
149const DicoValue * DicoValue::getElementInVecWhere(const PString & key, const PString & value) const{
150 if(!hasVec()){return NULL;}
151 for(VecDicoValue::const_iterator it(p_vecChild.begin()); it != p_vecChild.end(); ++it){
152 const DicoValue * element = it->getMap(key);
153 if(element != NULL){
154 if(element->getString() == value){
155 return &(*it);
156 }
157 }else if(it->p_mapChild.size() == 1lu){
158 const DicoValue & mapElement = it->p_mapChild.begin()->second;
159 const DicoValue * elMap = mapElement.getMap(key);
160 if(elMap != NULL){
161 if(elMap->getString() == value){
162 return &mapElement;
163 }
164 }
165 }
166 }
167 return NULL;
168}
169
170
172
175DicoValue * DicoValue::getMap(const PString & key){
176 std::map<PString, DicoValue>::const_iterator it(p_mapChild.find(key));
177 if(it != p_mapChild.end()){
178 return (DicoValue *)&(it->second);
179 }else{
180 return NULL;
181 }
182}
183
185
187void DicoValue::setValue(const PString & value){
188 p_value = value;
189}
190
192
194void DicoValue::setKey(const PString & key){
195 p_key = key;
196}
197
199
201void DicoValue::setVecChild(const std::vector<DicoValue> & vecChild){
202 p_vecChild = vecChild;
203}
204
206
208void DicoValue::setMapChild(const std::map<PString, DicoValue> & mapChild){
209 p_mapChild = mapChild;
210}
211
213
215const PString & DicoValue::getValue() const{
216 return p_value;
217}
218
220
223 return p_value;
224}
225
227
229PString DicoValue::getString() const{
230 return p_value.eraseFirstLastChar("\"\'");
231}
232
234
236const PString & DicoValue::getKey() const{
237 return p_key;
238}
239
241
244 return p_key;
245}
246
248
250const std::vector<DicoValue> & DicoValue::getVecChild() const{
251 return p_vecChild;
252}
253
255
257std::vector<DicoValue> & DicoValue::getVecChild(){
258 return p_vecChild;
259}
260
262
264const std::map<PString, DicoValue> & DicoValue::getMapChild() const{
265 return p_mapChild;
266}
267
269
271std::map<PString, DicoValue> & DicoValue::getMapChild(){
272 return p_mapChild;
273}
274
276
279 p_value = other.p_value;
280 p_key = other.p_key;
281 p_vecChild = other.p_vecChild;
282 p_mapChild = other.p_mapChild;
283}
284
286
290 parser.setEscapeChar('\\');
291 parser.setWhiteSpace(" \t\n");
292 parser.setSeparator(",:{}\"");
293 bool isRunning(true);
294 while(!parser.isEndOfFile() && isRunning){
295 if(parseDicoValue(parser, isRunning)){
296 parser.skipWhiteSpace();
297 }else{
298 errorAt(parser, isRunning, "Cannot parse dico value");
299 }
300 }
301 return isRunning;
302}
303
305
309bool DicoValue::parseDicoValue(PFileParser & parser, bool & isRunning){
310 if(parseListOrMap(parser, isRunning)){return true;}
311 else if(parseList(parser, isRunning)){return true;}
312 else{
313 PString nextKeyOrValue;
314 bool isParsingStrOk(parseString(nextKeyOrValue, parser));
315 if(nextKeyOrValue == ""){
316 nextKeyOrValue = parser.getStrComposedOf("abcdefghijklmnopqsrtuvwxyzABCDEFGHIJKLMNOPQSRTUVWXYZ0123456789._-+");
317 if(nextKeyOrValue == "" && !isParsingStrOk){
318 return errorAt(parser, isRunning,
319 "Expecting a string or a keywork composed of letters, number, underscore, slash or minus");
320 }
321 }
322 if(parser.isMatch(":")){ //It was a key for a dictionnary
323// std::cerr << "DicoValue::parseDicoValue : find key '"<<nextKeyOrValue<<"'" << std::endl;
324 p_key = nextKeyOrValue;
325 if(!parseDicoValue(parser, isRunning)){
326 return errorAt(parser, isRunning, "Cannot parse value");
327 }
328 }else{ //It was a value
329 p_value = nextKeyOrValue;
330 }
331 parser.skipWhiteSpace();
332 }
333 return true;
334}
335
337
341bool DicoValue::parseListOrMap(PFileParser & parser, bool & isRunning){
342 if(!parser.isMatch("{")){return false;} //If this is not a {, then it is not a list or a map
343 while(!parser.isEndOfFile() && !parser.isMatch("}") && isRunning){
344 DicoValue dv;
345 if(dv.parseDicoValue(parser, isRunning)){
346 if(dv.p_key != ""){ //It is a dico entry
347// std::cerr << "DicoValue::parseListOrMap : loadParser add DicoValue with key '"<<dv.p_key<<"'" << std::endl;
348 p_mapChild[dv.p_key] = dv;
349 }else{ //It is a value
350 p_vecChild.push_back(dv);
351 }
352 }else{
353 errorAt(parser, isRunning, "Cannot parse dico value");
354 }
355 if(parser.isMatch(",")){}
356 else if(parser.isMatchRewind("}")){}
357 else{
358 return errorAt(parser, isRunning, "Expect ',' or '}' after value");
359 }
360 }
361
362 return true;
363}
364
366
370bool DicoValue::parseList(PFileParser & parser, bool & isRunning){
371 if(!parser.isMatch("[")){return false;} //If this is not a {, then it is not a list or a map
372
373 while(!parser.isEndOfFile() && !parser.isMatch("]") && isRunning){
374 DicoValue dv;
375 if(dv.parseDicoValue(parser, isRunning)){
376 if(dv.p_key != ""){ //It is a dico entry
377// std::cerr << "DicoValue::parseListOrMap : loadParser add DicoValue with key '"<<dv.p_key<<"'" << std::endl;
378 p_mapChild[dv.p_key] = dv;
379 }else{ //It is a value
380 p_vecChild.push_back(dv);
381 }
382 }else{
383 errorAt(parser, isRunning, "Cannot parse list value");
384 }
385 if(parser.isMatch(",")){}
386 else if(parser.isMatchRewind("]")){}
387 else{
388 return errorAt(parser, isRunning, "Expect ',' or ']' after value");
389 }
390 }
391
392 return true;
393}
394
396
400bool DicoValue::parseString(PString & parsedString, PFileParser & parser){
401 if(parser.isMatch("\"")){
402 parsedString = parser.getUntilKeyWithoutPatern("\"");
403 return true;
404 }else if(parser.isMatch("'")){
405 parsedString = parser.getUntilKeyWithoutPatern("'");
406 return true;
407 }else{
408 parsedString = "";
409 return false;
410 }
411}
412
414
419bool DicoValue::errorAt(PFileParser & parser, bool & isRunning, const PString & errorMsg){
420 isRunning = false;
421 std::cerr << "DicoValue::errorAt : " << parser.getLocation() << std::endl;
422 std::cerr << "\t" << errorMsg << std::endl;
423 std::cerr << "Wrong token : '"<<parser.getNextToken()<<"'" << std::endl;
424 return true;
425}
426
428
435PString DicoValue::saveRecurse(const PString & indentation, const PString & valueDecorator, PString baseIndentation, PString baseNewLine, bool isInList) const{
436 PString out(""), newIndentation(indentation);
437 if(p_key != "" || isInList){
438 newIndentation = indentation + baseIndentation;
439 }
440 if(p_mapChild.size() != 0lu){
441 if(p_key != ""){out += baseNewLine + indentation +valueDecorator + p_key + valueDecorator + ": {";}
442 else if(isInList){out += baseNewLine+indentation+"{";}
443 PString comma("");
444 for(MapDicoValue::const_iterator it(p_mapChild.begin()); it != p_mapChild.end(); ++it){
445 out += comma;
446 out += it->second.saveRecurse(newIndentation, valueDecorator, baseIndentation, baseNewLine);
447 comma = ",";
448 }
449 if(p_key != ""){out += baseNewLine+indentation+"}";}
450 else if(isInList){out += baseNewLine+indentation+"}";}
451 }else if(p_vecChild.size() != 0lu){
452 if(p_key != ""){out += baseNewLine + indentation + valueDecorator + p_key + valueDecorator + ": [";}
453 PString comma("");
454 for(VecDicoValue::const_iterator it(p_vecChild.begin()); it != p_vecChild.end(); ++it){
455 out += comma;
456 out += it->saveRecurse(newIndentation, valueDecorator, baseIndentation, baseNewLine, true);
457 comma = ", ";
458 }
459 if(p_key != ""){out += "]";}
460 }else{
461 PString valueToSave(p_value);
462 if(valueDecorator != ""){
463 valueToSave = valueDecorator + p_value + valueDecorator;
464 }else if(p_value.find(" \t\n':/")){
465 valueToSave = "\"" + p_value + "\"";
466 }
467 if(p_key != ""){out += baseNewLine + indentation + valueDecorator + p_key + valueDecorator + ": "+valueToSave;}
468 else{out += valueToSave;}
469 }
470 return out;
471}
472
473
void setVecChild(const std::vector< DicoValue > &vecChild)
Sets the vecChild of the DicoValue.
PString toString(const PString &valueDecorator="", PString baseIndentation="\t", PString baseNewLine="\n") const
Convert the DicoValue into a string.
Definition DicoValue.cpp:75
const PString & getKey() const
Gets the key of the DicoValue.
bool isKeyExist(const PString &key) const
Say if the given key exists in the map of children.
PString p_value
Value of the current entry.
Definition DicoValue.h:70
void copyDicoValue(const DicoValue &other)
Copy Function of class DicoValue.
void setKey(const PString &key)
Sets the key of the DicoValue.
bool parseListOrMap(PFileParser &parser, bool &isRunning)
Parse a list or a map.
bool fromString(const PString &content)
Create a DicoValue from a PString.
Definition DicoValue.cpp:62
bool hasKey() const
Say if the DicoValue has a key.
Definition DicoValue.cpp:92
const std::vector< DicoValue > & getVecChild() const
Gets the vecChild of the DicoValue.
DicoValue & operator=(const DicoValue &other)
Operator = of class DicoValue.
Definition DicoValue.cpp:31
virtual ~DicoValue()
Destructor of class DicoValue.
Definition DicoValue.cpp:23
const DicoValue * getMap(const PString &key) const
Get a DicoValue in the map of the current one.
bool save(const PPath &fileName, const PString &valueDecorator="", PString baseIndentation="\t", PString baseNewLine="\n") const
Save the DicoValue with a text file.
Definition DicoValue.cpp:53
void setValue(const PString &value)
Sets the value of the DicoValue.
bool hasMap() const
Say if the DicoValue has a map of children.
Definition DicoValue.cpp:97
void print() const
Print the DicoValue.
Definition DicoValue.cpp:83
PString p_key
Key of the current entry.
Definition DicoValue.h:72
DicoValue()
Constructor of class DicoValue.
Definition DicoValue.cpp:11
std::map< PString, DicoValue > p_mapChild
Map of sub DicoValue.
Definition DicoValue.h:76
const std::map< PString, DicoValue > & getMapChild() const
Gets the mapChild of the DicoValue.
std::vector< DicoValue > p_vecChild
Vector of sub DicoValue.
Definition DicoValue.h:74
T getValue() const
Convert the value of the current DicoValue into a type.
bool parseDicoValue(PFileParser &parser, bool &isRunning)
Parse a DicoValue with a text file.
bool parseString(PString &parsedString, PFileParser &parser)
Parse a string.
bool loadParser(PFileParser &parser)
Load the DicoValue with a parser.
bool errorAt(PFileParser &parser, bool &isRunning, const PString &errorMsg)
Print the parsing error.
PString getString() const
Get a string value without the first and/or last quote or double quote in there are some.
PString saveRecurse(const PString &indentation, const PString &valueDecorator, PString baseIndentation, PString baseNewLine, bool isInList=false) const
Save the DicoValue with a text file.
bool load(const PPath &fileName)
Load the DicoValue with a text file.
Definition DicoValue.cpp:40
const DicoValue * getElementInVecWhere(const PString &key, const PString &value) const
Get the element of a vector of children of the current DicoValue which has 'key'.value = value.
void setMapChild(const std::map< PString, DicoValue > &mapChild)
Sets the mapChild of the DicoValue.
bool hasVec() const
Say if the DicoValue has a vector of children.
bool parseList(PFileParser &parser, bool &isRunning)
Parse a list or a map.
classe qui permet de parser des fichiers texte en renvoyant les tokens les uns après les autres
Definition PFileParser.h:20
void setSeparator(const PString &separator)
Initialise la liste des caractères séparateurs.
bool open(const PPath &fileName)
Fonction qui ouvre le fichier que l'on va parser.
PString getNextToken()
Get the next token.
PString getUntilKeyWithoutPatern(const PString &patern)
Renvoie la chaine de caractère du caractère courant jusqu'à patern exclu.
void setEscapeChar(char escapeChar)
Sets the escape character of the PFileParser.
PString getStrComposedOf(const PString &charset)
Get string composed of the characters in the string charset.
void setWhiteSpace(const PString &whiteSpace)
Initialise la liste des caractères blancs.
bool isMatchRewind(const PString &patern)
Do a isMatch and then go back at the previous position.
bool isMatch(const PString &patern)
Says if the patern match with the current caracters of the PFileParser.
PLocation getLocation() const
Fonction qui renvoie la PLocation du PFileParser.
void skipWhiteSpace()
Skip the white space if there is at the current caracter position.
void setFileContent(const PString &fileContent)
Set the file content.
bool isEndOfFile() const
Dit si on est à la fin du fichier.