BitShares-Core  4.0.0
BitShares blockchain implementation and command-line interface software
json_relaxed.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 // This file is an internal header,
4 // it is not meant to be included except internally from json.cpp in fc
5 
6 #include <fc/io/json.hpp>
8 #include <fc/io/iostream.hpp>
10 #include <fc/io/fstream.hpp>
11 #include <fc/io/sstream.hpp>
12 #include <fc/log/logger.hpp>
13 //#include <utfcpp/utf8.h>
14 #include <iostream>
15 #include <fstream>
16 #include <sstream>
17 
18 #include <boost/filesystem/fstream.hpp>
19 
20 namespace fc { namespace json_relaxed
21 {
22  template<typename T, bool strict>
23  variant variant_from_stream( T& in, uint32_t max_depth );
24 
25  template<typename T>
26  std::string tokenFromStream( T& in )
27  {
28  fc::stringstream token;
29  try
30  {
31  char c = in.peek();
32 
33  while( true )
34  {
35  switch( c = in.peek() )
36  {
37  case '\\':
38  token << parseEscape( in );
39  break;
40  case '\t':
41  case ' ':
42  case ',':
43  case ':':
44  case '\0':
45  case '\n':
46  case '\x04':
47  in.get();
48  return token.str();
49  case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
50  case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
51  case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
52  case 'y': case 'z':
53  case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H':
54  case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P':
55  case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
56  case 'Y': case 'Z':
57  case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
58  case '8': case '9':
59  case '_': case '-': case '.': case '+': case '/':
60  token << c;
61  in.get();
62  break;
63  default:
64  return token.str();
65  }
66  }
67  return token.str();
68  }
69  catch( const fc::eof_exception& eof )
70  {
71  return token.str();
72  }
73  catch (const std::ios_base::failure&)
74  {
75  return token.str();
76  }
77 
78  FC_RETHROW_EXCEPTIONS( warn, "while parsing token '${token}'",
79  ("token", token.str() ) );
80  }
81 
82  template<typename T, bool strict, bool allow_escape>
83  std::string quoteStringFromStream( T& in )
84  {
85  fc::stringstream token;
86  try
87  {
88  char q = in.get();
89  switch( q )
90  {
91  case '\'':
92  if( strict )
93  FC_THROW_EXCEPTION( parse_error_exception, "expected: '\"' at beginning of string, got '\''" );
94  // falls through
95  case '"':
96  break;
97  default:
98  if( strict )
99  FC_THROW_EXCEPTION( parse_error_exception, "expected: '\"' at beginning of string" );
100  else
101  FC_THROW_EXCEPTION( parse_error_exception, "expected: '\"' | '\\\'' at beginning of string" );
102  }
103  if( in.peek() == q )
104  {
105  in.get();
106  try
107  {
108  if( in.peek() != q )
109  return std::string();
110  }
111  catch( const fc::eof_exception& e )
112  {
113  return std::string();
114  }
115 
116  // triple quote processing
117  if( strict )
118  FC_THROW_EXCEPTION( parse_error_exception, "triple quote unsupported in strict mode" );
119  else
120  {
121  in.get();
122 
123  while( true )
124  {
125  char c = in.peek();
126  if( c == q )
127  {
128  in.get();
129  char c2 = in.peek();
130  if( c2 == q )
131  {
132  in.get();
133  char c3 = in.peek();
134  if( c3 == q )
135  {
136  in.get();
137  return token.str();
138  }
139  token << q << q;
140  continue;
141  }
142  token << q;
143  continue;
144  }
145  else if( c == '\x04' )
146  FC_THROW_EXCEPTION( parse_error_exception, "unexpected EOF in string '${token}'",
147  ("token", token.str() ) );
148  else if( allow_escape && (c == '\\') )
149  token << parseEscape( in );
150  else
151  {
152  in.get();
153  token << c;
154  }
155  }
156  }
157  }
158 
159  while( true )
160  {
161  char c = in.peek();
162 
163  if( c == q )
164  {
165  in.get();
166  return token.str();
167  }
168  else if( c == '\x04' )
169  FC_THROW_EXCEPTION( parse_error_exception, "unexpected EOF in string '${token}'",
170  ("token", token.str() ) );
171  else if( allow_escape && (c == '\\') )
172  token << parseEscape( in );
173  else if( (c == '\r') | (c == '\n') )
174  FC_THROW_EXCEPTION( parse_error_exception, "unexpected EOL in string '${token}'",
175  ("token", token.str() ) );
176  else
177  {
178  in.get();
179  token << c;
180  }
181  }
182 
183  } FC_RETHROW_EXCEPTIONS( warn, "while parsing token '${token}'",
184  ("token", token.str() ) );
185  }
186 
187  template<typename T, bool strict>
188  std::string stringFromStream( T& in )
189  {
190  try
191  {
192  char c = in.peek(), c2;
193 
194  switch( c )
195  {
196  case '\'':
197  if( strict )
198  FC_THROW_EXCEPTION( parse_error_exception, "expected: '\"' at beginning of string, got '\''" );
199  // falls through
200  case '"':
201  return quoteStringFromStream<T, strict, true>( in );
202  case 'r':
203  if( strict )
204  FC_THROW_EXCEPTION( parse_error_exception, "raw strings not supported in strict mode" );
205  case 'R':
206  in.get();
207  c2 = in.peek();
208  switch( c2 )
209  {
210  case '"':
211  case '\'':
212  if( strict )
213  FC_THROW_EXCEPTION( parse_error_exception, "raw strings not supported in strict mode" );
214  return quoteStringFromStream<T, strict, false>( in );
215  default:
216  if( strict )
217  FC_THROW_EXCEPTION( parse_error_exception, "unquoted strings not supported in strict mode" );
218  return c+tokenFromStream( in );
219  }
220  break;
221  case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
222  case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
223  case 'q': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
224  case 'y': case 'z':
225  case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H':
226  case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P':
227  case 'Q': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
228  case 'Y': case 'Z':
229  case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
230  case '8': case '9':
231  case '_': case '-': case '.': case '+': case '/':
232  if( strict )
233  FC_THROW_EXCEPTION( parse_error_exception, "unquoted strings not supported in strict mode" );
234  return tokenFromStream( in );
235  default:
236  FC_THROW_EXCEPTION( parse_error_exception, "expected: string" );
237  }
238 
239  } FC_RETHROW_EXCEPTIONS( warn, "while parsing string" );
240 
241  return {};
242  }
243 
245  {
246  public:
248  {
249  for( size_t i=0; i<0x100; i++ )
250  c2v[i] = 0xFF;
251  c2v[(unsigned char)'0'] = 0;
252  c2v[(unsigned char)'1'] = 1;
253  c2v[(unsigned char)'2'] = 2;
254  c2v[(unsigned char)'3'] = 3;
255  c2v[(unsigned char)'4'] = 4;
256  c2v[(unsigned char)'5'] = 5;
257  c2v[(unsigned char)'6'] = 6;
258  c2v[(unsigned char)'7'] = 7;
259  c2v[(unsigned char)'8'] = 8;
260  c2v[(unsigned char)'9'] = 9;
261  c2v[(unsigned char)'a'] = c2v[(unsigned char)'A'] = 10;
262  c2v[(unsigned char)'b'] = c2v[(unsigned char)'B'] = 11;
263  c2v[(unsigned char)'c'] = c2v[(unsigned char)'C'] = 12;
264  c2v[(unsigned char)'d'] = c2v[(unsigned char)'D'] = 13;
265  c2v[(unsigned char)'e'] = c2v[(unsigned char)'E'] = 14;
266  c2v[(unsigned char)'f'] = c2v[(unsigned char)'F'] = 15;
267  c2v[(unsigned char)'g'] = c2v[(unsigned char)'G'] = 16;
268  c2v[(unsigned char)'h'] = c2v[(unsigned char)'H'] = 17;
269  c2v[(unsigned char)'i'] = c2v[(unsigned char)'I'] = 18;
270  c2v[(unsigned char)'j'] = c2v[(unsigned char)'J'] = 19;
271  c2v[(unsigned char)'k'] = c2v[(unsigned char)'K'] = 20;
272  c2v[(unsigned char)'l'] = c2v[(unsigned char)'L'] = 21;
273  c2v[(unsigned char)'m'] = c2v[(unsigned char)'M'] = 22;
274  c2v[(unsigned char)'n'] = c2v[(unsigned char)'N'] = 23;
275  c2v[(unsigned char)'o'] = c2v[(unsigned char)'O'] = 24;
276  c2v[(unsigned char)'p'] = c2v[(unsigned char)'P'] = 25;
277  c2v[(unsigned char)'q'] = c2v[(unsigned char)'Q'] = 26;
278  c2v[(unsigned char)'r'] = c2v[(unsigned char)'R'] = 27;
279  c2v[(unsigned char)'s'] = c2v[(unsigned char)'S'] = 28;
280  c2v[(unsigned char)'t'] = c2v[(unsigned char)'T'] = 29;
281  c2v[(unsigned char)'u'] = c2v[(unsigned char)'U'] = 30;
282  c2v[(unsigned char)'v'] = c2v[(unsigned char)'V'] = 31;
283  c2v[(unsigned char)'w'] = c2v[(unsigned char)'W'] = 32;
284  c2v[(unsigned char)'x'] = c2v[(unsigned char)'X'] = 33;
285  c2v[(unsigned char)'y'] = c2v[(unsigned char)'Y'] = 34;
286  c2v[(unsigned char)'z'] = c2v[(unsigned char)'Z'] = 35;
287  return;
288  }
289 
290  uint8_t operator[]( char index ) const { return c2v[index & 0xFF]; }
291 
292  uint8_t c2v[0x100];
293  };
294 
295  template<uint8_t base>
296  fc::variant parseInt( const std::string& token, size_t start )
297  {
298  static const CharValueTable ctbl;
299  static const uint64_t INT64_MAX_PLUS_ONE = static_cast<uint64_t>(INT64_MAX) + 1;
300 
301  size_t i = start, n = token.length();
302  if( i >= n )
303  FC_THROW_EXCEPTION( parse_error_exception, "zero-length integer" );
304 
305  uint64_t val = 0;
306  uint64_t maxb4mul = UINT64_MAX / base;
307 
308  while(true)
309  {
310  char c = token[i];
311  uint8_t vc = ctbl[c];
312  if( vc == 0xFF )
313  FC_THROW_EXCEPTION( parse_error_exception, "illegal character {c} in integer of base {b}", ("c", c)("b", base) );
314  if( val > maxb4mul )
315  FC_THROW_EXCEPTION( parse_error_exception, "integer literal overflow" );
316  val *= base;
317  uint64_t newval = val + vc;
318  if( newval < val )
319  FC_THROW_EXCEPTION( parse_error_exception, "integer literal overflow" );
320  val = newval;
321  i++;
322  if( i >= n )
323  break;
324  }
325  if( token[0] == '-' )
326  {
327  if( val > INT64_MAX_PLUS_ONE )
328  FC_THROW_EXCEPTION( parse_error_exception, "negative integer literal overflow" );
329  // special cased to avoid trying to compute -INT64_MIN which is probably undefined or something
330  if( val == INT64_MAX_PLUS_ONE )
331  return fc::variant( INT64_MIN );
332  return fc::variant( -static_cast<int64_t>(val) );
333  }
334  return fc::variant( val );
335  }
336 
337  template<bool strict, uint8_t base>
338  fc::variant maybeParseInt( const std::string& token, size_t start )
339  {
340  try
341  {
342  return parseInt<base>( token, start );
343  }
344  catch( const parse_error_exception &e )
345  {
346  if( strict )
347  throw( e );
348  else
349  return fc::variant( token );
350  }
351  }
352 
353  template<bool strict>
354  fc::variant parseNumberOrStr( const std::string& token )
355  { try {
356  //ilog( (token) );
357  size_t i = 0, n = token.length();
358  if( n == 0 )
359  FC_THROW_EXCEPTION( parse_error_exception, "expected: non-empty token, got: empty token" );
360  switch( token[0] )
361  {
362  case '+':
363  if( strict )
364  FC_THROW_EXCEPTION( parse_error_exception, "unary + not supported in strict mode" );
365  i++;
366  break;
367  case '-':
368  i++;
369  break;
370  default:
371  break;
372  }
373  char c = token[i++];
374  switch( c )
375  {
376  case '0':
377  if( i >= n )
378  return fc::variant( uint64_t( 0 ) );
379  switch( token[i] )
380  {
381  case 'b':
382  case 'B':
383  if( strict )
384  FC_THROW_EXCEPTION( parse_error_exception, "binary numeric literals not supported in strict mode" );
385  i++;
386  if( i >= n )
387  FC_THROW_EXCEPTION( parse_error_exception, "empty binary numeric literal" );
388  return maybeParseInt<strict, 2>( token, i+1 );
389  case 'o':
390  case 'O':
391  if( strict )
392  FC_THROW_EXCEPTION( parse_error_exception, "octal numeric literals not supported in strict mode" );
393  return maybeParseInt<strict, 8>( token, i+1 );
394  case 'x':
395  case 'X':
396  if( strict )
397  FC_THROW_EXCEPTION( parse_error_exception, "hex numeric literals not supported in strict mode" );
398  return maybeParseInt<strict, 16>( token, i+1 );
399  case '.':
400  case 'e':
401  case 'E':
402  break;
403  default:
404  // since this is a lookahead, other cases will be treated later
405  if( strict )
406  FC_THROW_EXCEPTION( parse_error_exception, "expected '.'|'e'|'E' parsing number, got '{c}'",
407  ( "c", c ) );
408  }
409  break;
410  case '1': case '2': case '3': case '4':
411  case '5': case '6': case '7': case '8': case '9':
412  break;
413  case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
414  case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
415  case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
416  case 'y': case 'z':
417  case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H':
418  case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P':
419  case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
420  case 'Y': case 'Z':
421  case '_': case '-': case '.': case '+': case '/':
422  if( strict )
423  FC_THROW_EXCEPTION( parse_error_exception, "illegal character '{c}' parsing number", ( "c", c ) );
424  return fc::variant( token );
425  default:
426  FC_THROW_EXCEPTION( parse_error_exception, "illegal character '{c}' in token", ( "c", c ) );
427  }
428  size_t start = i-1;
429 
430  bool dot_ok = true;
431 
432  // int frac? exp?
433  while(true)
434  {
435  if( i >= n )
436  return parseInt<10>( token, start );
437  char c = token[i++];
438  //idump((c)(std::string()+c));
439  switch( c )
440  {
441  case '0': case '1': case '2': case '3': case '4':
442  case '5': case '6': case '7': case '8': case '9':
443  break;
444  case '.':
445  return fc::variant(token);
446  if( dot_ok )
447  {
448  dot_ok = false;
449  if( i == n )
450  {
451  if( strict )
452  FC_THROW_EXCEPTION( parse_error_exception, "number cannot end with '.' in strict mode" );
453  return fc::variant( fc::to_double(token.c_str()) );
454  }
455 
456  //idump((i));
457  c = token[i+1];
458  //idump((c));
459  switch( c )
460  {
461  case '0': case '1': case '2': case '3': case '4':
462  case '5': case '6': case '7': case '8': case '9':
463  break;
464  case 'e':
465  case 'E':
466  if( strict )
467  FC_THROW_EXCEPTION( parse_error_exception, "expected digit after '.'" );
468  break;
469  case 'a': case 'b': case 'c': case 'd': case 'f': case 'g': case 'h':
470  case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
471  case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
472  case 'y': case 'z':
473  case 'A': case 'B': case 'C': case 'D': case 'F': case 'G': case 'H':
474  case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P':
475  case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
476  case 'Y': case 'Z':
477  case '_': case '-': case '.': case '+': case '/':
478  if( strict )
479  FC_THROW_EXCEPTION( parse_error_exception, "expected digit after '.'" );
480  return fc::variant( token );
481  default:
482  FC_THROW_EXCEPTION( parse_error_exception, "illegal character '{c}' in token", ( "c", c )("i",int(c)) );
483  }
484  }
485  else
486  {
487  if( strict )
488  FC_THROW_EXCEPTION( parse_error_exception, "illegal multiple . in number" );
489  return fc::variant( token );
490  }
491  break;
492  case 'e':
493  case 'E':
494  if( i == n )
495  {
496  if( strict )
497  FC_THROW_EXCEPTION( parse_error_exception, "expected exponent after 'e'|'E' parsing number" );
498  return fc::variant( token );
499  }
500  c = token[i++];
501  switch( c )
502  {
503  case '+': case '-':
504  if( i == n )
505  {
506  if( strict )
507  FC_THROW_EXCEPTION( parse_error_exception, "expected exponent" );
508  return fc::variant( token );
509  }
510  break;
511  case '0': case '1': case '2': case '3': case '4':
512  case '5': case '6': case '7': case '8': case '9':
513  break;
514  case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
515  case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
516  case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
517  case 'y': case 'z':
518  case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H':
519  case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P':
520  case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
521  case 'Y': case 'Z':
522  case '_': case '.': case '/':
523  if( strict )
524  FC_THROW_EXCEPTION( parse_error_exception, "illegal character '{c}' in number", ( "c", c ) );
525  return fc::variant( token );
526  default:
527  FC_THROW_EXCEPTION( parse_error_exception, "illegal character '{c}' in token", ( "c", c ) );
528  }
529  while( true )
530  {
531  if( i == n )
532  break;
533  c = token[i++];
534  switch( c )
535  {
536  case '0': case '1': case '2': case '3': case '4':
537  case '5': case '6': case '7': case '8': case '9':
538  break;
539  case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
540  case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
541  case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
542  case 'y': case 'z':
543  case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H':
544  case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P':
545  case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
546  case 'Y': case 'Z':
547  case '_': case '-': case '.': case '+': case '/':
548  if( strict )
549  FC_THROW_EXCEPTION( parse_error_exception, "illegal character '{c}' in number", ( "c", c ) );
550  return fc::variant( token );
551  }
552  }
553  return fc::variant( fc::to_double(token.c_str()) );
554  case 'a': case 'b': case 'c': case 'd': case 'f': case 'g': case 'h':
555  case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
556  case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
557  case 'y': case 'z':
558  case 'A': case 'B': case 'C': case 'D': case 'F': case 'G': case 'H':
559  case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P':
560  case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
561  case 'Y': case 'Z':
562  case '_': case '-': case '+': case '/':
563  if( strict )
564  FC_THROW_EXCEPTION( parse_error_exception, "illegal character '{c}' parsing number", ( "c", c ) );
565  return fc::variant( token );
566  default:
567  FC_THROW_EXCEPTION( parse_error_exception, "illegal character '{c}' in number", ( "c", c ) );
568  }
569  }
570  } FC_CAPTURE_AND_RETHROW( (token) ) }
571 
572  template<typename T, bool strict>
573  variant_object objectFromStream( T& in, uint32_t max_depth )
574  {
575  std::function<std::string(T&)> get_key = []( T& in ){ return json_relaxed::stringFromStream<T, strict>( in ); };
576  std::function<variant(T&)> get_value = [max_depth]( T& in ){ return json_relaxed::variant_from_stream<T, strict>( in, max_depth ); };
577  return objectFromStreamBase<T>( in, get_key, get_value );
578  }
579 
580  template<typename T, bool strict>
581  variants arrayFromStream( T& in, uint32_t max_depth )
582  {
583  std::function<variant(T&)> get_value = [max_depth]( T& in ){ return json_relaxed::variant_from_stream<T, strict>( in, max_depth ); };
584  return arrayFromStreamBase<T>( in, get_value );
585  }
586 
587  template<typename T, bool strict>
589  { try {
590  std::string token = tokenFromStream(in);
591  variant result = json_relaxed::parseNumberOrStr<strict>( token );
592  if( strict && !(result.is_int64() || result.is_uint64() || result.is_double()) )
593  FC_THROW_EXCEPTION( parse_error_exception, "expected: number" );
594  return result;
596 
597  template<typename T, bool strict>
599  {
600  std::string token = tokenFromStream(in);
601 
602  FC_ASSERT( token.length() > 0 );
603 
604  switch( token[0] )
605  {
606  case 'n':
607  if( token == "null" )
608  return variant();
609  break;
610  case 't':
611  if( token == "true" )
612  return variant( true );
613  break;
614  case 'f':
615  if( token == "false" )
616  return variant( false );
617  break;
618  default:
619  break;
620  }
621 
622  if( !strict )
623  return token;
624 
625  FC_THROW_EXCEPTION( parse_error_exception, "expected: null|true|false" );
626  }
627 
628  template<typename T, bool strict>
629  variant variant_from_stream( T& in, uint32_t max_depth )
630  {
631  if( max_depth == 0 )
632  FC_THROW_EXCEPTION( parse_error_exception, "Too many nested items in JSON input!" );
633  skip_white_space(in);
634  signed char c = in.peek();
635  switch( c )
636  {
637  case '"':
638  return json_relaxed::stringFromStream<T, strict>( in );
639  case '{':
640  return json_relaxed::objectFromStream<T, strict>( in, max_depth - 1 );
641  case '[':
642  return json_relaxed::arrayFromStream<T, strict>( in, max_depth - 1 );
643  case '-':
644  case '+':
645  case '.':
646  case '0':
647  case '1':
648  case '2':
649  case '3':
650  case '4':
651  case '5':
652  case '6':
653  case '7':
654  case '8':
655  case '9':
656  return json_relaxed::numberFromStream<T, strict>( in );
657  // null, true, false, or 'warning' / string
658  case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
659  case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
660  case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
661  case 'y': case 'z':
662  case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H':
663  case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P':
664  case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
665  case 'Y': case 'Z':
666  case '_': case '/':
667  return json_relaxed::wordFromStream<T, strict>( in );
668  case 0x04: // ^D end of transmission
669  case EOF:
670  FC_THROW_EXCEPTION( eof_exception, "unexpected end of file" );
671  case 0:
672  default:
673  FC_THROW_EXCEPTION( parse_error_exception, "Unexpected char '${c}' in \"${s}\"",
674  ("c", c)("s", stringFromToken(in)) );
675  }
676  }
677 
678 } } // fc::json_relaxed
uint8_t operator[](char index) const
bool is_double() const
Definition: variant.cpp:322
An order-perserving dictionary of variant&#39;s.
variant_object objectFromStream(T &in, uint32_t max_depth)
std::vector< variant > variants
Definition: variant.hpp:170
bool is_int64() const
Definition: variant.cpp:330
fc::variant parseInt(const std::string &token, size_t start)
#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
char parseEscape(T &in)
Definition: json.cpp:47
typename impl::zip< typename impl::make_sequence< length< List >()>::type, List >::type index
Definition: typelist.hpp:225
variant wordFromStream(T &in)
virtual char get()
Definition: iostream.cpp:267
std::string str()
Definition: sstream.cpp:33
double to_double(const std::string &)
Definition: string.cpp:60
std::string tokenFromStream(T &in)
variants arrayFromStream(T &in, uint32_t max_depth)
bool skip_white_space(T &in)
Definition: json.cpp:76
#define FC_CAPTURE_AND_RETHROW(...)
Definition: exception.hpp:478
#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
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
Definition: exception.hpp:378
fc::variant parseNumberOrStr(const std::string &token)
Defines exception&#39;s used by fc.
fc::variant maybeParseInt(const std::string &token, size_t start)
std::string stringFromToken(T &in)
Definition: json.cpp:134
std::string stringFromStream(T &in)
std::string quoteStringFromStream(T &in)
Definition: api.hpp:15
variant numberFromStream(T &in)
bool is_uint64() const
Definition: variant.cpp:326
variant variant_from_stream(T &in, uint32_t max_depth)