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