PhoenixFileParser  1.5.1
Set of tools to ease file parsing
Loading...
Searching...
No Matches
parser_json.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
8#include "parser_json.h"
9
17
19bool parser_json_map(ConfigNode & node, PJsonParserData & data);
20
22
27bool parser_jsonErrorAt(PJsonParserData & data, const PString & errorMsg){
28 data.isRun = false;
29 std::cerr << "parser_jsonErrorAt : " << data.parser.getLocation() << std::endl;
30 std::cerr << "\t" << errorMsg << std::endl;
31 std::cerr << "Wrong token : '"<<data.parser.getNextToken()<<"'" << std::endl;
32 return true;
33}
34
36
40bool parser_jsonString(PString & str, PJsonParserData & data){
41 if(data.parser.isMatch("\"")){
42 str = "\"" + data.parser.getUntilKey("\"");
43 return true;
44 }
45 return false;
46}
47
48
50
54bool parser_json_value(PString & value, PJsonParserData & data){
55 PFileParser & parser = data.parser;
56 parser.pushPosition();
57 if(!parser_jsonString(value, data)){
58 value = parser.getStrComposedOf("abcdefghijklmnopqsrtuvwxyzABCDEFGHIJKLMNOPQSRTUVWXYZ0123456789._-+");
59 if(value == ""){
60 parser.popPosition();
61 parser.clearPosition();
62 return false;
63 }
64 }
65 if(parser.isMatchRewind(":")){
66 parser.popPosition();
67 return false;
68 }
69 parser.clearPosition();
70 return true;
71}
72
74
79 PString value;
80 if(parser_json_value(value, data)){
81 node.setValue(value);
82 node.setLineCol(data.parser.getLocation());
83 return true;
84 }
85 return false;
86}
87
89
94 PString key;
95 if(parser_jsonString(key, data)){
96 ConfigNode * child = node.addChild(key);
97 if(child == NULL){ //If the child is NULL, there is already a child named key
98 ConfigNode * prevChild = node.getChild(key.eraseFirstLastChar("\"'"));
99 std::stringstream location;
100 if(prevChild != NULL){
101 location << prevChild->getLocation();
102 }
103 return parser_jsonErrorAt(data, "key '"+key+"' already defined at " + location.str());
104 }
105 if(data.parser.isMatch(":")){
106 child->setLineCol(data.parser.getLocation());
107 //Let's parse the value of this child (map or list or value)
108 if(parser_json_map(*child, data)){}
109 else if(parser_json_list(*child, data)){}
110 else if(parser_json_value(*child, data)){}
111 else{
112 return parser_jsonErrorAt(data, "Cannot parse json value of key '"+key+"'");
113 }
114 return data.isRun;
115 }else{
116 return parser_jsonErrorAt(data, "Expect ':' after key '"+key+"'");
117 }
118 }else{
119 return parser_jsonErrorAt(data, "Expect \"key\"': ...");
120 }
121 return false;
122}
123
125
130 PFileParser & parser = data.parser;
131 if(!parser.isMatch("{")){return false;}
132 node.setLineCol(parser.getLocation());
133 while(!parser.isEndOfFile() && !parser.isMatch("}") && data.isRun){
134 //key:Map or key:list or key:value
135 if(!parser_json_key(node, data)){
136 return parser_jsonErrorAt(data, "Expect \"key\"");
137 }
138 if(parser.isMatch(",")){}
139 else if(parser.isMatchRewind("}")){}
140 else{
141 return parser_jsonErrorAt(data, "Expect ',' or '}' after key");
142 }
143 }
144 return data.isRun;
145}
146
148
153 PFileParser & parser = data.parser;
154 if(!parser.isMatch("[")){return false;}
155 node.setLineCol(parser.getLocation());
156 while(!parser.isEndOfFile() && !parser.isMatch("]") && data.isRun){
157 // On crée un enfant anonyme pour chaque élément du tableau
158 ConfigNode * child = node.addChild("");
159 if(parser_json_map(*child, data)){}
160 else if(parser_json_list(*child, data)){}
161 else{
162 PString value;
163 if(parser_json_value(value, data)){
164 child->setValue(value);
165 child->setLineCol(data.parser.getLocation());
166 }
167 }
168 if(parser.isMatch(",")){}
169 else if(parser.isMatchRewind("]")){}
170 else{
171 return parser_jsonErrorAt(data, "Expect ',' or ']' after value");
172 }
173 }
174 return data.isRun;
175}
176
178
183 PFileParser & parser = data.parser;
184 parser.getStrComposedOf(" \t\n"); //Skip all blank characters
185 if(!parser.isMatch("{")){ //It has to start as JSON
186 return !parser_jsonErrorAt(data, "JSON configuration has to start with a {");
187 }
188 node.setLineCol(data.parser.getLocation());
189 //Call the Node Parsing
190 //Map or list or value or set of keys
191 if(parser_json_map(node, data)){}
192 else if(parser_json_list(node, data)){}
193 else if(parser_json_value(node, data)){}
194 else{
195 while(!parser.isEndOfFile() && !parser.isMatchRewind("}") && data.isRun){
196 //key:Map or key:list or key:value
197 if(!parser_json_key(node, data)){
198 return !parser_jsonErrorAt(data, "Expect \"key\"");
199 }
200 if(parser.isMatch(",")){}
201 else if(parser.isMatchRewind("}")){}
202 else{
203 return !parser_jsonErrorAt(data, "Expect ',' or '}' after key");
204 }
205 }
206 }
207
208 if(!parser.isMatch("}")){ //It has to start as JSON
209 return !parser_jsonErrorAt(data, "JSON configuration has to end with a }");
210 }
211 return data.isRun;
212}
213
215
219bool parser_json(ConfigNode & main, const PPath & fileName){
220 PJsonParserData data;
221 PFileParser & parser = data.parser;
222 parser.setWhiteSpace(" \n\t");
223 parser.setSeparator(":-'\",{}[]>|");
224 parser.setEscapeChar('\\');
225 if(!parser.open(fileName)){
226 std::cerr << "parser_json : cannot open file '"<<fileName<<"'" << std::endl;
227 return false;
228 }
229 main.setFileName(fileName);
230 bool b(parser_json_fileParser(main, data));
231 return b;
232}
233
235
239bool parser_jsonString(ConfigNode & main, const PString & fileContent){
240 PJsonParserData data;
241 PFileParser & parser = data.parser;
242 parser.setWhiteSpace(" \n\t");
243 parser.setSeparator(":-'\",{}[]>|");
244 parser.setEscapeChar('\\');
245 parser.setFileContent(fileContent);
246 bool b(parser_json_fileParser(main, data));
247 return b;
248}
249
250
252
259PString toJsonSaveRecurse(const ConfigNode & node, const PString & indentation, const PString & baseIndentation, const PString & baseNewLine, bool isInList){
260 PString out(""), newIndentation(indentation);
261 const PString & name = node.getName();
262 if(name != "" || isInList){
263 newIndentation = indentation + baseIndentation;
264 }
265 const VecConfigNode & vecChild = node.getVecChild();
266 const MapConfigNode & mapChild = node.getMapChild();
267 if(mapChild.size() != 0lu){
268 if(name != ""){out += baseNewLine + indentation + name.addPrefixSuffix("\"","\"") + ": {";}
269 else if(isInList){out += baseNewLine+indentation+"{";}
270 PString comma("");
271 for(VecConfigNode::const_iterator it(vecChild.begin()); it != vecChild.end(); ++it){
272 out += comma;
273 out += toJsonSaveRecurse(**it, newIndentation, baseIndentation, baseNewLine, false);
274 comma = ",";
275 }
276 if(name != ""){out += baseNewLine+indentation+"}";}
277 else if(isInList){out += baseNewLine+indentation+"}";}
278 }else if(vecChild.size() != 0lu){
279 if(name != ""){out += baseNewLine + indentation + name.addPrefixSuffix("\"","\"") + ": [";}
280 PString comma("");
281 for(VecConfigNode::const_iterator it(vecChild.begin()); it != vecChild.end(); ++it){
282 out += comma;
283 out += toJsonSaveRecurse(**it, newIndentation, baseIndentation, baseNewLine, true);
284 comma = ", ";
285 }
286 if(name != ""){out += "]";}
287 }else{
288 if(name != ""){out += baseNewLine + indentation + name.addPrefixSuffix("\"","\"") + ": " + node.getValue().addPrefixSuffix("\"","\"");}
289 else{out += node.getValue().addPrefixSuffix("\"","\"");}
290 }
291 return out;
292}
293
295
300PString toJsonString(const ConfigNode & main, const PString & baseIndentation, const PString & baseNewLine){
301 PString out("{");
302 out += toJsonSaveRecurse(main, baseIndentation, baseIndentation, baseNewLine, false);
303 out += baseNewLine + "}";
304 return out;
305}
306
307
std::vector< ConfigNode * > VecConfigNode
Definition ConfigNode.h:74
std::map< PString, ConfigNode * > MapConfigNode
Definition ConfigNode.h:75
Configuration of values.
Definition ConfigNode.h:18
const PString & getValue() const
Gets the value of the ConfigNode.
void setValue(const PString &value)
Sets the value of the ConfigNode.
PLocation getLocation() const
Gets the location of the ConfigNode.
void setLineCol(const PLocation &location)
Set the line and the column of the current ConfigNode.
const PString & getName() const
Gets the name of the ConfigNode.
const std::vector< ConfigNode * > & getVecChild() const
Gets the vecChild of the ConfigNode.
ConfigNode * addChild(const PString &name="")
Add a child in the current ConfigNode.
ConfigNode * getChild(const PString &name)
Get the child of the given name.
const std::map< PString, ConfigNode * > & getMapChild() const
Gets the mapChild of the ConfigNode.
void setFileName(const PPath &fileName)
Set the fileName of the current ConfigNode.
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.
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.
void popPosition()
Get to the last saved position of the PFileParser in the current file.
void clearPosition()
Clear the save position of the parser in ther current file.
PString getUntilKey(const PString &patern)
Renvoie la chaine de caractère du caractère courant jusqu'à patern comprise.
PLocation getLocation() const
Fonction qui renvoie la PLocation du PFileParser.
void setFileContent(const PString &fileContent)
Set the file content.
void pushPosition()
Remember the current position of the PFileParser in the current file.
bool isEndOfFile() const
Dit si on est à la fin du fichier.
bool parser_jsonErrorAt(PJsonParserData &data, const PString &errorMsg)
Print the parsing error.
bool parser_json(ConfigNode &main, const PPath &fileName)
Load a JSON file.
bool parser_json_value(PString &value, PJsonParserData &data)
Parse a json.
PString toJsonSaveRecurse(const ConfigNode &node, const PString &indentation, const PString &baseIndentation, const PString &baseNewLine, bool isInList)
Convert the ConfigNode in a PString.
bool parser_jsonString(PString &str, PJsonParserData &data)
Parse a JSON string.
bool parser_json_key(ConfigNode &node, PJsonParserData &data)
Parse a json.
PString toJsonString(const ConfigNode &main, const PString &baseIndentation, const PString &baseNewLine)
Convert the current ConfigNode to a JSON string.
bool parser_json_map(ConfigNode &node, PJsonParserData &data)
Parse a json.
bool parser_json_fileParser(ConfigNode &node, PJsonParserData &data)
Parse a json file.
bool parser_json_list(ConfigNode &node, PJsonParserData &data)
Parse a json.
Data used to parse a toml file.
PFileParser parser
File parser to be used.
bool isRun
True to continue the parsing, false to stop.