28#include <boost/lexical_cast.hpp>
29#include <boost/utility/string_ref.hpp>
30#include <boost/algorithm/string/predicate.hpp>
34#define EPEE_JSON_RECURSION_LIMIT_INTERNAL 100
38 using namespace misc_utils::parse;
43#define CHECK_ISSPACE() if(!epee::misc_utils::parse::isspace(*it)){ ASSERT_MES_AND_THROW("Wrong JSON character at: " << std::string(it, buf_end));}
49 template<
class t_storage>
50 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)
55 typename t_storage::harray h_array =
nullptr;
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:
117 stg.set_value(
name, std::move(val), current_section);
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,
int64_t(nval), current_section);
135 uint64_t nval = strtoull(val.data(), NULL, 10);
136 if (errno)
throw std::runtime_error(
"Invalid number: " + std::string(val));
142 double nval = strtod(val.data(), NULL);
143 if (errno)
throw std::runtime_error(
"Invalid number: " + std::string(val));
144 stg.set_value(
name,
double(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;
163 }
else ASSERT_MES_AND_THROW(
"Unknown value keyword " << word);
167 typename t_storage::hsection new_sec = stg.open_section(
name, current_section,
true);
168 CHECK_AND_ASSERT_THROW_MES(new_sec,
"Failed to insert new section in json: " << std::string(it, buf_end));
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:
189 ASSERT_MES_AND_THROW(
"array of array not suppoerted yet :( sorry");
195 typename t_storage::hsection new_sec =
nullptr;
196 h_array = stg.insert_first_section(
name, new_sec, current_section);
197 CHECK_AND_ASSERT_THROW_MES(h_array&&new_sec,
"failed to create new 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);
207 CHECK_AND_ASSERT_THROW_MES(h_array,
" failed to insert values entry");
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,
int64_t(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,
uint64_t(nval), current_section);
230 CHECK_AND_ASSERT_THROW_MES(h_array,
" failed to insert values section entry");
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,
double(nval), current_section);
237 CHECK_AND_ASSERT_THROW_MES(h_array,
" failed to insert values section entry");
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);
253 CHECK_AND_ASSERT_THROW_MES(h_array,
" failed to insert values section entry");
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);
259 CHECK_AND_ASSERT_THROW_MES(h_array,
" failed to insert values section entry");
260 state = match_state_array_after_value;
261 array_md = array_mode_booleans;
263 }
else ASSERT_MES_AND_THROW(
"Unknown value keyword " << word)
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:
282 typename t_storage::hsection new_sec = NULL;
283 bool res = stg.insert_next_section(h_array, new_sec);
284 CHECK_AND_ASSERT_THROW_MES(
res&&new_sec,
"failed to insert next section");
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));
295 CHECK_AND_ASSERT_THROW_MES(
res,
"failed to insert values");
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,
int64_t(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,
uint64_t(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,
double(nval));
328 CHECK_AND_ASSERT_THROW_MES(insert_res,
"Failed to insert next value");
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);
341 CHECK_AND_ASSERT_THROW_MES(r,
" failed to insert values section entry");
342 state = match_state_array_after_value;
343 }
else if(boost::iequals(word,
"false"))
345 bool r = stg.insert_next_value(h_array,
false);
346 CHECK_AND_ASSERT_THROW_MES(r,
" failed to insert values section entry");
347 state = match_state_array_after_value;
349 else ASSERT_MES_AND_THROW(
"Unknown value keyword " << word);
352 case array_mode_undifined:
354 ASSERT_MES_AND_THROW(
"Bad array state");
357 case match_state_error:
359 ASSERT_MES_AND_THROW(
"WRONG JSON STATE");
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");
const char * res
Definition: hmac_keccak.cpp:42
void match_string2(std::string::const_iterator &star_end_string, std::string::const_iterator buf_end, std::string &val)
Definition: parserse_base_utils.cpp:95
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)
Definition: parserse_base_utils.cpp:187
bool isdigit(char c)
Definition: parserse_base_utils.h:90
void match_word2(std::string::const_iterator &star_end_string, std::string::const_iterator buf_end, boost::string_ref &val)
Definition: parserse_base_utils.cpp:223
bool load_from_json(const std::string &buff_json, t_storage &stg)
Definition: portable_storage_from_json.h:393
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)
Definition: portable_storage_from_json.h:50
TODO: (mj-xmr) This will be reduced in an another PR.
Definition: byte_slice.h:40
Definition: binary_utils.h:36
const char * name
Definition: options.c:30
#define EPEE_JSON_RECURSION_LIMIT_INTERNAL
Definition: portable_storage_from_json.h:34
#define CHECK_ISSPACE()
Definition: portable_storage_from_json.h:43
signed __int64 int64_t
Definition: stdint.h:135
unsigned __int64 uint64_t
Definition: stdint.h:136
Definition: blake256.h:36
rapidjson::Document json
Definition: transport.cpp:50