Electroneum
parserse_base_utils.h
Go to the documentation of this file.
1 // Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above copyright
9 // notice, this list of conditions and the following disclaimer in the
10 // documentation and/or other materials provided with the distribution.
11 // * Neither the name of the Andrey N. Sabelnikov nor the
12 // names of its contributors may be used to endorse or promote products
13 // derived from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
19 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 //
26 
27 
28 
29 #pragma once
30 
31 #include <algorithm>
32 #include <boost/utility/string_ref.hpp>
33 
34 namespace epee
35 {
36 namespace misc_utils
37 {
38  namespace parse
39  {
40  // 1: digit
41  // 2: .eE (floating point)
42  // 4: alpha
43  // 8: whitespace
44  // 16: allowed in float but doesn't necessarily mean it's a float
45  // 32: \ and " (end of verbatim string)
46  static const constexpr uint8_t lut[256]={
47  0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 0, 0, // 16
48  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32
49  8, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 16, 18, 0, // 48
50  17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, // 64
51  0, 4, 4, 4, 4, 22, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 80
52  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 32, 0, 0, 0, // 96
53  0, 4, 4, 4, 4, 22, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 112
54  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, // 128
55  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
58  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
59  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
60  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
61  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
62  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
63  };
64 
65  inline bool isspace(char c)
66  {
67  return lut[(uint8_t)c] & 8;
68  }
69 
70  inline bool isdigit(char c)
71  {
72  return lut[(uint8_t)c] & 1;
73  }
74 
76  {
77  static const char escaped[] = "\b\f\n\r\t\v\"\\/";
78  std::string::const_iterator it = std::find_first_of(src.begin(), src.end(), escaped, escaped + sizeof(escaped));
79  if (it == src.end())
80  return src;
81 
83  res.reserve(2 * src.size());
84  res.assign(src.begin(), it);
85  for(; it!=src.end(); ++it)
86  {
87  switch(*it)
88  {
89  case '\b': //Backspace (ascii code 08)
90  res+="\\b"; break;
91  case '\f': //Form feed (ascii code 0C)
92  res+="\\f"; break;
93  case '\n': //New line
94  res+="\\n"; break;
95  case '\r': //Carriage return
96  res+="\\r"; break;
97  case '\t': //Tab
98  res+="\\t"; break;
99  case '\v': //Vertical tab
100  res+="\\v"; break;
101  //case '\'': //Apostrophe or single quote
102  // res+="\\'"; break;
103  case '"': //Double quote
104  res+="\\\""; break;
105  case '\\': //Backslash caracter
106  res+="\\\\"; break;
107  case '/': //Backslash caracter
108  res+="\\/"; break;
109  default:
110  res.push_back(*it);
111  }
112  }
113  return res;
114  }
115  /*
116 
117  \b Backspace (ascii code 08)
118  \f Form feed (ascii code 0C)
119  \n New line
120  \r Carriage return
121  \t Tab
122  \v Vertical tab
123  \' Apostrophe or single quote
124  \" Double quote
125  \\ Backslash character
126 
127  */
128  inline void match_string2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val)
129  {
130  bool escape_mode = false;
131  std::string::const_iterator it = star_end_string;
132  ++it;
133  std::string::const_iterator fi = it;
134  while (fi != buf_end && ((lut[(uint8_t)*fi] & 32)) == 0)
135  ++fi;
136  val.assign(it, fi);
137  val.reserve(std::distance(star_end_string, buf_end));
138  it = fi;
139  for(;it != buf_end;it++)
140  {
141  if(escape_mode/*prev_ch == '\\'*/)
142  {
143  switch(*it)
144  {
145  case 'b': //Backspace (ascii code 08)
146  val.push_back(0x08);break;
147  case 'f': //Form feed (ascii code 0C)
148  val.push_back(0x0C);break;
149  case 'n': //New line
150  val.push_back('\n');break;
151  case 'r': //Carriage return
152  val.push_back('\r');break;
153  case 't': //Tab
154  val.push_back('\t');break;
155  case 'v': //Vertical tab
156  val.push_back('\v');break;
157  case '\'': //Apostrophe or single quote
158  val.push_back('\'');break;
159  case '"': //Double quote
160  val.push_back('"');break;
161  case '\\': //Backslash character
162  val.push_back('\\');break;
163  case '/': //Slash character
164  val.push_back('/');break;
165  default:
166  val.push_back(*it);
167  LOG_PRINT_L0("Unknown escape sequence :\"\\" << *it << "\"");
168  }
169  escape_mode = false;
170  }else if(*it == '"')
171  {
172  star_end_string = it;
173  return;
174  }else if(*it == '\\')
175  {
176  escape_mode = true;
177  }
178  else
179  {
180  val.push_back(*it);
181  }
182  }
183  ASSERT_MES_AND_THROW("Failed to match string in json entry: " << std::string(star_end_string, buf_end));
184  }
185  inline bool match_string(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val)
186  {
187  try
188  {
189 
190  match_string2(star_end_string, buf_end, val);
191  return true;
192  }
193  catch(...)
194  {
195  return false;
196  }
197  }
198  inline void match_number2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val, bool& is_float_val, bool& is_signed_val)
199  {
200  val.clear();
201  uint8_t float_flag = 0;
202  is_signed_val = false;
203  size_t chars = 0;
204  std::string::const_iterator it = star_end_string;
205  if (it != buf_end && *it == '-')
206  {
207  is_signed_val = true;
208  ++chars;
209  ++it;
210  }
211  for(;it != buf_end;it++)
212  {
213  const uint8_t flags = lut[(uint8_t)*it];
214  if (flags & 16)
215  {
216  float_flag |= flags;
217  ++chars;
218  }
219  else
220  {
221  val = boost::string_ref(&*star_end_string, chars);
222  if(val.size())
223  {
224  star_end_string = --it;
225  is_float_val = !!(float_flag & 2);
226  return;
227  }
228  else
229  ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end));
230  }
231  }
232  ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end));
233  }
234  inline bool match_number(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val)
235  {
236  try
237  {
238  bool is_v_float = false;bool is_signed_val = false;
239  match_number2(star_end_string, buf_end, val, is_v_float, is_signed_val);
240  return !is_v_float;
241  }
242  catch(...)
243  {
244  return false;
245  }
246  }
247  inline void match_word2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val)
248  {
249  val.clear();
250 
251  for(std::string::const_iterator it = star_end_string;it != buf_end;it++)
252  {
253  if (!(lut[(uint8_t)*it] & 4))
254  {
255  val = boost::string_ref(&*star_end_string, std::distance(star_end_string, it));
256  if(val.size())
257  {
258  star_end_string = --it;
259  return;
260  }else
261  ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end));
262  }
263  }
264  ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end));
265  }
266  inline bool match_word(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val)
267  {
268  try
269  {
270  match_word2(star_end_string, buf_end, val);
271  return true;
272  }
273  catch(...)
274  {
275  return false;
276  }
277  }
278  inline bool match_word_with_extrasymb(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val)
279  {
280  val.clear();
281 
282  for(std::string::const_iterator it = star_end_string;it != buf_end;it++)
283  {
284  if(!isalnum(*it) && *it != '-' && *it != '_')
285  {
286  val.assign(star_end_string, it);
287  if(val.size())
288  {
289  star_end_string = --it;
290  return true;
291  }else
292  return false;
293  }
294  }
295  return false;
296  }
297  inline bool match_word_til_equal_mark(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string::const_iterator& word_end)
298  {
299  word_end = star_end_string;
300 
301  for(std::string::const_iterator it = star_end_string;it != buf_end;it++)
302  {
303  if(isspace(*it))
304  {
305 
306  continue;
307  }else if( *it == '=' )
308  {
309  star_end_string = it;
310  word_end = it;
311  return true;
312  }
313  }
314  return false;
315  }
316  }
317 }
318 }
const char * res
Definition: hmac_keccak.cpp:41
#define ASSERT_MES_AND_THROW(message)
Definition: misc_log_ex.h:172
::std::string string
Definition: gtest-port.h:1097
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
unsigned char uint8_t
Definition: stdint.h:124
bool match_word(std::string::const_iterator &star_end_string, std::string::const_iterator buf_end, boost::string_ref &val)
bool match_word_til_equal_mark(std::string::const_iterator &star_end_string, std::string::const_iterator buf_end, std::string::const_iterator &word_end)
void match_string2(std::string::const_iterator &star_end_string, std::string::const_iterator buf_end, std::string &val)
std::string transform_to_escape_sequence(const std::string &src)
void match_number2(std::string::const_iterator &star_end_string, std::string::const_iterator buf_end, boost::string_ref &val, bool &is_float_val, bool &is_signed_val)
bool match_string(std::string::const_iterator &star_end_string, std::string::const_iterator buf_end, std::string &val)
void match_word2(std::string::const_iterator &star_end_string, std::string::const_iterator buf_end, boost::string_ref &val)
bool match_number(std::string::const_iterator &star_end_string, std::string::const_iterator buf_end, boost::string_ref &val)
bool match_word_with_extrasymb(std::string::const_iterator &star_end_string, std::string::const_iterator buf_end, std::string &val)