28 #include <boost/lexical_cast.hpp> 29 #include <boost/algorithm/string/predicate.hpp> 33 #define EPEE_JSON_RECURSION_LIMIT_INTERNAL 100 37 using namespace misc_utils::parse;
42 #define CHECK_ISSPACE() if(!epee::misc_utils::parse::isspace(*it)){ ASSERT_MES_AND_THROW("Wrong JSON character at: " << std::string(it, buf_end));} 48 template<
class t_storage>
49 inline void run_handler(
typename t_storage::hsection current_section, std::string::const_iterator& sec_buf_begin, std::string::const_iterator buf_end, t_storage& stg,
unsigned int recursion)
53 std::string::const_iterator sub_element_start;
58 match_state_lookup_for_section_start,
59 match_state_lookup_for_name,
60 match_state_waiting_separator,
61 match_state_wonder_after_separator,
62 match_state_wonder_after_value,
63 match_state_wonder_array,
64 match_state_array_after_value,
65 match_state_array_waiting_value,
71 array_mode_undifined = 0,
78 match_state
state = match_state_lookup_for_section_start;
79 array_mode array_md = array_mode_undifined;
80 std::string::const_iterator it = sec_buf_begin;
81 for(;it != buf_end;it++)
85 case match_state_lookup_for_section_start:
87 state = match_state_lookup_for_name;
90 case match_state_lookup_for_name:
95 state = match_state_waiting_separator;
106 case match_state_waiting_separator:
108 state = match_state_wonder_after_separator;
111 case match_state_wonder_after_separator:
118 state = match_state_wonder_after_value;
121 boost::string_ref val;
122 bool is_v_float =
false;
bool is_signed =
false;
129 int64_t nval = strtoll(val.data(), NULL, 10);
130 if (errno)
throw std::runtime_error(
"Invalid number: " +
std::string(val));
131 stg.set_value(
name, nval, current_section);
135 uint64_t nval = strtoull(val.data(), NULL, 10);
136 if (errno)
throw std::runtime_error(
"Invalid number: " +
std::string(val));
137 stg.set_value(
name, nval, current_section);
142 double nval = strtod(val.data(), NULL);
143 if (errno)
throw std::runtime_error(
"Invalid number: " +
std::string(val));
144 stg.set_value(
name, nval, current_section);
146 state = match_state_wonder_after_value;
147 }
else if(isalpha(*it) )
149 boost::string_ref word;
151 if(boost::iequals(word,
"null"))
153 state = match_state_wonder_after_value;
155 }
else if(boost::iequals(word,
"true"))
157 stg.set_value(
name,
true, current_section);
158 state = match_state_wonder_after_value;
159 }
else if(boost::iequals(word,
"false"))
161 stg.set_value(
name,
false, current_section);
162 state = match_state_wonder_after_value;
169 run_handler(new_sec, it, buf_end, stg, recursion + 1);
170 state = match_state_wonder_after_value;
173 state = match_state_wonder_array;
176 case match_state_wonder_after_value:
178 state = match_state_lookup_for_name;
186 case match_state_wonder_array:
196 h_array = stg.insert_first_section(
name, new_sec, current_section);
198 run_handler(new_sec, it, buf_end, stg, recursion + 1);
199 state = match_state_array_after_value;
200 array_md = array_mode_sections;
206 h_array = stg.insert_first_value(
name,
std::move(val), current_section);
208 state = match_state_array_after_value;
209 array_md = array_mode_string;
212 boost::string_ref val;
213 bool is_v_float =
false;
bool is_signed_val =
false;
220 int64_t nval = strtoll(val.data(), NULL, 10);
221 if (errno)
throw std::runtime_error(
"Invalid number: " +
std::string(val));
222 h_array = stg.insert_first_value(
name, nval, current_section);
226 uint64_t nval = strtoull(val.data(), NULL, 10);
227 if (errno)
throw std::runtime_error(
"Invalid number: " +
std::string(val));
228 h_array = stg.insert_first_value(
name, nval, current_section);
234 double nval = strtod(val.data(), NULL);
235 if (errno)
throw std::runtime_error(
"Invalid number: " +
std::string(val));
236 h_array = stg.insert_first_value(
name, nval, current_section);
240 state = match_state_array_after_value;
241 array_md = array_mode_numbers;
244 array_md = array_mode_undifined;
245 state = match_state_wonder_after_value;
246 }
else if(isalpha(*it) )
248 boost::string_ref word;
250 if(boost::iequals(word,
"true"))
252 h_array = stg.insert_first_value(
name,
true, current_section);
254 state = match_state_array_after_value;
255 array_md = array_mode_booleans;
256 }
else if(boost::iequals(word,
"false"))
258 h_array = stg.insert_first_value(
name,
false, current_section);
260 state = match_state_array_after_value;
261 array_md = array_mode_booleans;
266 case match_state_array_after_value:
268 state = match_state_array_waiting_value;
272 array_md = array_mode_undifined;
273 state = match_state_wonder_after_value;
276 case match_state_array_waiting_value:
279 case array_mode_sections:
283 bool res = stg.insert_next_section(h_array, new_sec);
285 run_handler(new_sec, it, buf_end, stg, recursion + 1);
286 state = match_state_array_after_value;
289 case array_mode_string:
294 bool res = stg.insert_next_value(h_array,
std::move(val));
296 state = match_state_array_after_value;
299 case array_mode_numbers:
302 boost::string_ref val;
303 bool is_v_float =
false;
bool is_signed_val =
false;
305 bool insert_res =
false;
311 int64_t nval = strtoll(val.data(), NULL, 10);
312 if (errno)
throw std::runtime_error(
"Invalid number: " +
std::string(val));
313 insert_res = stg.insert_next_value(h_array, nval);
317 uint64_t nval = strtoull(val.data(), NULL, 10);
318 if (errno)
throw std::runtime_error(
"Invalid number: " +
std::string(val));
319 insert_res = stg.insert_next_value(h_array, nval);
324 double nval = strtod(val.data(), NULL);
325 if (errno)
throw std::runtime_error(
"Invalid number: " +
std::string(val));
326 insert_res = stg.insert_next_value(h_array, nval);
329 state = match_state_array_after_value;
330 array_md = array_mode_numbers;
333 case array_mode_booleans:
336 boost::string_ref word;
338 if(boost::iequals(word,
"true"))
340 bool r = stg.insert_next_value(h_array,
true);
342 state = match_state_array_after_value;
343 }
else if(boost::iequals(word,
"false"))
345 bool r = stg.insert_next_value(h_array,
false);
347 state = match_state_array_after_value;
352 case array_mode_undifined:
357 case match_state_error:
392 template<
class t_storage>
395 std::string::const_iterator sec_buf_begin = buff_json.begin();
398 run_handler(
nullptr, sec_buf_begin, buff_json.end(), stg, 0);
401 catch(
const std::exception& ex)
403 MERROR(
"Failed to parse json, what: " << ex.what());
408 MERROR(
"Failed to parse json");
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
#define ASSERT_MES_AND_THROW(message)
#define EPEE_JSON_RECURSION_LIMIT_INTERNAL
bool load_from_json(const std::string &buff_json, t_storage &stg)
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)
unsigned __int64 uint64_t
void run_handler(typename t_storage::hsection current_section, std::string::const_iterator &sec_buf_begin, std::string::const_iterator buf_end, t_storage &stg, unsigned int recursion)
void match_word2(std::string::const_iterator &star_end_string, std::string::const_iterator buf_end, boost::string_ref &val)
const T & move(const T &t)