rippled
json_reader.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/basics/contract.h>
21 #include <ripple/json/json_reader.h>
22 #include <algorithm>
23 #include <string>
24 #include <cctype>
25 
26 namespace Json
27 {
28 // Implementation of class Reader
29 // ////////////////////////////////
30 
31 constexpr unsigned Reader::nest_limit;
32 
33 static
35 codePointToUTF8 (unsigned int cp)
36 {
37  std::string result;
38 
39  // based on description from http://en.wikipedia.org/wiki/UTF-8
40 
41  if (cp <= 0x7f)
42  {
43  result.resize (1);
44  result[0] = static_cast<char> (cp);
45  }
46  else if (cp <= 0x7FF)
47  {
48  result.resize (2);
49  result[1] = static_cast<char> (0x80 | (0x3f & cp));
50  result[0] = static_cast<char> (0xC0 | (0x1f & (cp >> 6)));
51  }
52  else if (cp <= 0xFFFF)
53  {
54  result.resize (3);
55  result[2] = static_cast<char> (0x80 | (0x3f & cp));
56  result[1] = 0x80 | static_cast<char> ((0x3f & (cp >> 6)));
57  result[0] = 0xE0 | static_cast<char> ((0xf & (cp >> 12)));
58  }
59  else if (cp <= 0x10FFFF)
60  {
61  result.resize (4);
62  result[3] = static_cast<char> (0x80 | (0x3f & cp));
63  result[2] = static_cast<char> (0x80 | (0x3f & (cp >> 6)));
64  result[1] = static_cast<char> (0x80 | (0x3f & (cp >> 12)));
65  result[0] = static_cast<char> (0xF0 | (0x7 & (cp >> 18)));
66  }
67 
68  return result;
69 }
70 
71 
72 // Class Reader
73 // //////////////////////////////////////////////////////////////////
74 
75 bool
76 Reader::parse ( std::string const& document,
77  Value& root)
78 {
79  document_ = document;
80  const char* begin = document_.c_str ();
81  const char* end = begin + document_.length ();
82  return parse ( begin, end, root );
83 }
84 
85 
86 bool
88  Value& root)
89 {
90  //std::istream_iterator<char> begin(sin);
91  //std::istream_iterator<char> end;
92  // Those would allow streamed input from a file, if parse() were a
93  // template function.
94 
95  // Since std::string is reference-counted, this at least does not
96  // create an extra copy.
97  std::string doc;
98  std::getline (sin, doc, (char)EOF);
99  return parse ( doc, root );
100 }
101 
102 bool
103 Reader::parse ( const char* beginDoc, const char* endDoc,
104  Value& root)
105 {
106  begin_ = beginDoc;
107  end_ = endDoc;
108  current_ = begin_;
109  lastValueEnd_ = 0;
110  lastValue_ = 0;
111  errors_.clear ();
112 
113  while ( !nodes_.empty () )
114  nodes_.pop ();
115 
116  nodes_.push ( &root );
117  bool successful = readValue(0);
118  Token token;
119  skipCommentTokens ( token );
120 
121  if ( !root.isNull() && !root.isArray() && !root.isObject() )
122  {
123  // Set error location to start of doc, ideally should be first token found in doc
124  token.type_ = tokenError;
125  token.start_ = beginDoc;
126  token.end_ = endDoc;
127  addError ( "A valid JSON document must be either an array or an object value.",
128  token );
129  return false;
130  }
131 
132  return successful;
133 }
134 
135 bool
136 Reader::readValue(unsigned depth)
137 {
138  Token token;
139  skipCommentTokens ( token );
140  if (depth > nest_limit)
141  return addError("Syntax error: maximum nesting depth exceeded", token);
142  bool successful = true;
143 
144  switch ( token.type_ )
145  {
146  case tokenObjectBegin:
147  successful = readObject(token, depth);
148  break;
149 
150  case tokenArrayBegin:
151  successful = readArray(token, depth);
152  break;
153 
154  case tokenInteger:
155  successful = decodeNumber ( token );
156  break;
157 
158  case tokenDouble:
159  successful = decodeDouble ( token );
160  break;
161 
162  case tokenString:
163  successful = decodeString ( token );
164  break;
165 
166  case tokenTrue:
167  currentValue () = true;
168  break;
169 
170  case tokenFalse:
171  currentValue () = false;
172  break;
173 
174  case tokenNull:
175  currentValue () = Value ();
176  break;
177 
178  default:
179  return addError ( "Syntax error: value, object or array expected.", token );
180  }
181 
182  return successful;
183 }
184 
185 
186 void
188 {
189  do
190  {
191  readToken ( token );
192  }
193  while ( token.type_ == tokenComment );
194 }
195 
196 
197 bool
198 Reader::expectToken ( TokenType type, Token& token, const char* message )
199 {
200  readToken ( token );
201 
202  if ( token.type_ != type )
203  return addError ( message, token );
204 
205  return true;
206 }
207 
208 
209 bool
211 {
212  skipSpaces ();
213  token.start_ = current_;
214  Char c = getNextChar ();
215  bool ok = true;
216 
217  switch ( c )
218  {
219  case '{':
220  token.type_ = tokenObjectBegin;
221  break;
222 
223  case '}':
224  token.type_ = tokenObjectEnd;
225  break;
226 
227  case '[':
228  token.type_ = tokenArrayBegin;
229  break;
230 
231  case ']':
232  token.type_ = tokenArrayEnd;
233  break;
234 
235  case '"':
236  token.type_ = tokenString;
237  ok = readString ();
238  break;
239 
240  case '/':
241  token.type_ = tokenComment;
242  ok = readComment ();
243  break;
244 
245  case '0':
246  case '1':
247  case '2':
248  case '3':
249  case '4':
250  case '5':
251  case '6':
252  case '7':
253  case '8':
254  case '9':
255  case '-':
256  token.type_ = readNumber ();
257  break;
258 
259  case 't':
260  token.type_ = tokenTrue;
261  ok = match ( "rue", 3 );
262  break;
263 
264  case 'f':
265  token.type_ = tokenFalse;
266  ok = match ( "alse", 4 );
267  break;
268 
269  case 'n':
270  token.type_ = tokenNull;
271  ok = match ( "ull", 3 );
272  break;
273 
274  case ',':
275  token.type_ = tokenArraySeparator;
276  break;
277 
278  case ':':
279  token.type_ = tokenMemberSeparator;
280  break;
281 
282  case 0:
283  token.type_ = tokenEndOfStream;
284  break;
285 
286  default:
287  ok = false;
288  break;
289  }
290 
291  if ( !ok )
292  token.type_ = tokenError;
293 
294  token.end_ = current_;
295  return true;
296 }
297 
298 
299 void
301 {
302  while ( current_ != end_ )
303  {
304  Char c = *current_;
305 
306  if ( c == ' ' || c == '\t' || c == '\r' || c == '\n' )
307  ++current_;
308  else
309  break;
310  }
311 }
312 
313 
314 bool
316  int patternLength )
317 {
318  if ( end_ - current_ < patternLength )
319  return false;
320 
321  int index = patternLength;
322 
323  while ( index-- )
324  if ( current_[index] != pattern[index] )
325  return false;
326 
327  current_ += patternLength;
328  return true;
329 }
330 
331 
332 bool
334 {
335  Char c = getNextChar ();
336 
337  if ( c == '*' )
338  return readCStyleComment ();
339 
340  if ( c == '/' )
341  return readCppStyleComment ();
342 
343  return false;
344 }
345 
346 bool
348 {
349  while ( current_ != end_ )
350  {
351  Char c = getNextChar ();
352 
353  if ( c == '*' && *current_ == '/' )
354  break;
355  }
356 
357  return getNextChar () == '/';
358 }
359 
360 
361 bool
363 {
364  while ( current_ != end_ )
365  {
366  Char c = getNextChar ();
367 
368  if ( c == '\r' || c == '\n' )
369  break;
370  }
371 
372  return true;
373 }
374 
377 {
378  static char const extended_tokens[] = { '.', 'e', 'E', '+', '-' };
379 
380  TokenType type = tokenInteger;
381 
382  if ( current_ != end_ )
383  {
384  if (*current_ == '-')
385  ++current_;
386 
387  while ( current_ != end_ )
388  {
389  if (!std::isdigit (static_cast<unsigned char>(*current_)))
390  {
391  auto ret = std::find (std::begin (extended_tokens),
392  std::end (extended_tokens), *current_);
393 
394  if (ret == std::end (extended_tokens))
395  break;
396 
397  type = tokenDouble;
398  }
399 
400  ++current_;
401  }
402  }
403 
404  return type;
405 }
406 
407 bool
409 {
410  Char c = 0;
411 
412  while ( current_ != end_ )
413  {
414  c = getNextChar ();
415 
416  if ( c == '\\' )
417  getNextChar ();
418  else if ( c == '"' )
419  break;
420  }
421 
422  return c == '"';
423 }
424 
425 
426 bool
427 Reader::readObject(Token& tokenStart, unsigned depth)
428 {
429  Token tokenName;
430  std::string name;
431  currentValue () = Value ( objectValue );
432 
433  while ( readToken ( tokenName ) )
434  {
435  bool initialTokenOk = true;
436 
437  while ( tokenName.type_ == tokenComment && initialTokenOk )
438  initialTokenOk = readToken ( tokenName );
439 
440  if ( !initialTokenOk )
441  break;
442 
443  if ( tokenName.type_ == tokenObjectEnd && name.empty () ) // empty object
444  return true;
445 
446  if ( tokenName.type_ != tokenString )
447  break;
448 
449  name = "";
450 
451  if ( !decodeString ( tokenName, name ) )
452  return recoverFromError ( tokenObjectEnd );
453 
454  Token colon;
455 
456  if ( !readToken ( colon ) || colon.type_ != tokenMemberSeparator )
457  {
458  return addErrorAndRecover ( "Missing ':' after object member name",
459  colon,
460  tokenObjectEnd );
461  }
462 
463  // Reject duplicate names
464  if (currentValue ().isMember (name))
465  return addError ( "Key '" + name + "' appears twice.", tokenName );
466 
467  Value& value = currentValue ()[ name ];
468  nodes_.push ( &value );
469  bool ok = readValue(depth+1);
470  nodes_.pop ();
471 
472  if ( !ok ) // error already set
473  return recoverFromError ( tokenObjectEnd );
474 
475  Token comma;
476 
477  if ( !readToken ( comma )
478  || ( comma.type_ != tokenObjectEnd &&
479  comma.type_ != tokenArraySeparator &&
480  comma.type_ != tokenComment ) )
481  {
482  return addErrorAndRecover ( "Missing ',' or '}' in object declaration",
483  comma,
484  tokenObjectEnd );
485  }
486 
487  bool finalizeTokenOk = true;
488 
489  while ( comma.type_ == tokenComment &&
490  finalizeTokenOk )
491  finalizeTokenOk = readToken ( comma );
492 
493  if ( comma.type_ == tokenObjectEnd )
494  return true;
495  }
496 
497  return addErrorAndRecover ( "Missing '}' or object member name",
498  tokenName,
499  tokenObjectEnd );
500 }
501 
502 
503 bool
504 Reader::readArray(Token& tokenStart, unsigned depth)
505 {
506  currentValue () = Value ( arrayValue );
507  skipSpaces ();
508 
509  if ( *current_ == ']' ) // empty array
510  {
511  Token endArray;
512  readToken ( endArray );
513  return true;
514  }
515 
516  int index = 0;
517 
518  while ( true )
519  {
520  Value& value = currentValue ()[ index++ ];
521  nodes_.push ( &value );
522  bool ok = readValue(depth+1);
523  nodes_.pop ();
524 
525  if ( !ok ) // error already set
526  return recoverFromError ( tokenArrayEnd );
527 
528  Token token;
529  // Accept Comment after last item in the array.
530  ok = readToken ( token );
531 
532  while ( token.type_ == tokenComment && ok )
533  {
534  ok = readToken ( token );
535  }
536 
537  bool badTokenType = ( token.type_ != tokenArraySeparator &&
538  token.type_ != tokenArrayEnd );
539 
540  if ( !ok || badTokenType )
541  {
542  return addErrorAndRecover ( "Missing ',' or ']' in array declaration",
543  token,
544  tokenArrayEnd );
545  }
546 
547  if ( token.type_ == tokenArrayEnd )
548  break;
549  }
550 
551  return true;
552 }
553 
554 bool
556 {
557  Location current = token.start_;
558  bool isNegative = *current == '-';
559 
560  if ( isNegative )
561  ++current;
562 
563  if (current == token.end_)
564  {
565  return addError ( "'" + std::string ( token.start_, token.end_ ) +
566  "' is not a valid number.", token );
567  }
568 
569  // The existing Json integers are 32-bit so using a 64-bit value here avoids
570  // overflows in the conversion code below.
571  std::int64_t value = 0;
572 
573  static_assert(sizeof(value) > sizeof(Value::maxUInt),
574  "The JSON integer overflow logic will need to be reworked.");
575 
576  while (current < token.end_ && (value <= Value::maxUInt))
577  {
578  Char c = *current++;
579 
580  if ( c < '0' || c > '9' )
581  {
582  return addError ( "'" + std::string ( token.start_, token.end_ ) +
583  "' is not a number.", token );
584  }
585 
586  value = (value * 10) + (c - '0');
587  }
588 
589  // More tokens left -> input is larger than largest possible return value
590  if (current != token.end_)
591  {
592  return addError ( "'" + std::string ( token.start_, token.end_ ) +
593  "' exceeds the allowable range.", token );
594  }
595 
596  if ( isNegative )
597  {
598  value = -value;
599 
600  if (value < Value::minInt || value > Value::maxInt)
601  {
602  return addError ( "'" + std::string ( token.start_, token.end_ ) +
603  "' exceeds the allowable range.", token );
604  }
605 
606  currentValue () = static_cast<Value::Int>( value );
607  }
608  else
609  {
610  if (value > Value::maxUInt)
611  {
612  return addError ( "'" + std::string ( token.start_, token.end_ ) +
613  "' exceeds the allowable range.", token );
614  }
615 
616  // If it's representable as a signed integer, construct it as one.
617  if ( value <= Value::maxInt )
618  currentValue () = static_cast<Value::Int>( value );
619  else
620  currentValue () = static_cast<Value::UInt>( value );
621  }
622 
623  return true;
624 }
625 
626 bool
628 {
629  double value = 0;
630  const int bufferSize = 32;
631  int count;
632  int length = int(token.end_ - token.start_);
633  // Sanity check to avoid buffer overflow exploits.
634  if (length < 0) {
635  return addError( "Unable to parse token length", token );
636  }
637  // Avoid using a string constant for the format control string given to
638  // sscanf, as this can cause hard to debug crashes on OS X. See here for more
639  // info:
640  //
641  // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
642  char format[] = "%lf";
643  if ( length <= bufferSize )
644  {
645  Char buffer[bufferSize+1];
646  memcpy( buffer, token.start_, length );
647  buffer[length] = 0;
648  count = sscanf( buffer, format, &value );
649  }
650  else
651  {
652  std::string buffer( token.start_, token.end_ );
653  count = sscanf( buffer.c_str(), format, &value );
654  }
655  if ( count != 1 )
656  return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
657  currentValue() = value;
658  return true;
659 }
660 
661 
662 
663 bool
665 {
666  std::string decoded;
667 
668  if ( !decodeString ( token, decoded ) )
669  return false;
670 
671  currentValue () = decoded;
672  return true;
673 }
674 
675 
676 bool
678 {
679  decoded.reserve ( token.end_ - token.start_ - 2 );
680  Location current = token.start_ + 1; // skip '"'
681  Location end = token.end_ - 1; // do not include '"'
682 
683  while ( current != end )
684  {
685  Char c = *current++;
686 
687  if ( c == '"' )
688  break;
689  else if ( c == '\\' )
690  {
691  if ( current == end )
692  return addError ( "Empty escape sequence in string", token, current );
693 
694  Char escape = *current++;
695 
696  switch ( escape )
697  {
698  case '"':
699  decoded += '"';
700  break;
701 
702  case '/':
703  decoded += '/';
704  break;
705 
706  case '\\':
707  decoded += '\\';
708  break;
709 
710  case 'b':
711  decoded += '\b';
712  break;
713 
714  case 'f':
715  decoded += '\f';
716  break;
717 
718  case 'n':
719  decoded += '\n';
720  break;
721 
722  case 'r':
723  decoded += '\r';
724  break;
725 
726  case 't':
727  decoded += '\t';
728  break;
729 
730  case 'u':
731  {
732  unsigned int unicode;
733 
734  if ( !decodeUnicodeCodePoint ( token, current, end, unicode ) )
735  return false;
736 
737  decoded += codePointToUTF8 (unicode);
738  }
739  break;
740 
741  default:
742  return addError ( "Bad escape sequence in string", token, current );
743  }
744  }
745  else
746  {
747  decoded += c;
748  }
749  }
750 
751  return true;
752 }
753 
754 bool
756  Location& current,
757  Location end,
758  unsigned int& unicode )
759 {
760 
761  if ( !decodeUnicodeEscapeSequence ( token, current, end, unicode ) )
762  return false;
763 
764  if (unicode >= 0xD800 && unicode <= 0xDBFF)
765  {
766  // surrogate pairs
767  if (end - current < 6)
768  return addError ( "additional six characters expected to parse unicode surrogate pair.", token, current );
769 
770  unsigned int surrogatePair;
771 
772  if (* (current++) == '\\' && * (current++) == 'u')
773  {
774  if (decodeUnicodeEscapeSequence ( token, current, end, surrogatePair ))
775  {
776  unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
777  }
778  else
779  return false;
780  }
781  else
782  return addError ( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current );
783  }
784 
785  return true;
786 }
787 
788 bool
790  Location& current,
791  Location end,
792  unsigned int& unicode )
793 {
794  if ( end - current < 4 )
795  return addError ( "Bad unicode escape sequence in string: four digits expected.", token, current );
796 
797  unicode = 0;
798 
799  for ( int index = 0; index < 4; ++index )
800  {
801  Char c = *current++;
802  unicode *= 16;
803 
804  if ( c >= '0' && c <= '9' )
805  unicode += c - '0';
806  else if ( c >= 'a' && c <= 'f' )
807  unicode += c - 'a' + 10;
808  else if ( c >= 'A' && c <= 'F' )
809  unicode += c - 'A' + 10;
810  else
811  return addError ( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current );
812  }
813 
814  return true;
815 }
816 
817 
818 bool
819 Reader::addError ( std::string const& message,
820  Token& token,
821  Location extra )
822 {
823  ErrorInfo info;
824  info.token_ = token;
825  info.message_ = message;
826  info.extra_ = extra;
827  errors_.push_back ( info );
828  return false;
829 }
830 
831 
832 bool
834 {
835  int errorCount = int (errors_.size ());
836  Token skip;
837 
838  while ( true )
839  {
840  if ( !readToken (skip) )
841  errors_.resize ( errorCount ); // discard errors caused by recovery
842 
843  if ( skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream )
844  break;
845  }
846 
847  errors_.resize ( errorCount );
848  return false;
849 }
850 
851 
852 bool
854  Token& token,
855  TokenType skipUntilToken )
856 {
857  addError ( message, token );
858  return recoverFromError ( skipUntilToken );
859 }
860 
861 
862 Value&
864 {
865  return * (nodes_.top ());
866 }
867 
868 
871 {
872  if ( current_ == end_ )
873  return 0;
874 
875  return *current_++;
876 }
877 
878 
879 void
881  int& line,
882  int& column ) const
883 {
884  Location current = begin_;
885  Location lastLineStart = current;
886  line = 0;
887 
888  while ( current < location && current != end_ )
889  {
890  Char c = *current++;
891 
892  if ( c == '\r' )
893  {
894  if ( *current == '\n' )
895  ++current;
896 
897  lastLineStart = current;
898  ++line;
899  }
900  else if ( c == '\n' )
901  {
902  lastLineStart = current;
903  ++line;
904  }
905  }
906 
907  // column & line start at 1
908  column = int (location - lastLineStart) + 1;
909  ++line;
910 }
911 
912 
915 {
916  int line, column;
917  getLocationLineAndColumn ( location, line, column );
918  char buffer[18 + 16 + 16 + 1];
919  sprintf ( buffer, "Line %d, Column %d", line, column );
920  return buffer;
921 }
922 
923 
926 {
927  std::string formattedMessage;
928 
929  for ( Errors::const_iterator itError = errors_.begin ();
930  itError != errors_.end ();
931  ++itError )
932  {
933  const ErrorInfo& error = *itError;
934  formattedMessage += "* " + getLocationLineAndColumn ( error.token_.start_ ) + "\n";
935  formattedMessage += " " + error.message_ + "\n";
936 
937  if ( error.extra_ )
938  formattedMessage += "See " + getLocationLineAndColumn ( error.extra_ ) + " for detail.\n";
939  }
940 
941  return formattedMessage;
942 }
943 
944 
946 {
947  Json::Reader reader;
948  bool ok = reader.parse (sin, root);
949 
950  //JSON_ASSERT( ok );
951  if (! ok)
952  ripple::Throw<std::runtime_error> (reader.getFormatedErrorMessages ());
953 
954  return sin;
955 }
956 
957 
958 } // namespace Json
Json::error
Definition: json_errors.h:28
Json::Value::Int
Json::Int Int
Definition: json_value.h:150
std::string::resize
T resize(T... args)
Json::Reader::tokenFalse
@ tokenFalse
Definition: json_reader.h:98
Json::Reader::addError
bool addError(std::string const &message, Token &token, Location extra=0)
Definition: json_reader.cpp:819
Json::Value::isObject
bool isObject() const
Definition: json_value.cpp:1069
std::string
STL class.
Json::Reader::Token::start_
Location start_
Definition: json_reader.h:112
Json::Reader::skipCommentTokens
void skipCommentTokens(Token &token)
Definition: json_reader.cpp:187
Json::Reader::Token
Definition: json_reader.h:106
Json::Reader::current_
Location current_
Definition: json_reader.h:175
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition: json_value.h:44
Json::Reader::decodeDouble
bool decodeDouble(Token &token)
Definition: json_reader.cpp:627
std::string::reserve
T reserve(T... args)
Json::Reader::nodes_
Nodes nodes_
Definition: json_reader.h:170
Json::Reader::decodeString
bool decodeString(Token &token)
Definition: json_reader.cpp:664
std::find
T find(T... args)
std::string::length
T length(T... args)
Json::Reader::readCStyleComment
bool readCStyleComment()
Definition: json_reader.cpp:347
Json::Reader::tokenComment
@ tokenComment
Definition: json_reader.h:102
Json::Reader::readObject
bool readObject(Token &token, unsigned depth)
Definition: json_reader.cpp:427
Json::Value::isNull
bool isNull() const
isNull() tests to see if this field is null.
Definition: json_value.cpp:998
Json::Reader::ErrorInfo
Definition: json_reader.h:116
Json::Reader
Unserialize a JSON document into a Value.
Definition: json_reader.h:36
Json::Reader::expectToken
bool expectToken(TokenType type, Token &token, const char *message)
Definition: json_reader.cpp:198
Json::Reader::ErrorInfo::extra_
Location extra_
Definition: json_reader.h:123
Json::Reader::tokenTrue
@ tokenTrue
Definition: json_reader.h:97
Json::Reader::readValue
bool readValue(unsigned depth)
Definition: json_reader.cpp:136
algorithm
Json::Reader::tokenMemberSeparator
@ tokenMemberSeparator
Definition: json_reader.h:101
std::deque::clear
T clear(T... args)
std::deque::push_back
T push_back(T... args)
Json::Reader::lastValueEnd_
Location lastValueEnd_
Definition: json_reader.h:176
Json::Reader::Token::type_
TokenType type_
Definition: json_reader.h:111
Json::Value::maxInt
static const Int maxInt
Definition: json_value.h:155
Json
JSON (JavaScript Object Notation).
Definition: json_reader.cpp:26
Json::Reader::ErrorInfo::token_
Token token_
Definition: json_reader.h:121
Json::Reader::document_
std::string document_
Definition: json_reader.h:172
Json::Reader::decodeNumber
bool decodeNumber(Token &token)
Definition: json_reader.cpp:555
Json::Reader::end_
Location end_
Definition: json_reader.h:174
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:45
Json::Reader::match
bool match(Location pattern, int patternLength)
Definition: json_reader.cpp:315
Json::Reader::tokenObjectBegin
@ tokenObjectBegin
Definition: json_reader.h:90
std::string::c_str
T c_str(T... args)
Json::Reader::tokenEndOfStream
@ tokenEndOfStream
Definition: json_reader.h:89
std::stack::pop
T pop(T... args)
std::stack::top
T top(T... args)
Json::Reader::decodeUnicodeCodePoint
bool decodeUnicodeCodePoint(Token &token, Location &current, Location end, unsigned int &unicode)
Definition: json_reader.cpp:755
Json::Reader::getLocationLineAndColumn
void getLocationLineAndColumn(Location location, int &line, int &column) const
Definition: json_reader.cpp:880
Json::Reader::decodeUnicodeEscapeSequence
bool decodeUnicodeEscapeSequence(Token &token, Location &current, Location end, unsigned int &unicode)
Definition: json_reader.cpp:789
Json::Reader::currentValue
Value & currentValue()
Definition: json_reader.cpp:863
std::int64_t
Json::Reader::begin_
Location begin_
Definition: json_reader.h:173
Json::Reader::TokenType
TokenType
Definition: json_reader.h:87
Json::Reader::tokenInteger
@ tokenInteger
Definition: json_reader.h:95
Json::Value::UInt
Json::UInt UInt
Definition: json_value.h:149
Json::Reader::skipSpaces
void skipSpaces()
Definition: json_reader.cpp:300
Json::Value::isArray
bool isArray() const
Definition: json_value.cpp:1056
Json::Reader::tokenArrayBegin
@ tokenArrayBegin
Definition: json_reader.h:92
Json::Reader::readComment
bool readComment()
Definition: json_reader.cpp:333
Json::Reader::Token::end_
Location end_
Definition: json_reader.h:113
Json::Reader::Char
char Char
Definition: json_reader.h:39
Json::Reader::tokenObjectEnd
@ tokenObjectEnd
Definition: json_reader.h:91
Json::Reader::Location
const Char * Location
Definition: json_reader.h:40
Json::Reader::tokenDouble
@ tokenDouble
Definition: json_reader.h:96
Json::Reader::errors_
Errors errors_
Definition: json_reader.h:171
Json::Value::maxUInt
static const UInt maxUInt
Definition: json_value.h:156
Json::Reader::tokenArrayEnd
@ tokenArrayEnd
Definition: json_reader.h:93
Json::codePointToUTF8
static std::string codePointToUTF8(unsigned int cp)
Definition: json_reader.cpp:35
Json::operator>>
std::istream & operator>>(std::istream &sin, Value &root)
Read from 'sin' into 'root'.
Definition: json_reader.cpp:945
std::begin
T begin(T... args)
std::getline
T getline(T... args)
Json::Reader::nest_limit
static constexpr unsigned nest_limit
Definition: json_reader.h:84
Json::Reader::readToken
bool readToken(Token &token)
Definition: json_reader.cpp:210
Json::Reader::parse
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
Definition: json_reader.cpp:76
Json::Reader::getFormatedErrorMessages
std::string getFormatedErrorMessages() const
Returns a user friendly string that list errors in the parsed document.
Definition: json_reader.cpp:925
cctype
Json::Reader::lastValue_
Value * lastValue_
Definition: json_reader.h:177
Json::Reader::recoverFromError
bool recoverFromError(TokenType skipUntilToken)
Definition: json_reader.cpp:833
std::stack::empty
T empty(T... args)
std::stack::push
T push(T... args)
std::end
T end(T... args)
Json::Reader::readArray
bool readArray(Token &token, unsigned depth)
Definition: json_reader.cpp:504
Json::Reader::readNumber
Reader::TokenType readNumber()
Definition: json_reader.cpp:376
Json::Reader::ErrorInfo::message_
std::string message_
Definition: json_reader.h:122
Json::Reader::readCppStyleComment
bool readCppStyleComment()
Definition: json_reader.cpp:362
std::istream
STL class.
Json::Reader::getNextChar
Char getNextChar()
Definition: json_reader.cpp:870
Json::Reader::tokenNull
@ tokenNull
Definition: json_reader.h:99
Json::Reader::tokenString
@ tokenString
Definition: json_reader.h:94
Json::Reader::addErrorAndRecover
bool addErrorAndRecover(std::string const &message, Token &token, TokenType skipUntilToken)
Definition: json_reader.cpp:853
Json::Reader::tokenError
@ tokenError
Definition: json_reader.h:103
Json::Value
Represents a JSON value.
Definition: json_value.h:141
Json::Reader::readString
bool readString()
Definition: json_reader.cpp:408
Json::Reader::tokenArraySeparator
@ tokenArraySeparator
Definition: json_reader.h:100
string