Electroneum
epee::serialization::json Namespace Reference

Functions

template<class t_storage >
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)
 
template<class t_storage >
bool load_from_json (const std::string &buff_json, t_storage &stg)
 

Function Documentation

◆ load_from_json()

template<class t_storage >
bool epee::serialization::json::load_from_json ( const std::string &  buff_json,
t_storage &  stg 
)
inline

Definition at line 393 of file portable_storage_from_json.h.

394  {
395  std::string::const_iterator sec_buf_begin = buff_json.begin();
396  try
397  {
398  run_handler(nullptr, sec_buf_begin, buff_json.end(), stg, 0);
399  return true;
400  }
401  catch(const std::exception& ex)
402  {
403  MERROR("Failed to parse json, what: " << ex.what());
404  return false;
405  }
406  catch(...)
407  {
408  MERROR("Failed to parse json");
409  return false;
410  }
411  }
#define MERROR(x)
Definition: misc_log_ex.h:73
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)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ run_handler()

template<class t_storage >
void epee::serialization::json::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 
)
inline

Definition at line 49 of file portable_storage_from_json.h.

50  {
51  CHECK_AND_ASSERT_THROW_MES(recursion < EPEE_JSON_RECURSION_LIMIT_INTERNAL, "Wrong JSON data: recursion limitation (" << EPEE_JSON_RECURSION_LIMIT_INTERNAL << ") exceeded");
52 
53  std::string::const_iterator sub_element_start;
55  typename t_storage::harray h_array = nullptr;
56  enum match_state
57  {
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,
66  match_state_error
67  };
68 
69  enum array_mode
70  {
71  array_mode_undifined = 0,
72  array_mode_sections,
73  array_mode_string,
74  array_mode_numbers,
75  array_mode_booleans
76  };
77 
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++)
82  {
83  switch (state)
84  {
85  case match_state_lookup_for_section_start:
86  if(*it == '{')
87  state = match_state_lookup_for_name;
88  else CHECK_ISSPACE();
89  break;
90  case match_state_lookup_for_name:
91  switch(*it)
92  {
93  case '"':
94  match_string2(it, buf_end, name);
95  state = match_state_waiting_separator;
96  break;
97  case '}':
98  //this is it! section ends here.
99  //seems that it is empty section
100  sec_buf_begin = it;
101  return;
102  default:
103  CHECK_ISSPACE();
104  }
105  break;
106  case match_state_waiting_separator:
107  if(*it == ':')
108  state = match_state_wonder_after_separator;
109  else CHECK_ISSPACE();
110  break;
111  case match_state_wonder_after_separator:
112  if(*it == '"')
113  {//just a named string value started
114  std::string val;
115  match_string2(it, buf_end, val);
116  //insert text value
117  stg.set_value(name, std::move(val), current_section);
118  state = match_state_wonder_after_value;
119  }else if (epee::misc_utils::parse::isdigit(*it) || *it == '-')
120  {//just a named number value started
121  boost::string_ref val;
122  bool is_v_float = false;bool is_signed = false;
123  match_number2(it, buf_end, val, is_v_float, is_signed);
124  if(!is_v_float)
125  {
126  if(is_signed)
127  {
128  errno = 0;
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);
132  }else
133  {
134  errno = 0;
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);
138  }
139  }else
140  {
141  errno = 0;
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);
145  }
146  state = match_state_wonder_after_value;
147  }else if(isalpha(*it) )
148  {// could be null, true or false
149  boost::string_ref word;
150  match_word2(it, buf_end, word);
151  if(boost::iequals(word, "null"))
152  {
153  state = match_state_wonder_after_value;
154  //just skip this,
155  }else if(boost::iequals(word, "true"))
156  {
157  stg.set_value(name, true, current_section);
158  state = match_state_wonder_after_value;
159  }else if(boost::iequals(word, "false"))
160  {
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);
164  }else if(*it == '{')
165  {
166  //sub section here
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;
171  }else if(*it == '[')
172  {//array of something
173  state = match_state_wonder_array;
174  }else CHECK_ISSPACE();
175  break;
176  case match_state_wonder_after_value:
177  if(*it == ',')
178  state = match_state_lookup_for_name;
179  else if(*it == '}')
180  {
181  //this is it! section ends here.
182  sec_buf_begin = it;
183  return;
184  }else CHECK_ISSPACE();
185  break;
186  case match_state_wonder_array:
187  if(*it == '[')
188  {
189  ASSERT_MES_AND_THROW("array of array not suppoerted yet :( sorry");
190  //mean array of array
191  }
192  if(*it == '{')
193  {
194  //mean array of sections
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;
201  }else if(*it == '"')
202  {
203  //mean array of strings
204  std::string val;
205  match_string2(it, buf_end, val);
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;
210  }else if (epee::misc_utils::parse::isdigit(*it) || *it == '-')
211  {//array of numbers value started
212  boost::string_ref val;
213  bool is_v_float = false;bool is_signed_val = false;
214  match_number2(it, buf_end, val, is_v_float, is_signed_val);
215  if(!is_v_float)
216  {
217  if (is_signed_val)
218  {
219  errno = 0;
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);
223  }else
224  {
225  errno = 0;
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);
229  }
230  CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry");
231  }else
232  {
233  errno = 0;
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);
237  CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry");
238  }
239 
240  state = match_state_array_after_value;
241  array_md = array_mode_numbers;
242  }else if(*it == ']')//empty array
243  {
244  array_md = array_mode_undifined;
245  state = match_state_wonder_after_value;
246  }else if(isalpha(*it) )
247  {// array of booleans
248  boost::string_ref word;
249  match_word2(it, buf_end, word);
250  if(boost::iequals(word, "true"))
251  {
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"))
257  {
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;
262 
263  }else ASSERT_MES_AND_THROW("Unknown value keyword " << word)
264  }else CHECK_ISSPACE();
265  break;
266  case match_state_array_after_value:
267  if(*it == ',')
268  state = match_state_array_waiting_value;
269  else if(*it == ']')
270  {
271  h_array = nullptr;
272  array_md = array_mode_undifined;
273  state = match_state_wonder_after_value;
274  }else CHECK_ISSPACE();
275  break;
276  case match_state_array_waiting_value:
277  switch(array_md)
278  {
279  case array_mode_sections:
280  if(*it == '{')
281  {
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;
287  }else CHECK_ISSPACE();
288  break;
289  case array_mode_string:
290  if(*it == '"')
291  {
292  std::string val;
293  match_string2(it, buf_end, val);
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;
297  }else CHECK_ISSPACE();
298  break;
299  case array_mode_numbers:
300  if (epee::misc_utils::parse::isdigit(*it) || *it == '-')
301  {//array of numbers value started
302  boost::string_ref val;
303  bool is_v_float = false;bool is_signed_val = false;
304  match_number2(it, buf_end, val, is_v_float, is_signed_val);
305  bool insert_res = false;
306  if(!is_v_float)
307  {
308  if (is_signed_val)
309  {
310  errno = 0;
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);
314  }else
315  {
316  errno = 0;
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);
320  }
321  }else
322  {
323  errno = 0;
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);
327  }
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;
331  }else CHECK_ISSPACE();
332  break;
333  case array_mode_booleans:
334  if(isalpha(*it) )
335  {// array of booleans
336  boost::string_ref word;
337  match_word2(it, buf_end, word);
338  if(boost::iequals(word, "true"))
339  {
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"))
344  {
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;
348  }
349  else ASSERT_MES_AND_THROW("Unknown value keyword " << word);
350  }else CHECK_ISSPACE();
351  break;
352  case array_mode_undifined:
353  default:
354  ASSERT_MES_AND_THROW("Bad array state");
355  }
356  break;
357  case match_state_error:
358  default:
359  ASSERT_MES_AND_THROW("WRONG JSON STATE");
360  }
361  }
362  }
const char * res
Definition: hmac_keccak.cpp:41
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
#define CHECK_ISSPACE()
#define ASSERT_MES_AND_THROW(message)
Definition: misc_log_ex.h:172
::std::string string
Definition: gtest-port.h:1097
#define EPEE_JSON_RECURSION_LIMIT_INTERNAL
const char * name
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
Definition: stdint.h:136
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)
Definition: gtest-port.h:1317
Definition: blake256.h:37
signed __int64 int64_t
Definition: stdint.h:135
Here is the call graph for this function:
Here is the caller graph for this function: