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