Awali
Another Weighted Automata library
utils.hh
Go to the documentation of this file.
1 // This file is part of Awali.
2 // Copyright 2016-2022 Sylvain Lombardy, Victor Marsault, Jacques Sakarovitch
3 //
4 // Awali is a free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 
17 #ifndef AWALI_JSON_UTILS_HH
18 #define AWALI_JSON_UTILS_HH
19 
20 #include<iostream>
21 #include<vector>
22 #include<limits>
23 #include<iomanip>
24 #include<sstream>
26 
27 #define __SUPPRESS_UNUSED_WARNING__(a) (void)a;
28 
29 
30 namespace awali {
31  namespace internal {
32 
41  static inline
42  std::ostream& tabs(std::ostream& o, int n) {
44  for(int i=0; i<n; i++)
45  o << " ";
46  return o;
47  }
48 
62  static inline
63  std::ostream& js_formate(std::ostream& o, std::istream& i) {
65  int depth=0;
66  char c;
67  bool inopen=false;
68  bool instring=false;
69  while(! i.eof()) {
70  i.get(c);
71  switch(c) {
72  case '\t': break;
73  case '{':
74  if(!instring) {
75  inopen=true;
76  if(depth>0)
77  o << std::endl;
78  tabs(o,depth++);
79  }
80  o << c;
81  break;
82  case '}':
83  if(!instring) {
84  --depth;
85  if(depth<0)
86  return o;
87  if(!inopen){
88  o << std::endl;
89  tabs(o,depth);
90  }
91  inopen=false;
92  }
93  o << c;
94  break;
95  case '\n' :
96  o << std::endl << ' ';
97  tabs(o,depth-1);
98  break;
99  case '"' :
100  instring=!instring;
101  default :
102  o << c;
103  }
104  }
105  return o;
106  }
107 
115  static inline
116  void check(std::istream& i, char e, std::string oth="") {
118  char c;
119  do {
120  i>>c;
121  }while(c==' ' || c== '\n' || c== '\t');
122  //std::cerr << c << '&' << std::endl;
123  if(c!=e){
124  std::ostringstream os;
125  os << "parser expects ";
126  for(auto o : oth)
127  os << o << " or ";
128  os << e << " gets " << c;
129  throw parse_exception(i, os.str());
130  }
131  }
132 
138  static inline
139  char peek(std::istream& i) {
141  char c;
142  while(1) {
143  c=i.peek();
144  if(c!=' ' && c!= '\n' && c!= '\t')
145  return c;
146  i.get(c);
147  }
148  }
149 
150 
151  static inline
152  std::string parsestring(std::istream& i) {
154  char c;
155  i >> c;
156  if(c!='"')
157  throw parse_exception(i,"parser \"");
158  std::ostringstream o;
159  while(true) {
160  i.get(c);
161  if(c=='"')
162  break;
163  if(c=='\\') {
164  i.get(c);
165  switch(c) {
166  case '\\':
167  case '"':
168  std::cerr << "found " << c;
169  o << c;
170  break;
171  case 'b': o << '\b'; std::cerr << "found \\b"; break;
172  case 'n': o << '\n'; break;
173  case 'f': o << '\f'; break;
174  case 'r': o << '\r'; break;
175  case 't': o << '\t'; break;
176  case 'u': {
177  char c1,c2,c3,c4;
178  i >> c1;
179  i >> c2;
180  i >> c3;
181  i >> c4;
182  if(c1=='0' && c2 =='0' && (c3 == '0' || c3 == '1')) {
183  c = (c3 == '1')?16:0;
184  if ('0'<= c4 && c4 <= '9')
185  c += (c4-'0');
186  else if ('a'<= c4 && c4 <= 'f')
187  c += 10 + c4 -'a';
188  else if ('A'<= c4 && c4 <= 'F')
189  c += 10 + c4 -'A';
190  else
191  throw parse_exception(i, "Only unicode escaped character "
192  "below 1F are supported, i.e., of the form \\u00YZ, where "
193  "Y = 0 or 1.");
194  std::cerr << "found " << std::hex << (int) c;
195  o << c;
196  }
197  else
198  throw parse_exception(i, "Only unicode escaped character below "
199  "1F are supported, i.e., of the form \\u00YZ, where Y = 0 or "
200  "1.");
201 
202  }
203  break;
204  default:
205  o << '\\' << c;
206  }
207  }
208  else
209  o << c;
210  }
211  return o.str();
212  }
213 
214 
215  static inline
216  char parsecst(std::istream& i) {
218  std::string s;
219  int l;
220  switch(i.peek()) {
221  case 'n' : case 't': l=4; break;
222  case 'f' : l=5; break;
223  default:
224  throw parse_exception(i,"parser cst");
225  }
226  for(int n=0; n<l; ++n) {
227  char c;
228  i.get(c) ;
229  s.append(1,c);
230  }
231  if(s!="true" && s!="none" && s!="null" && s!= "false")
232  throw parse_exception(i,"parser cst");
233  return s[0];
234  }
235 
236  static inline
237  int parseint(std::istream& i) {
239  int x;
240  i >> x;
241  return x;
242  }
243 
244  static inline
245  std::string get_first_attr(std::istream& i) {
247  check(i, '{');
248  std::string attr = parsestring(i);
249  check(i, ':');
250  return attr;
251  }
252 
253  static inline
254  void parseignore(std::istream& i) {
256  switch(peek(i)) {
257  case '"':
258  parsestring(i);
259  if(peek(i)!=':')
260  return;
261  check(i,':');
262  parseignore(i);
263  return;
264  case '{':
265  check(i,'{');
266  while(peek(i)!='}')
267  parseignore(i);
268  check(i,'}');
269  return;
270  case '[' :
271  check(i,'[');
272  while(1) {
273  parseignore(i);
274  if(peek(i)!=',')
275  break;
276  check(i,',');
277  }
278  check(i,']');
279  return;
280  case 't': case 'n' : case 'f':
281  parsecst(i);
282  return;
283  default :
284  throw parse_exception(i,"Parse ignore");
285  }
286  }
287 
288 
289  static std::vector<std::string> init_converter () {
290  std::vector<std::string> res;
291  for (int i = std::numeric_limits<char>::min();
292  i <= (int) std::numeric_limits<char>::max();
293  i++)
294  res.push_back("");
295  for (int i = std::numeric_limits<char>::min();
297  i++)
298  {
299  char c = (char) i;
300  std::stringstream o;
301  switch (c) {
302  case '\b': o << "\\b"; break;
303  case '\f': o << "\\f"; break;
304  case '\n': o << "\\n"; break;
305  case '\r': o << "\\r"; break;
306  case '\t': o << "\\t"; break;
307  case '"': o << "\\\""; break;
308  case '\\': o << "\\\\"; break;
309  default:
310  if ('\x00' <= c && c <= '\x1f') {
311  o << "\\u"
312  << std::hex << std::setw(4) << std::setfill('0') << (int)c;
313  }
314  else
315  o << c;
316  }
317  res[(unsigned char) c] = o.str();
318  }
319  return res;
320  }
321 
322  static std::vector<std::string> const converter = init_converter();
323 } // end of namespace awali::internal
324 
325 namespace json {
326 
327  inline std::string const& escape(char c) {
328  return internal::converter[(unsigned char) c];
329  }
330 
331 
332  inline std::string unescape(std::string const& str) {
333  std::stringstream ss(str);
334  std::string res= internal::parsestring(ss);
335  if (ss.eof())
336  return res;
337  throw parse_exception(ss, "Given string contains more than a json "
338  "string.");
339  }
340 
341 
342  inline
343  std::ostream& escape_and_print(std::ostream& o,
344  std::string const & str)
345  {
347  o << '"';
348  for (char c : str)
349  o << escape(c);
350  return (o << '"');
351  }
352 
353  inline std::string escape (std::string const& str) {
354  __SUPPRESS_UNUSED_WARNING__((std::string(*)(std::string const&))escape)
355  std::stringstream ss;
356  escape_and_print(ss,str);
357  return ss.str();
358  }
359 
360 
361 }// end of namespace awali::json
362 }// end of namespace awali
363 
364 #undef __SUPPRESS_UNUSED_WARNING__
365 #endif //AWALI_JSON_UTILS_HH
366 
Definition: node.hh:132
std::ostream & json(automaton_t aut, std::ostream &out)
static std::ostream & tabs(std::ostream &o, int n)
prints spaces
Definition: utils.hh:42
static char parsecst(std::istream &i)
Definition: utils.hh:216
static char peek(std::istream &i)
peeks the next character
Definition: utils.hh:139
static std::vector< std::string > const converter
Definition: utils.hh:322
static std::ostream & js_formate(std::ostream &o, std::istream &i)
formates a json file
Definition: utils.hh:63
static std::string parsestring(std::istream &i)
Definition: utils.hh:152
static int parseint(std::istream &i)
Definition: utils.hh:237
static std::string get_first_attr(std::istream &i)
Definition: utils.hh:245
static std::vector< std::string > init_converter()
Definition: utils.hh:289
static void parseignore(std::istream &i)
Definition: utils.hh:254
static void check(std::istream &i, char e, std::string oth="")
checks the next character
Definition: utils.hh:116
std::string const & escape(char c)
Definition: utils.hh:327
std::string unescape(std::string const &str)
Definition: utils.hh:332
std::ostream & escape_and_print(std::ostream &o, std::string const &str)
Definition: utils.hh:343
ATTRIBUTE_CONST int max(int a, int b)
Definition: arith.hh:54
ATTRIBUTE_CONST int min(int a, int b)
Definition: arith.hh:48
Main namespace of Awali.
Definition: ato.hh:22
Exceptions thrown during parsing.
Definition: parse_exception.hh:26
#define __SUPPRESS_UNUSED_WARNING__(a)
Definition: utils.hh:27