BitShares-Core  5.0.0
BitShares blockchain implementation and command-line interface software
json.cpp
Go to the documentation of this file.
1 #include <fc/io/json.hpp>
3 #include <fc/io/iostream.hpp>
5 #include <fc/io/fstream.hpp>
6 #include <fc/io/sstream.hpp>
7 #include <fc/log/logger.hpp>
8 #include <cstdint>
9 #include <iostream>
10 #include <fstream>
11 #include <sstream>
12 
13 #include <boost/filesystem/fstream.hpp>
14 
15 namespace fc
16 {
17  // forward declarations of provided functions
18  template<typename T, json::parse_type parser_type> variant variant_from_stream( T& in, uint32_t max_depth );
19  template<typename T> char parseEscape( T& in );
20  template<typename T> std::string stringFromStream( T& in );
21  template<typename T> bool skip_white_space( T& in );
22  template<typename T> std::string stringFromToken( T& in );
23  template<typename T> variant_object objectFromStreamBase( T& in, std::function<std::string(T&)>& get_key, std::function<variant(T&)>& get_value );
24  template<typename T, json::parse_type parser_type> variant_object objectFromStream( T& in, uint32_t max_depth );
25  template<typename T> variants arrayFromStreamBase( T& in, std::function<variant(T&)>& get_value );
26  template<typename T, json::parse_type parser_type> variants arrayFromStream( T& in, uint32_t max_depth );
27  template<typename T, json::parse_type parser_type> variant number_from_stream( T& in );
28  template<typename T> variant token_from_stream( T& in );
29  void escape_string( const string& str, ostream& os );
30  template<typename T> void to_stream( T& os, const variants& a, json::output_formatting format, uint32_t max_depth );
31  template<typename T> void to_stream( T& os, const variant_object& o, json::output_formatting format, uint32_t max_depth );
32  template<typename T> void to_stream( T& os, const variant& v, json::output_formatting format, uint32_t max_depth );
33  std::string pretty_print( const std::string& v, uint8_t indent );
34 }
35 
36 #if __cplusplus > 201402L
37 #define FALLTHROUGH [[fallthrough]];
38 #else
39 #define FALLTHROUGH
40 #endif
41 
42 #include <fc/io/json_relaxed.hpp>
43 
44 namespace fc
45 {
46  template<typename T>
47  char parseEscape( T& in )
48  {
49  if( in.peek() == '\\' )
50  {
51  try {
52  in.get();
53  switch( in.peek() )
54  {
55  case 't':
56  in.get();
57  return '\t';
58  case 'n':
59  in.get();
60  return '\n';
61  case 'r':
62  in.get();
63  return '\r';
64  case '\\':
65  in.get();
66  return '\\';
67  default:
68  return in.get();
69  }
70  } FC_RETHROW_EXCEPTIONS( info, "Stream ended with '\\'" );
71  }
72  FC_THROW_EXCEPTION( parse_error_exception, "Expected '\\'" );
73  }
74 
75  template<typename T>
76  bool skip_white_space( T& in )
77  {
78  bool skipped = false;
79  while( true )
80  {
81  switch( in.peek() )
82  {
83  case ' ':
84  case '\t':
85  case '\n':
86  case '\r':
87  skipped = true;
88  in.get();
89  break;
90  default:
91  return skipped;
92  }
93  }
94  }
95 
96  template<typename T>
97  std::string stringFromStream( T& in )
98  {
99  fc::stringstream token;
100  try
101  {
102  char c = in.peek();
103 
104  if( c != '"' )
105  FC_THROW_EXCEPTION( parse_error_exception,
106  "Expected '\"' but read '${char}'",
107  ("char", string(&c, (&c) + 1) ) );
108  in.get();
109  while( true )
110  {
111 
112  switch( c = in.peek() )
113  {
114  case '\\':
115  token << parseEscape( in );
116  break;
117  case 0x04:
118  FC_THROW_EXCEPTION( parse_error_exception, "EOF before closing '\"' in string '${token}'",
119  ("token", token.str() ) );
120  case '"':
121  in.get();
122  return token.str();
123  default:
124  token << c;
125  in.get();
126  }
127  }
128  FC_THROW_EXCEPTION( parse_error_exception, "EOF before closing '\"' in string '${token}'",
129  ("token", token.str() ) );
130  } FC_RETHROW_EXCEPTIONS( warn, "while parsing token '${token}'",
131  ("token", token.str() ) );
132  }
133  template<typename T>
134  std::string stringFromToken( T& in )
135  {
136  fc::stringstream token;
137  try
138  {
139  char c = in.peek();
140 
141  while( true )
142  {
143  switch( c = in.peek() )
144  {
145  case '\\':
146  token << parseEscape( in );
147  break;
148  case '\t':
149  case ' ':
150  case '\0':
151  case '\n':
152  in.get();
153  return token.str();
154  default:
155  if( isalnum( c ) || c == '_' || c == '-' || c == '.' || c == ':' || c == '/' )
156  {
157  token << c;
158  in.get();
159  }
160  else return token.str();
161  }
162  }
163  return token.str();
164  }
165  catch( const fc::eof_exception& eof )
166  {
167  return token.str();
168  }
169  catch (const std::ios_base::failure&)
170  {
171  return token.str();
172  }
173 
174  FC_RETHROW_EXCEPTIONS( warn, "while parsing token '${token}'",
175  ("token", token.str() ) );
176  }
177 
178  template<typename T>
179  variant_object objectFromStreamBase( T& in, std::function<std::string(T&)>& get_key, std::function<variant(T&)>& get_value )
180  {
182  try
183  {
184  char c = in.peek();
185  if( c != '{' )
186  FC_THROW_EXCEPTION( parse_error_exception,
187  "Expected '{', but read '${char}'",
188  ("char",string(&c, &c + 1)) );
189  in.get();
190  while( in.peek() != '}' )
191  {
192  if( in.peek() == ',' )
193  {
194  in.get();
195  continue;
196  }
197  if( skip_white_space(in) ) continue;
198  string key = get_key( in );
199  skip_white_space(in);
200  if( in.peek() != ':' )
201  {
202  FC_THROW_EXCEPTION( parse_error_exception, "Expected ':' after key \"${key}\"",
203  ("key", key) );
204  }
205  in.get();
206  auto val = get_value( in );
207 
208  obj(std::move(key),std::move(val));
209  }
210  if( in.peek() == '}' )
211  {
212  in.get();
213  return obj;
214  }
215  FC_THROW_EXCEPTION( parse_error_exception, "Expected '}' after ${variant}", ("variant", obj ) );
216  }
217  catch( const fc::eof_exception& e )
218  {
219  FC_THROW_EXCEPTION( parse_error_exception, "Unexpected EOF: ${e}", ("e", e.to_detail_string() ) );
220  }
221  catch( const std::ios_base::failure& e )
222  {
223  FC_THROW_EXCEPTION( parse_error_exception, "Unexpected EOF: ${e}", ("e", e.what() ) );
224  } FC_RETHROW_EXCEPTIONS( warn, "Error parsing object" );
225  }
226 
227  template<typename T, json::parse_type parser_type>
228  variant_object objectFromStream( T& in, uint32_t max_depth )
229  {
230  std::function<std::string(T&)> get_key = []( T& in ){ return stringFromStream( in ); };
231  std::function<variant(T&)> get_value = [max_depth]( T& in ){ return variant_from_stream<T, parser_type>( in, max_depth ); };
232  return objectFromStreamBase<T>( in, get_key, get_value );
233  }
234 
235  template<typename T>
236  variants arrayFromStreamBase( T& in, std::function<variant(T&)>& get_value )
237  {
238  variants ar;
239  try
240  {
241  if( in.peek() != '[' )
242  FC_THROW_EXCEPTION( parse_error_exception, "Expected '['" );
243  in.get();
244 
245  while( in.peek() != ']' )
246  {
247  if( in.peek() == ',' )
248  {
249  in.get();
250  continue;
251  }
252  if( skip_white_space(in) ) continue;
253  ar.push_back( get_value(in) );
254  }
255  if( in.peek() != ']' )
256  FC_THROW_EXCEPTION( parse_error_exception, "Expected ']' after parsing ${variant}",
257  ("variant", ar) );
258 
259  in.get();
260  } FC_RETHROW_EXCEPTIONS( warn, "Attempting to parse array ${array}",
261  ("array", ar ) );
262  return ar;
263  }
264 
265  template<typename T, json::parse_type parser_type>
266  variants arrayFromStream( T& in, uint32_t max_depth )
267  {
268  std::function<variant(T&)> get_value = [max_depth]( T& in ){ return variant_from_stream<T, parser_type>( in, max_depth ); };
269  return arrayFromStreamBase<T>( in, get_value );
270  }
271 
272  template<typename T, json::parse_type parser_type>
274  {
275  fc::stringstream ss;
276 
277  bool dot = false;
278  bool neg = false;
279  if( in.peek() == '-')
280  {
281  neg = true;
282  ss.put( in.get() );
283  }
284  bool done = false;
285 
286  try
287  {
288  char c;
289  while((c = in.peek()) && !done)
290  {
291 
292  switch( c )
293  {
294  case '.':
295  if (dot)
296  FC_THROW_EXCEPTION(parse_error_exception, "Can't parse a number with two decimal places");
297  dot = true;
299  case '0':
300  case '1':
301  case '2':
302  case '3':
303  case '4':
304  case '5':
305  case '6':
306  case '7':
307  case '8':
308  case '9':
309  ss.put( in.get() );
310  break;
311  default:
312  if( isalnum( c ) )
313  {
314  return ss.str() + stringFromToken( in );
315  }
316  done = true;
317  break;
318  }
319  }
320  }
321  catch (fc::eof_exception&)
322  { // EOF ends the loop
323  }
324  catch (const std::ios_base::failure&)
325  { // read error ends the loop
326  }
327  std::string str = ss.str();
328  if (str == "-." || str == "." || str == "-") // check the obviously wrong things we could have encountered
329  FC_THROW_EXCEPTION(parse_error_exception, "Can't parse token \"${token}\" as a JSON numeric constant", ("token", str));
330  if( dot )
331  return
332 #ifdef WITH_EXOTIC_JSON_PARSERS
333  parser_type == json::legacy_parser_with_string_doubles ? variant(str) :
334 #endif
335  variant(to_double(str));
336  if( neg )
337  return to_int64(str);
338  return to_uint64(str);
339  }
340  template<typename T>
342  {
343  std::stringstream ss;
344  ss.exceptions( std::ifstream::badbit );
345  bool received_eof = false;
346  bool done = false;
347 
348  try
349  {
350  char c;
351  while((c = in.peek()) && !done)
352  {
353  switch( c )
354  {
355  case 'n':
356  case 'u':
357  case 'l':
358  case 't':
359  case 'r':
360  case 'e':
361  case 'f':
362  case 'a':
363  case 's':
364  ss.put( in.get() );
365  break;
366  default:
367  done = true;
368  break;
369  }
370  }
371  }
372  catch (fc::eof_exception&)
373  {
374  received_eof = true;
375  }
376  catch (const std::ios_base::failure&)
377  {
378  received_eof = true;
379  }
380 
381  // we can get here either by processing a delimiter as in "null,"
382  // an EOF like "null<EOF>", or an invalid token like "nullZ"
383  std::string str = ss.str();
384  if( str == "null" )
385  return variant();
386  if( str == "true" )
387  return true;
388  if( str == "false" )
389  return false;
390  else
391  {
392  if (received_eof)
393  {
394  if (str.empty())
395  FC_THROW_EXCEPTION( parse_error_exception, "Unexpected EOF" );
396  else
397  return str;
398  }
399  else
400  {
401  // if we've reached this point, we've either seen a partial
402  // token ("tru<EOF>") or something our simple parser couldn't
403  // make out ("falfe")
404  // A strict JSON parser would signal this as an error, but we
405  // will just treat the malformed token as an un-quoted string.
406  return str + stringFromToken(in);
407  }
408  }
409  }
410 
411 
412  template<typename T, json::parse_type parser_type>
413  variant variant_from_stream( T& in, uint32_t max_depth )
414  {
415  if( max_depth == 0 )
416  FC_THROW_EXCEPTION( parse_error_exception, "Too many nested items in JSON input!" );
417  skip_white_space(in);
418  signed char c = in.peek();
419  switch( c )
420  {
421  case '"':
422  return stringFromStream( in );
423  case '{':
424  return objectFromStream<T, parser_type>( in, max_depth - 1 );
425  case '[':
426  return arrayFromStream<T, parser_type>( in, max_depth - 1 );
427  case '-':
428  case '.':
429  case '0':
430  case '1':
431  case '2':
432  case '3':
433  case '4':
434  case '5':
435  case '6':
436  case '7':
437  case '8':
438  case '9':
439  return number_from_stream<T, parser_type>( in );
440  // null, true, false, or 'warning' / string
441  case 'n':
442  case 't':
443  case 'f':
444  return token_from_stream( in );
445  case 0x04: // ^D end of transmission
446  case EOF:
447  FC_THROW_EXCEPTION( eof_exception, "unexpected end of file" );
448  case 0:
449  if( parser_type == fc::json::broken_nul_parser )
450  return variant();
452  default:
453  FC_THROW_EXCEPTION( parse_error_exception, "Unexpected char '${c}' in \"${s}\"",
454  ("c", c)("s", stringFromToken(in)) );
455  }
456  }
457 
458  variant json::from_string( const std::string& utf8_str, parse_type ptype, uint32_t max_depth )
459  { try {
460  fc::istream_ptr in( new fc::stringstream( utf8_str ) );
461  fc::buffered_istream bin( in );
462  return from_stream( bin, ptype, max_depth );
463  } FC_RETHROW_EXCEPTIONS( warn, "", ("str",utf8_str) ) }
464 
465  variants json::variants_from_string( const std::string& utf8_str, parse_type ptype, uint32_t max_depth )
466  {
467  variants result;
468  try {
469  fc::stringstream in( utf8_str );
470  while( true )
471  result.push_back(json_relaxed::variant_from_stream<fc::stringstream, false>( in, max_depth ));
472  } catch ( const fc::eof_exception& ) {
473  return result;
474  } FC_RETHROW_EXCEPTIONS( warn, "", ("str",utf8_str) )
475  }
476 
482  void escape_string( const string& str, ostream& os )
483  {
484  os << '"';
485  for( auto itr = str.begin(); itr != str.end(); ++itr )
486  {
487  switch( *itr )
488  {
489  case '\b': // \x08
490  os << "\\b";
491  break;
492  case '\f': // \x0c
493  os << "\\f";
494  break;
495  case '\n': // \x0a
496  os << "\\n";
497  break;
498  case '\r': // \x0d
499  os << "\\r";
500  break;
501  case '\t': // \x09
502  os << "\\t";
503  break;
504  case '\\':
505  os << "\\\\";
506  break;
507  case '\"':
508  os << "\\\"";
509  break;
510  case '\x00': os << "\\u0000"; break;
511  case '\x01': os << "\\u0001"; break;
512  case '\x02': os << "\\u0002"; break;
513  case '\x03': os << "\\u0003"; break;
514  case '\x04': os << "\\u0004"; break;
515  case '\x05': os << "\\u0005"; break;
516  case '\x06': os << "\\u0006"; break;
517  case '\x07': os << "\\u0007"; break; // \a is not valid JSON
518  // case '\x08': os << "\\u0008"; break; // \b
519  // case '\x09': os << "\\u0009"; break; // \t
520  // case '\x0a': os << "\\u000a"; break; // \n
521  case '\x0b': os << "\\u000b"; break;
522  // case '\x0c': os << "\\u000c"; break; // \f
523  // case '\x0d': os << "\\u000d"; break; // \r
524  case '\x0e': os << "\\u000e"; break;
525  case '\x0f': os << "\\u000f"; break;
526 
527  case '\x10': os << "\\u0010"; break;
528  case '\x11': os << "\\u0011"; break;
529  case '\x12': os << "\\u0012"; break;
530  case '\x13': os << "\\u0013"; break;
531  case '\x14': os << "\\u0014"; break;
532  case '\x15': os << "\\u0015"; break;
533  case '\x16': os << "\\u0016"; break;
534  case '\x17': os << "\\u0017"; break;
535  case '\x18': os << "\\u0018"; break;
536  case '\x19': os << "\\u0019"; break;
537  case '\x1a': os << "\\u001a"; break;
538  case '\x1b': os << "\\u001b"; break;
539  case '\x1c': os << "\\u001c"; break;
540  case '\x1d': os << "\\u001d"; break;
541  case '\x1e': os << "\\u001e"; break;
542  case '\x1f': os << "\\u001f"; break;
543 
544  default:
545  os << *itr;
546  }
547  }
548  os << '"';
549  }
550  ostream& json::to_stream( ostream& out, const std::string& str )
551  {
552  escape_string( str, out );
553  return out;
554  }
555 
556  template<typename T>
557  void to_stream( T& os, const variants& a, json::output_formatting format, uint32_t max_depth )
558  {
559  os << '[';
560  auto itr = a.begin();
561 
562  while( itr != a.end() )
563  {
564  to_stream( os, *itr, format, max_depth );
565  ++itr;
566  if( itr != a.end() )
567  os << ',';
568  }
569  os << ']';
570  }
571  template<typename T>
572  void to_stream( T& os, const variant_object& o, json::output_formatting format, uint32_t max_depth )
573  {
574  os << '{';
575  auto itr = o.begin();
576 
577  while( itr != o.end() )
578  {
579  escape_string( itr->key(), os );
580  os << ':';
581  to_stream( os, itr->value(), format, max_depth );
582  ++itr;
583  if( itr != o.end() )
584  os << ',';
585  }
586  os << '}';
587  }
588 
589  template<typename T>
590  void to_stream( T& os, const variant& v, json::output_formatting format, uint32_t max_depth )
591  {
592  FC_ASSERT( max_depth > 0, "Too many nested objects!" );
593  switch( v.get_type() )
594  {
595  case variant::null_type:
596  os << "null";
597  return;
598  case variant::int64_type:
600  ( v.as_int64() > INT32_MAX || v.as_int64() < INT32_MIN ) )
601  os << '"'<<v.as_string()<<'"';
602  else
603  os << v.as_int64();
604  return;
607  v.as_uint64() > 0xffffffff )
608  os << '"'<<v.as_string()<<'"';
609  else
610  os << v.as_uint64();
611  return;
614  os << '"'<<v.as_string()<<'"';
615  else
616  os << v.as_string();
617  return;
618  case variant::bool_type:
619  os << v.as_string();
620  return;
622  escape_string( v.get_string(), os );
623  return;
624  case variant::blob_type:
625  escape_string( v.as_string(), os );
626  return;
627  case variant::array_type:
628  to_stream( os, v.get_array(), format, max_depth - 1 );
629  return;
631  to_stream(os, v.get_object(), format, max_depth - 1 );
632  return;
633  default:
634  FC_THROW_EXCEPTION( fc::invalid_arg_exception, "Unsupported variant type: ${type}", ( "type", v.get_type() ) );
635  }
636  }
637 
638  std::string json::to_string( const variant& v, output_formatting format, uint32_t max_depth )
639  {
640  fc::stringstream ss;
641  fc::to_stream( ss, v, format, max_depth );
642  return ss.str();
643  }
644 
645 
646  std::string pretty_print( const std::string& v, uint8_t indent ) {
647  int level = 0;
648  fc::stringstream ss;
649  bool first = false;
650  bool quote = false;
651  bool escape = false;
652  for( uint32_t i = 0; i < v.size(); ++i ) {
653  switch( v[i] ) {
654  case '\\':
655  if( !escape ) {
656  if( quote )
657  escape = true;
658  } else { escape = false; }
659  ss<<v[i];
660  break;
661  case ':':
662  if( !quote ) {
663  ss<<": ";
664  } else {
665  ss<<':';
666  }
667  break;
668  case '"':
669  if( first ) {
670  ss<<'\n';
671  for( int i = 0; i < level*indent; ++i ) ss<<' ';
672  first = false;
673  }
674  if( !escape ) {
675  quote = !quote;
676  }
677  escape = false;
678  ss<<'"';
679  break;
680  case '{':
681  case '[':
682  ss<<v[i];
683  if( !quote ) {
684  ++level;
685  first = true;
686  }else {
687  escape = false;
688  }
689  break;
690  case '}':
691  case ']':
692  if( !quote ) {
693  if( v[i-1] != '[' && v[i-1] != '{' ) {
694  ss<<'\n';
695  }
696  --level;
697  if( !first ) {
698  for( int i = 0; i < level*indent; ++i ) ss<<' ';
699  }
700  first = false;
701  ss<<v[i];
702  break;
703  } else {
704  escape = false;
705  ss<<v[i];
706  }
707  break;
708  case ',':
709  if( !quote ) {
710  ss<<',';
711  first = true;
712  } else {
713  escape = false;
714  ss<<',';
715  }
716  break;
717  case 'n':
718  //If we're in quotes and see a \n, just print it literally but unset the escape flag.
719  if( quote && escape )
720  escape = false;
722  default:
723  if( first ) {
724  ss<<'\n';
725  for( int i = 0; i < level*indent; ++i ) ss<<' ';
726  first = false;
727  }
728  ss << v[i];
729  }
730  }
731  return ss.str();
732  }
733 
734 
735 
736  std::string json::to_pretty_string( const variant& v, output_formatting format, uint32_t max_depth )
737  {
738  return pretty_print(to_string(v, format, max_depth), 2);
739  }
740 
741  void json::save_to_file( const variant& v, const fc::path& fi, bool pretty, output_formatting format, uint32_t max_depth )
742  {
743  if( pretty )
744  {
745  auto str = json::to_pretty_string( v, format, max_depth );
746  fc::ofstream o(fi);
747  o.write( str.c_str(), str.size() );
748  }
749  else
750  {
751  fc::ofstream o(fi);
752  fc::to_stream( o, v, format, max_depth );
753  }
754  }
755  variant json::from_file( const fc::path& p, parse_type ptype, uint32_t max_depth )
756  {
757  fc::istream_ptr in( new fc::ifstream( p ) );
758  fc::buffered_istream bin( in );
759  return from_stream( bin, ptype, max_depth );
760  }
761  variant json::from_stream( buffered_istream& in, parse_type ptype, uint32_t max_depth )
762  {
763  switch( ptype )
764  {
765  case legacy_parser:
766  return variant_from_stream<fc::buffered_istream, legacy_parser>( in, max_depth );
767 #ifdef WITH_EXOTIC_JSON_PARSERS
768  case legacy_parser_with_string_doubles:
769  return variant_from_stream<fc::buffered_istream, legacy_parser_with_string_doubles>( in, max_depth );
770  case strict_parser:
771  return json_relaxed::variant_from_stream<buffered_istream, true>( in, max_depth );
772  case relaxed_parser:
773  return json_relaxed::variant_from_stream<buffered_istream, false>( in, max_depth );
774 #endif
775  case broken_nul_parser:
776  return variant_from_stream<fc::buffered_istream, broken_nul_parser>( in, max_depth );
777  default:
778  FC_ASSERT( false, "Unknown JSON parser type {ptype}", ("ptype", ptype) );
779  }
780  }
781 
782  ostream& json::to_stream( ostream& out, const variant& v, output_formatting format, uint32_t max_depth )
783  {
784  fc::to_stream( out, v, format, max_depth );
785  return out;
786  }
787  ostream& json::to_stream( ostream& out, const variants& v, output_formatting format, uint32_t max_depth )
788  {
789  fc::to_stream( out, v, format, max_depth );
790  return out;
791  }
792  ostream& json::to_stream( ostream& out, const variant_object& v, output_formatting format, uint32_t max_depth )
793  {
794  fc::to_stream( out, v, format, max_depth );
795  return out;
796  }
797 
798  bool json::is_valid( const std::string& utf8_str, parse_type ptype, uint32_t max_depth )
799  {
800  if( utf8_str.size() == 0 ) return false;
801  fc::istream_ptr in( new fc::stringstream( utf8_str ) );
802  fc::buffered_istream bin( in );
803  from_stream( bin, ptype, max_depth );
804  try { bin.peek(); } catch ( const eof_exception& e ) { return true; }
805  return false;
806  }
807 
808 } // fc
static string to_string(const variant &v, output_formatting format=stringify_large_ints_and_doubles, uint32_t max_depth=DEFAULT_MAX_RECURSION_DEPTH)
Definition: json.cpp:638
const std::string & get_string() const
Definition: variant.cpp:575
variants arrayFromStream(T &in, uint32_t max_depth)
Definition: json.cpp:266
An order-perserving dictionary of variant&#39;s.
virtual char peek() const
std::vector< variant > variants
Definition: variant.hpp:170
static bool is_valid(const std::string &json_str, parse_type ptype=legacy_parser, uint32_t max_depth=DEFAULT_MAX_RECURSION_DEPTH)
Definition: json.cpp:798
static variants variants_from_string(const string &utf8_str, parse_type ptype=legacy_parser, uint32_t max_depth=DEFAULT_MAX_RECURSION_DEPTH)
Definition: json.cpp:465
int64_t to_int64(const std::string &)
Definition: string.cpp:34
#define FC_RETHROW_EXCEPTIONS(LOG_LEVEL, FORMAT,...)
Catchs all exception&#39;s, std::exceptions, and ... and rethrows them after appending the provided log m...
Definition: exception.hpp:463
uint64_t as_uint64() const
Definition: variant.cpp:398
static variant from_file(const fc::path &p, parse_type ptype=legacy_parser, uint32_t max_depth=DEFAULT_MAX_RECURSION_DEPTH)
Definition: json.cpp:755
char parseEscape(T &in)
Definition: json.cpp:47
variant_object objectFromStream(T &in, uint32_t max_depth)
Definition: json.cpp:228
variant_object objectFromStreamBase(T &in, std::function< std::string(T &)> &get_key, std::function< variant(T &)> &get_value)
Definition: json.cpp:179
static ostream & to_stream(ostream &out, const std::string &)
Definition: json.cpp:550
std::string pretty_print(const std::string &v, uint8_t indent)
Definition: json.cpp:646
type_id get_type() const
Definition: variant.cpp:304
variant_object & get_object()
Definition: variant.cpp:554
void escape_string(const string &str, ostream &os)
Definition: json.cpp:482
virtual char get()
Definition: iostream.cpp:267
iterator begin() const
std::string str()
Definition: sstream.cpp:33
static variant from_stream(buffered_istream &in, parse_type ptype=legacy_parser, uint32_t max_depth=DEFAULT_MAX_RECURSION_DEPTH)
Definition: json.cpp:761
parse_type
Definition: json.hpp:20
double to_double(const std::string &)
Definition: string.cpp:60
output_formatting
Definition: json.hpp:30
variant variant_from_stream(T &in, uint32_t max_depth)
Definition: json.cpp:413
bool skip_white_space(T &in)
Definition: json.cpp:76
void to_stream(T &os, const variants &a, json::output_formatting format, uint32_t max_depth)
Definition: json.cpp:557
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object&#39;s.
Definition: variant.hpp:198
static string to_pretty_string(const variant &v, output_formatting format=stringify_large_ints_and_doubles, uint32_t max_depth=DEFAULT_MAX_RECURSION_DEPTH)
Definition: json.cpp:736
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
Definition: exception.hpp:378
uint64_t to_uint64(const std::string &)
Definition: string.cpp:47
variant number_from_stream(T &in)
Definition: json.cpp:273
at< List, 0 > first
Get the type at the beginning of the list.
Definition: typelist.hpp:190
Defines exception&#39;s used by fc.
void put(char c)
Definition: iostream.hpp:50
std::string stringFromToken(T &in)
Definition: json.cpp:134
variants & get_array()
Definition: variant.cpp:496
int64_t as_int64() const
Definition: variant.cpp:377
#define FALLTHROUGH
Definition: json.cpp:39
variant token_from_stream(T &in)
Definition: json.cpp:341
iterator end() const
Definition: api.hpp:15
static variant from_string(const string &utf8_str, parse_type ptype=legacy_parser, uint32_t max_depth=DEFAULT_MAX_RECURSION_DEPTH)
Definition: json.cpp:458
wraps boost::filesystem::path to provide platform independent path manipulation.
Definition: filesystem.hpp:28
variants arrayFromStreamBase(T &in, std::function< variant(T &)> &get_value)
Definition: json.cpp:236
ostream & write(const char *buf, size_t len)
Definition: iostream.cpp:290
Reads data from an unbuffered stream and enables peek functionality.
std::string stringFromStream(T &in)
Definition: json.cpp:97
std::string as_string() const
Definition: variant.cpp:469
An order-perserving dictionary of variant&#39;s.
static void save_to_file(const T &v, const fc::path &fi, bool pretty=true, output_formatting format=stringify_large_ints_and_doubles, uint32_t max_depth=DEFAULT_MAX_RECURSION_DEPTH)
Definition: json.hpp:51
std::shared_ptr< istream > istream_ptr
Definition: iostream.hpp:35