Electroneum
Loading...
Searching...
No Matches
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
34namespace epee
35{
36namespace 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
75 inline std::string transform_to_escape_sequence(const std::string& src)
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
82 std::string res;
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
#define LOG_PRINT_L0(x)
Definition misc_log_ex.h:99
#define ASSERT_MES_AND_THROW(message)
bool match_word_with_extrasymb(std::string::const_iterator &star_end_string, std::string::const_iterator buf_end, std::string &val)
void match_string2(std::string::const_iterator &star_end_string, std::string::const_iterator buf_end, std::string &val)
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)
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_string(std::string::const_iterator &star_end_string, std::string::const_iterator buf_end, std::string &val)
bool match_word(std::string::const_iterator &star_end_string, std::string::const_iterator buf_end, boost::string_ref &val)
std::string transform_to_escape_sequence(const std::string &src)
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)
unsigned char uint8_t
Definition stdint.h:124