Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
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>
9//#include <fc/io/buffered_iostream.hpp>
10//#include <fc/io/fstream.hpp>
11//#include <fc/io/sstream.hpp>
12#include <fc/log/logger.hpp>
13#include <fc/string.hpp>
14//#include <utfcpp/utf8.h>
15#include <iostream>
16#include <fstream>
17#include <sstream>
18
19#include <boost/filesystem/fstream.hpp>
20
21namespace fc { namespace json_relaxed
22{
23 template<typename T, bool strict>
24 variant variant_from_stream( T& in, uint32_t max_depth );
25
26 template<typename T>
27 std::string tokenFromStream( T& in )
28 {
29 std::stringstream token;
30 try
31 {
32 char c = in.peek();
33
34 while( true )
35 {
36 switch( c = in.peek() )
37 {
38 case '\\':
39 token << parseEscape( in );
40 break;
41 case '\t':
42 case ' ':
43 case ',':
44 case ':':
45 case '\0':
46 case '\n':
47 case '\x04':
48 in.get();
49 return token.str();
50 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
51 case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
52 case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
53 case 'y': case 'z':
54 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H':
55 case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P':
56 case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
57 case 'Y': case 'Z':
58 case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
59 case '8': case '9':
60 case '_': case '-': case '.': case '+': case '/':
61 token << c;
62 in.get();
63 break;
64 case EOF:
65 FC_THROW_EXCEPTION( eof_exception, "unexpected end of file" );
66 default:
67 return token.str();
68 }
69 }
70 return token.str();
71 }
72 catch( const fc::eof_exception& eof )
73 {
74 return token.str();
75 }
76 catch (const std::ios_base::failure&)
77 {
78 return token.str();
79 }
80
81 FC_RETHROW_EXCEPTIONS( warn, "while parsing token '${token}'",
82 ("token", token.str() ) );
83 }
84
85 template<typename T, bool strict, bool allow_escape>
86 std::string quoteStringFromStream( T& in )
87 {
88 std::stringstream token;
89 try
90 {
91 char q = in.get();
92 switch( q )
93 {
94 case '\'':
95 if( strict )
96 FC_THROW_EXCEPTION( parse_error_exception, "expected: '\"' at beginning of string, got '\''" );
97 // falls through
98 case '"':
99 break;
100 default:
101 if( strict )
102 FC_THROW_EXCEPTION( parse_error_exception, "expected: '\"' at beginning of string" );
103 else
104 FC_THROW_EXCEPTION( parse_error_exception, "expected: '\"' | '\\\'' at beginning of string" );
105 }
106 if( in.peek() == q )
107 {
108 in.get();
109 if( in.peek() != q )
110 return std::string();
111
112 // triple quote processing
113 if( strict )
114 FC_THROW_EXCEPTION( parse_error_exception, "triple quote unsupported in strict mode" );
115 else
116 {
117 in.get();
118
119 while( true )
120 {
121 char c = in.peek();
122 if( c == q )
123 {
124 in.get();
125 char c2 = in.peek();
126 if( c2 == q )
127 {
128 in.get();
129 char c3 = in.peek();
130 if( c3 == q )
131 {
132 in.get();
133 return token.str();
134 }
135 token << q << q;
136 continue;
137 }
138 token << q;
139 continue;
140 }
141 else if( c == '\x04' )
142 FC_THROW_EXCEPTION( parse_error_exception, "unexpected EOF in string '${token}'",
143 ("token", token.str() ) );
144 else if( allow_escape && (c == '\\') )
145 token << parseEscape( in );
146 else
147 {
148 in.get();
149 token << c;
150 }
151 }
152 }
153 }
154
155 while( true )
156 {
157 char c = in.peek();
158
159 if (c == EOF) {
160 FC_THROW_EXCEPTION( eof_exception, "unexpected end of file" );
161 }
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 '"':
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" );
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 case EOF:
236 FC_THROW_EXCEPTION( eof_exception, "unexpected end of file" );
237 default:
238 FC_THROW_EXCEPTION( parse_error_exception, "expected: string" );
239 }
240
241 } FC_RETHROW_EXCEPTIONS( warn, "while parsing string" );
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>
574 {
576 try
577 {
578 char c = in.peek();
579 if( c != '{' )
580 FC_THROW_EXCEPTION( parse_error_exception,
581 "Expected '{', but read '${char}'",
582 ("char",string(&c, &c + 1)) );
583 in.get();
585 while( in.peek() != '}' )
586 {
587 if( in.peek() == ',' )
588 {
589 in.get();
590 continue;
591 }
592 if( skip_white_space(in) ) continue;
595 if( in.peek() != ':' )
596 {
597 FC_THROW_EXCEPTION( parse_error_exception, "Expected ':' after key \"${key}\"",
598 ("key", key) );
599 }
600 in.get();
601 auto val = json_relaxed::variant_from_stream<T, strict>( in, max_depth - 1 );
602
603 obj(std::move(key),std::move(val));
605 }
606 if( in.peek() == '}' )
607 {
608 in.get();
609 return obj;
610 }
611 FC_THROW_EXCEPTION( parse_error_exception, "Expected '}' after ${variant}", ("variant", obj ) );
612 }
613 catch( const fc::eof_exception& e )
614 {
615 FC_THROW_EXCEPTION( parse_error_exception, "Unexpected EOF: ${e}", ("e", e.to_detail_string() ) );
616 }
617 catch( const std::ios_base::failure& e )
618 {
619 FC_THROW_EXCEPTION( parse_error_exception, "Unexpected EOF: ${e}", ("e", e.what() ) );
620 } FC_RETHROW_EXCEPTIONS( warn, "Error parsing object" );
621 }
622
623 template<typename T, bool strict>
625 {
626 variants ar;
627 try
628 {
629 if( in.peek() != '[' )
630 FC_THROW_EXCEPTION( parse_error_exception, "Expected '['" );
631 in.get();
633
634 while( in.peek() != ']' )
635 {
636 if( in.peek() == ',' )
637 {
638 in.get();
639 continue;
640 }
641 if( skip_white_space(in) ) continue;
642 ar.push_back( json_relaxed::variant_from_stream<T, strict>(in, max_depth - 1) );
644 }
645 if( in.peek() != ']' )
646 FC_THROW_EXCEPTION( parse_error_exception, "Expected ']' after parsing ${variant}",
647 ("variant", ar) );
648
649 in.get();
650 } FC_RETHROW_EXCEPTIONS( warn, "Attempting to parse array ${array}",
651 ("array", ar ) );
652 return ar;
653 }
654
655 template<typename T, bool strict>
657 { try {
658 std::string token = tokenFromStream(in);
660 if( strict && !(result.is_int64() || result.is_uint64() || result.is_double()) )
661 FC_THROW_EXCEPTION( parse_error_exception, "expected: number" );
662 return result;
664
665 template<typename T, bool strict>
667 {
668 std::string token = tokenFromStream(in);
669
670 FC_ASSERT( token.length() > 0 );
671
672 switch( token[0] )
673 {
674 case 'n':
675 if( token == "null" )
676 return variant();
677 break;
678 case 't':
679 if( token == "true" )
680 return variant( true );
681 break;
682 case 'f':
683 if( token == "false" )
684 return variant( false );
685 break;
686 default:
687 break;
688 }
689
690 if( !strict )
691 return token;
692
693 FC_THROW_EXCEPTION( parse_error_exception, "expected: null|true|false" );
694 }
695
696 template<typename T, bool strict>
698 {
700 variant var;
701 while( signed char c = in.peek() )
702 {
703 switch( c )
704 {
705 case ' ':
706 case '\t':
707 case '\n':
708 case '\r':
709 in.get();
710 continue;
711 case '"':
713 case '{':
714 return json_relaxed::objectFromStream<T, strict>( in, max_depth - 1 );
715 case '[':
716 return json_relaxed::arrayFromStream<T, strict>( in, max_depth - 1 );
717 case '-':
718 case '+':
719 case '.':
720 case '0':
721 case '1':
722 case '2':
723 case '3':
724 case '4':
725 case '5':
726 case '6':
727 case '7':
728 case '8':
729 case '9':
731 // null, true, false, or 'warning' / string
732 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
733 case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
734 case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
735 case 'y': case 'z':
736 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H':
737 case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P':
738 case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
739 case 'Y': case 'Z':
740 case '_': case '/':
742 case 0x04: // ^D end of transmission
743 case EOF:
744 FC_THROW_EXCEPTION( eof_exception, "unexpected end of file" );
745 default:
746 FC_THROW_EXCEPTION( parse_error_exception, "Unexpected char '${c}' in \"${s}\"",
747 ("c", c)("s", stringFromToken(in)) );
748 }
749 }
750 return variant();
751 }
752
753} } // fc::json_relaxed
An order-preserving dictionary of variants.
An order-preserving dictionary of variants.
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object's.
Definition variant.hpp:191
Defines exception's used by fc.
#define FC_CAPTURE_AND_RETHROW(...)
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
#define FC_RETHROW_EXCEPTIONS(LOG_LEVEL, FORMAT,...)
Catchs all exception's, std::exceptions, and ... and rethrows them after appending the provided log m...
std::string quoteStringFromStream(T &in)
variants arrayFromStream(T &in, uint32_t max_depth)
fc::variant parseNumberOrStr(const std::string &token)
fc::variant maybeParseInt(const std::string &token, size_t start)
variant_object objectFromStream(T &in, uint32_t max_depth)
std::string stringFromStream(T &in)
variant wordFromStream(T &in)
variant variant_from_stream(T &in, uint32_t max_depth)
std::string tokenFromStream(T &in)
fc::variant parseInt(const std::string &token, size_t start)
variant numberFromStream(T &in)
namespace sysio::chain
Definition authority.cpp:3
char parseEscape(T &in)
Definition json.cpp:36
std::string stringFromToken(T &in)
Definition json.cpp:125
std::vector< fc::variant > variants
Definition variant.hpp:173
bool skip_white_space(T &in)
Definition json.cpp:65
double to_double(const fc::string &)
Definition string.cpp:118
#define T(meth, val, expected)
#define UINT64_MAX
Definition stdint.h:189
signed __int64 int64_t
Definition stdint.h:135
unsigned int uint32_t
Definition stdint.h:126
#define INT64_MIN
Definition stdint.h:184
unsigned char uint8_t
Definition stdint.h:124
#define INT64_MAX
Definition stdint.h:185
unsigned __int64 uint64_t
Definition stdint.h:136
uint8_t operator[](char index) const