1f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III// Copyright 2007-2011 Baptiste Lepilleur
2f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III// Distributed under MIT license, or public domain if desired and
3f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III// recognized in your jurisdiction.
4f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
6f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III#if !defined(JSON_IS_AMALGAMATION)
72eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger#include <json/assertions.h>
82eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger#include <json/reader.h>
92eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger#include <json/value.h>
102eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger#include "json_tool.h"
11f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III#endif // if !defined(JSON_IS_AMALGAMATION)
125021d59dfbed53039ac6f20e198dc3684245b495Greg Hartman#include <iostream>
135021d59dfbed53039ac6f20e198dc3684245b495Greg Hartman#include <fstream>
14f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III#include <utility>
15f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III#include <cstdio>
16f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III#include <cassert>
17f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III#include <cstring>
182eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger#include <istream>
19f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
202eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below
212eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger#define snprintf _snprintf
222eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger#endif
232eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
242eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
252eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger// Disable warning about strdup being deprecated.
262eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger#pragma warning(disable : 4996)
27f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III#endif
28f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
29f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIInamespace Json {
30f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
31f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III// Implementation of class Features
32f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III// ////////////////////////////////
33f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
34f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIFeatures::Features()
352eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    : allowComments_(true), strictRoot_(false),
362eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
37f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
382eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek SollenbergerFeatures Features::all() { return Features(); }
39f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
402eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek SollenbergerFeatures Features::strictMode() {
412eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Features features;
422eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  features.allowComments_ = false;
432eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  features.strictRoot_ = true;
442eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  features.allowDroppedNullPlaceholders_ = false;
452eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  features.allowNumericKeys_ = false;
462eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return features;
47f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
48f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
49f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III// Implementation of class Reader
50f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III// ////////////////////////////////
51f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
522eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerstatic inline bool in(Reader::Char c,
532eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                      Reader::Char c1,
542eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                      Reader::Char c2,
552eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                      Reader::Char c3,
562eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                      Reader::Char c4) {
572eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return c == c1 || c == c2 || c == c3 || c == c4;
58f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
59f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
602eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerstatic inline bool in(Reader::Char c,
612eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                      Reader::Char c1,
622eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                      Reader::Char c2,
632eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                      Reader::Char c3,
642eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                      Reader::Char c4,
652eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                      Reader::Char c5) {
662eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return c == c1 || c == c2 || c == c3 || c == c4 || c == c5;
67f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
68f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
692eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerstatic bool containsNewLine(Reader::Location begin, Reader::Location end) {
702eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  for (; begin < end; ++begin)
712eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (*begin == '\n' || *begin == '\r')
722eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      return true;
732eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return false;
74f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
75f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
76f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III// Class Reader
77f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III// //////////////////////////////////////////////////////////////////
78f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
79f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIReader::Reader()
802eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
812eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      lastValue_(), commentsBefore_(), features_(Features::all()),
822eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      collectComments_() {}
83f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
842eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek SollenbergerReader::Reader(const Features& features)
852eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
862eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      lastValue_(), commentsBefore_(), features_(features), collectComments_() {
87f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
88f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
89f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIbool
902eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek SollenbergerReader::parse(const std::string& document, Value& root, bool collectComments) {
912eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  document_ = document;
922eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  const char* begin = document_.c_str();
932eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  const char* end = begin + document_.length();
942eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return parse(begin, end, root, collectComments);
952eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
962eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
972eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::parse(std::istream& sin, Value& root, bool collectComments) {
982eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  // std::istream_iterator<char> begin(sin);
992eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  // std::istream_iterator<char> end;
1002eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  // Those would allow streamed input from a file, if parse() were a
1012eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  // template function.
1022eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
1032eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  // Since std::string is reference-counted, this at least does not
1042eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  // create an extra copy.
1052eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  std::string doc;
1062eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  std::getline(sin, doc, (char)EOF);
1072eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return parse(doc, root, collectComments);
1082eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
1092eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
1102eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::parse(const char* beginDoc,
1112eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                   const char* endDoc,
1122eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                   Value& root,
1132eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                   bool collectComments) {
1142eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (!features_.allowComments_) {
1152eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    collectComments = false;
1162eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
1172eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
1182eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  begin_ = beginDoc;
1192eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  end_ = endDoc;
1202eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  collectComments_ = collectComments;
1212eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  current_ = begin_;
1222eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  lastValueEnd_ = 0;
1232eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  lastValue_ = 0;
1242eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  commentsBefore_ = "";
1252eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  errors_.clear();
1262eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  while (!nodes_.empty())
1272eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    nodes_.pop();
1282eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  nodes_.push(&root);
1292eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
1302eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  bool successful = readValue();
1312eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Token token;
1322eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  skipCommentTokens(token);
1332eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (collectComments_ && !commentsBefore_.empty())
1342eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    root.setComment(commentsBefore_, commentAfter);
1352eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (features_.strictRoot_) {
1362eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (!root.isArray() && !root.isObject()) {
1372eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      // Set error location to start of doc, ideally should be first token found
1382eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      // in doc
1392eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      token.type_ = tokenError;
1402eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      token.start_ = beginDoc;
1412eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      token.end_ = endDoc;
1422eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      addError(
1432eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger          "A valid JSON document must be either an array or an object value.",
1442eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger          token);
1452eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      return false;
1462eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    }
1472eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
1482eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return successful;
1492eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
1502eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
1512eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::readValue() {
1522eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Token token;
1532eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  skipCommentTokens(token);
1542eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  bool successful = true;
1552eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
1562eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (collectComments_ && !commentsBefore_.empty()) {
1572eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    // Remove newline characters at the end of the comments
1582eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    size_t lastNonNewline = commentsBefore_.find_last_not_of("\r\n");
1592eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (lastNonNewline != std::string::npos) {
1602eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      commentsBefore_.erase(lastNonNewline + 1);
1612eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    } else {
1622eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      commentsBefore_.clear();
1632eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    }
164f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
1652eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    currentValue().setComment(commentsBefore_, commentBefore);
1662eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    commentsBefore_ = "";
1672eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
1682eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
1692eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  switch (token.type_) {
1702eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case tokenObjectBegin:
1712eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    successful = readObject(token);
1722eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    currentValue().setOffsetLimit(current_ - begin_);
1732eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    break;
1742eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case tokenArrayBegin:
1752eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    successful = readArray(token);
1762eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    currentValue().setOffsetLimit(current_ - begin_);
1772eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    break;
1782eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case tokenNumber:
1792eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    successful = decodeNumber(token);
1802eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    break;
1812eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case tokenString:
1822eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    successful = decodeString(token);
1832eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    break;
1842eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case tokenTrue:
1852eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    currentValue() = true;
1862eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    currentValue().setOffsetStart(token.start_ - begin_);
1872eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    currentValue().setOffsetLimit(token.end_ - begin_);
1882eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    break;
1892eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case tokenFalse:
1902eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    currentValue() = false;
1912eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    currentValue().setOffsetStart(token.start_ - begin_);
1922eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    currentValue().setOffsetLimit(token.end_ - begin_);
1932eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    break;
1942eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case tokenNull:
1952eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    currentValue() = Value();
1962eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    currentValue().setOffsetStart(token.start_ - begin_);
1972eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    currentValue().setOffsetLimit(token.end_ - begin_);
1982eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    break;
1992eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case tokenArraySeparator:
2002eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (features_.allowDroppedNullPlaceholders_) {
2012eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      // "Un-read" the current token and mark the current value as a null
2022eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      // token.
2032eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      current_--;
204f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      currentValue() = Value();
2052eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      currentValue().setOffsetStart(current_ - begin_ - 1);
2062eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      currentValue().setOffsetLimit(current_ - begin_);
2072eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      break;
2082eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    }
2092eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  // Else, fall through...
2102eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  default:
2112eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    currentValue().setOffsetStart(token.start_ - begin_);
2122eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    currentValue().setOffsetLimit(token.end_ - begin_);
2132eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    return addError("Syntax error: value, object or array expected.", token);
2142eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
2152eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
2162eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (collectComments_) {
2172eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    lastValueEnd_ = current_;
2182eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    lastValue_ = &currentValue();
2192eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
2202eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
2212eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return successful;
2222eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
2232eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
2242eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergervoid Reader::skipCommentTokens(Token& token) {
2252eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (features_.allowComments_) {
2262eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    do {
2272eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      readToken(token);
2282eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    } while (token.type_ == tokenComment);
2292eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  } else {
2302eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    readToken(token);
2312eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
2322eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
2332eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
2342eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::expectToken(TokenType type, Token& token, const char* message) {
2352eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  readToken(token);
2362eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (token.type_ != type)
2372eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    return addError(message, token);
2382eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return true;
2392eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
2402eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
2412eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::readToken(Token& token) {
2422eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  skipSpaces();
2432eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  token.start_ = current_;
2442eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Char c = getNextChar();
2452eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  bool ok = true;
2462eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  switch (c) {
2472eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case '{':
2482eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    token.type_ = tokenObjectBegin;
2492eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    break;
2502eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case '}':
2512eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    token.type_ = tokenObjectEnd;
2522eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    break;
2532eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case '[':
2542eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    token.type_ = tokenArrayBegin;
2552eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    break;
2562eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case ']':
2572eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    token.type_ = tokenArrayEnd;
2582eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    break;
2592eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case '"':
2602eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    token.type_ = tokenString;
2612eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    ok = readString();
2622eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    break;
2632eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case '/':
2642eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    token.type_ = tokenComment;
2652eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    ok = readComment();
2662eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    break;
2672eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case '0':
2682eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case '1':
2692eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case '2':
2702eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case '3':
2712eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case '4':
2722eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case '5':
2732eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case '6':
2742eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case '7':
2752eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case '8':
2762eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case '9':
2772eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case '-':
2782eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    token.type_ = tokenNumber;
2792eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    readNumber();
2802eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    break;
2812eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case 't':
2822eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    token.type_ = tokenTrue;
2832eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    ok = match("rue", 3);
2842eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    break;
2852eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case 'f':
2862eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    token.type_ = tokenFalse;
2872eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    ok = match("alse", 4);
2882eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    break;
2892eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case 'n':
2902eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    token.type_ = tokenNull;
2912eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    ok = match("ull", 3);
2922eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    break;
2932eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case ',':
2942eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    token.type_ = tokenArraySeparator;
2952eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    break;
2962eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case ':':
2972eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    token.type_ = tokenMemberSeparator;
2982eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    break;
2992eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  case 0:
3002eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    token.type_ = tokenEndOfStream;
3012eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    break;
3022eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  default:
3032eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    ok = false;
3042eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    break;
3052eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
3062eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (!ok)
3072eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    token.type_ = tokenError;
3082eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  token.end_ = current_;
3092eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return true;
3102eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
3112eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
3122eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergervoid Reader::skipSpaces() {
3132eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  while (current_ != end_) {
3142eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    Char c = *current_;
3152eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
3162eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      ++current_;
3172eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    else
318f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      break;
3192eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
3202eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
321f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
3222eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::match(Location pattern, int patternLength) {
3232eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (end_ - current_ < patternLength)
3242eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    return false;
3252eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  int index = patternLength;
3262eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  while (index--)
3272eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (current_[index] != pattern[index])
3282eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      return false;
3292eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  current_ += patternLength;
3302eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return true;
3312eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
3322eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
3332eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::readComment() {
3342eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Location commentBegin = current_ - 1;
3352eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Char c = getNextChar();
3362eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  bool successful = false;
3372eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (c == '*')
3382eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    successful = readCStyleComment();
3392eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  else if (c == '/')
3402eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    successful = readCppStyleComment();
3412eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (!successful)
3422eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    return false;
3432eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
3442eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (collectComments_) {
3452eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    CommentPlacement placement = commentBefore;
3462eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
3472eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      if (c != '*' || !containsNewLine(commentBegin, current_))
3482eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        placement = commentAfterOnSameLine;
3492eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    }
350f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
3512eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    addComment(commentBegin, current_, placement);
3522eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
3532eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return true;
354f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
355f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
3562eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergervoid
3572eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek SollenbergerReader::addComment(Location begin, Location end, CommentPlacement placement) {
3582eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  assert(collectComments_);
3592eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (placement == commentAfterOnSameLine) {
3602eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    assert(lastValue_ != 0);
3612eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    lastValue_->setComment(std::string(begin, end), placement);
3622eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  } else {
3632eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    commentsBefore_ += std::string(begin, end);
3642eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
3652eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
366f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
3672eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::readCStyleComment() {
3682eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  while (current_ != end_) {
3692eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    Char c = getNextChar();
3702eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (c == '*' && *current_ == '/')
371f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      break;
3722eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
3732eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return getNextChar() == '/';
374f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
375f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
3762eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::readCppStyleComment() {
3772eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  while (current_ != end_) {
3782eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    Char c = getNextChar();
3792eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (c == '\r' || c == '\n')
3802eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      break;
3812eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
3822eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return true;
383f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
384f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
3852eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergervoid Reader::readNumber() {
3862eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  while (current_ != end_) {
3872eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (!(*current_ >= '0' && *current_ <= '9') &&
3882eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        !in(*current_, '.', 'e', 'E', '+', '-'))
3892eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      break;
3902eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    ++current_;
3912eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
392f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
393f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
3942eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::readString() {
3952eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Char c = 0;
3962eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  while (current_ != end_) {
3972eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    c = getNextChar();
3982eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (c == '\\')
3992eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      getNextChar();
4002eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    else if (c == '"')
4012eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      break;
4022eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
4032eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return c == '"';
4042eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
4052eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
4062eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::readObject(Token& tokenStart) {
4072eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Token tokenName;
4082eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  std::string name;
4092eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  currentValue() = Value(objectValue);
4102eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  currentValue().setOffsetStart(tokenStart.start_ - begin_);
4112eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  while (readToken(tokenName)) {
4122eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    bool initialTokenOk = true;
4132eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    while (tokenName.type_ == tokenComment && initialTokenOk)
4142eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      initialTokenOk = readToken(tokenName);
4152eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (!initialTokenOk)
4162eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      break;
4172eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
4182eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      return true;
4192eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    name = "";
4202eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (tokenName.type_ == tokenString) {
4212eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      if (!decodeString(tokenName, name))
4222eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        return recoverFromError(tokenObjectEnd);
4232eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
4242eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      Value numberName;
4252eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      if (!decodeNumber(tokenName, numberName))
4262eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        return recoverFromError(tokenObjectEnd);
4272eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      name = numberName.asString();
4282eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    } else {
4292eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      break;
4302eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    }
431f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
4322eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    Token colon;
4332eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
4342eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      return addErrorAndRecover(
4352eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger          "Missing ':' after object member name", colon, tokenObjectEnd);
4362eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    }
4372eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    Value& value = currentValue()[name];
4382eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    nodes_.push(&value);
4392eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    bool ok = readValue();
4402eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    nodes_.pop();
4412eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (!ok) // error already set
4422eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      return recoverFromError(tokenObjectEnd);
4432eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
4442eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    Token comma;
4452eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (!readToken(comma) ||
4462eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
4472eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger         comma.type_ != tokenComment)) {
4482eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      return addErrorAndRecover(
4492eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger          "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
4502eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    }
4512eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    bool finalizeTokenOk = true;
4522eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    while (comma.type_ == tokenComment && finalizeTokenOk)
4532eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      finalizeTokenOk = readToken(comma);
4542eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (comma.type_ == tokenObjectEnd)
455f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      return true;
4562eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
4572eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return addErrorAndRecover(
4582eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      "Missing '}' or object member name", tokenName, tokenObjectEnd);
4592eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
4602eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
4612eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::readArray(Token& tokenStart) {
4622eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  currentValue() = Value(arrayValue);
4632eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  currentValue().setOffsetStart(tokenStart.start_ - begin_);
4642eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  skipSpaces();
4652eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (*current_ == ']') // empty array
4662eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  {
4672eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    Token endArray;
4682eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    readToken(endArray);
4692eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    return true;
4702eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
4712eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  int index = 0;
4722eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  for (;;) {
4732eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    Value& value = currentValue()[index++];
4742eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    nodes_.push(&value);
4752eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    bool ok = readValue();
4762eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    nodes_.pop();
4772eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (!ok) // error already set
4782eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      return recoverFromError(tokenArrayEnd);
4792eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
4802eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    Token token;
4812eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    // Accept Comment after last item in the array.
4822eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    ok = readToken(token);
4832eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    while (token.type_ == tokenComment && ok) {
4842eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      ok = readToken(token);
4852eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    }
4862eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    bool badTokenType =
4872eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
4882eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (!ok || badTokenType) {
4892eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      return addErrorAndRecover(
4902eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger          "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
4912eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    }
4922eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (token.type_ == tokenArrayEnd)
4932eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      break;
4942eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
4952eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return true;
4962eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
4972eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
4982eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::decodeNumber(Token& token) {
4992eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Value decoded;
5002eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (!decodeNumber(token, decoded))
5012eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    return false;
5022eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  currentValue() = decoded;
5032eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  currentValue().setOffsetStart(token.start_ - begin_);
5042eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  currentValue().setOffsetLimit(token.end_ - begin_);
5052eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return true;
5062eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
5072eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
5082eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::decodeNumber(Token& token, Value& decoded) {
5092eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  bool isDouble = false;
5102eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  for (Location inspect = token.start_; inspect != token.end_; ++inspect) {
5112eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    isDouble = isDouble || in(*inspect, '.', 'e', 'E', '+') ||
5122eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger               (*inspect == '-' && inspect != token.start_);
5132eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
5142eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (isDouble)
5152eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    return decodeDouble(token, decoded);
5162eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  // Attempts to parse the number as an integer. If the number is
5172eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  // larger than the maximum supported value of an integer then
5182eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  // we decode the number as a double.
5192eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Location current = token.start_;
5202eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  bool isNegative = *current == '-';
5212eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (isNegative)
5222eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    ++current;
5232eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Value::LargestUInt maxIntegerValue =
5242eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      isNegative ? Value::LargestUInt(-Value::minLargestInt)
5252eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                 : Value::maxLargestUInt;
5262eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Value::LargestUInt threshold = maxIntegerValue / 10;
5272eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Value::LargestUInt value = 0;
5282eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  while (current < token.end_) {
5292eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    Char c = *current++;
5302eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (c < '0' || c > '9')
5312eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      return addError("'" + std::string(token.start_, token.end_) +
5322eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                          "' is not a number.",
5332eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                      token);
5342eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    Value::UInt digit(c - '0');
5352eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (value >= threshold) {
5362eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      // We've hit or exceeded the max value divided by 10 (rounded down). If
5372eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      // a) we've only just touched the limit, b) this is the last digit, and
5382eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      // c) it's small enough to fit in that rounding delta, we're okay.
5392eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      // Otherwise treat this number as a double to avoid overflow.
5402eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      if (value > threshold || current != token.end_ ||
5412eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger          digit > maxIntegerValue % 10) {
5422eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        return decodeDouble(token, decoded);
543f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      }
5442eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    }
5452eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    value = value * 10 + digit;
5462eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
5472eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (isNegative)
5482eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    decoded = -Value::LargestInt(value);
5492eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  else if (value <= Value::LargestUInt(Value::maxInt))
5502eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    decoded = Value::LargestInt(value);
5512eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  else
5522eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    decoded = value;
5532eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return true;
5542eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
5552eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
5562eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::decodeDouble(Token& token) {
5572eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Value decoded;
5582eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (!decodeDouble(token, decoded))
5592eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    return false;
5602eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  currentValue() = decoded;
5612eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  currentValue().setOffsetStart(token.start_ - begin_);
5622eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  currentValue().setOffsetLimit(token.end_ - begin_);
5632eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return true;
5642eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
5652eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
5662eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::decodeDouble(Token& token, Value& decoded) {
5672eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  double value = 0;
5682eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  const int bufferSize = 32;
5692eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  int count;
5702eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  int length = int(token.end_ - token.start_);
5712eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
5722eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  // Sanity check to avoid buffer overflow exploits.
5732eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (length < 0) {
5742eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    return addError("Unable to parse token length", token);
5752eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
5762eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
5772eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  // Avoid using a string constant for the format control string given to
5782eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  // sscanf, as this can cause hard to debug crashes on OS X. See here for more
5792eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  // info:
5802eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  //
5812eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  //     http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
5822eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  char format[] = "%lf";
5832eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
5842eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (length <= bufferSize) {
5852eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    Char buffer[bufferSize + 1];
5862eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    memcpy(buffer, token.start_, length);
5872eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    buffer[length] = 0;
5882eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    count = sscanf(buffer, format, &value);
5892eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  } else {
5902eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    std::string buffer(token.start_, token.end_);
5912eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    count = sscanf(buffer.c_str(), format, &value);
5922eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
5932eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
5942eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (count != 1)
5952eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    return addError("'" + std::string(token.start_, token.end_) +
5962eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                        "' is not a number.",
5972eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                    token);
5982eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  decoded = value;
5992eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return true;
6002eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
6012eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
6022eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::decodeString(Token& token) {
6032eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  std::string decoded;
6042eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (!decodeString(token, decoded))
6052eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    return false;
6062eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  currentValue() = decoded;
6072eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  currentValue().setOffsetStart(token.start_ - begin_);
6082eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  currentValue().setOffsetLimit(token.end_ - begin_);
6092eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return true;
6102eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
6112eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
6122eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::decodeString(Token& token, std::string& decoded) {
6132eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  decoded.reserve(token.end_ - token.start_ - 2);
6142eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Location current = token.start_ + 1; // skip '"'
6152eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Location end = token.end_ - 1;       // do not include '"'
6162eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  while (current != end) {
6172eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    Char c = *current++;
6182eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (c == '"')
6192eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      break;
6202eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    else if (c == '\\') {
6212eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      if (current == end)
6222eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        return addError("Empty escape sequence in string", token, current);
6232eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      Char escape = *current++;
6242eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      switch (escape) {
6252eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      case '"':
6262eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        decoded += '"';
6272eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        break;
6282eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      case '/':
6292eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        decoded += '/';
6302eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        break;
6312eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      case '\\':
6322eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        decoded += '\\';
6332eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        break;
6342eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      case 'b':
6352eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        decoded += '\b';
6362eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        break;
6372eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      case 'f':
6382eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        decoded += '\f';
6392eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        break;
6402eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      case 'n':
6412eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        decoded += '\n';
6422eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        break;
6432eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      case 'r':
6442eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        decoded += '\r';
6452eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        break;
6462eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      case 't':
6472eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        decoded += '\t';
6482eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        break;
6492eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      case 'u': {
6502eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        unsigned int unicode;
6512eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        if (!decodeUnicodeCodePoint(token, current, end, unicode))
6522eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger          return false;
6532eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        decoded += codePointToUTF8(unicode);
6542eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      } break;
6552eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      default:
6562eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        return addError("Bad escape sequence in string", token, current);
657f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      }
6582eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    } else {
6592eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      decoded += c;
6602eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    }
6612eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
6622eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return true;
6632eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
6642eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
6652eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::decodeUnicodeCodePoint(Token& token,
6662eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                                    Location& current,
6672eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                                    Location end,
6682eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                                    unsigned int& unicode) {
6692eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
6702eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
6712eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    return false;
6722eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (unicode >= 0xD800 && unicode <= 0xDBFF) {
6732eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    // surrogate pairs
6742eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (end - current < 6)
6752eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      return addError(
6762eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger          "additional six characters expected to parse unicode surrogate pair.",
6772eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger          token,
6782eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger          current);
6792eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    unsigned int surrogatePair;
6802eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (*(current++) == '\\' && *(current++) == 'u') {
6812eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
6822eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
6832eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      } else
6842eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        return false;
6852eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    } else
6862eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      return addError("expecting another \\u token to begin the second half of "
6872eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                      "a unicode surrogate pair",
6882eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                      token,
6892eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                      current);
6902eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
6912eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return true;
6922eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
6932eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
6942eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::decodeUnicodeEscapeSequence(Token& token,
6952eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                                         Location& current,
6962eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                                         Location end,
6972eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                                         unsigned int& unicode) {
6982eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (end - current < 4)
6992eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    return addError(
7002eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        "Bad unicode escape sequence in string: four digits expected.",
7012eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        token,
7022eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        current);
7032eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  unicode = 0;
7042eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  for (int index = 0; index < 4; ++index) {
7052eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    Char c = *current++;
7062eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    unicode *= 16;
7072eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (c >= '0' && c <= '9')
7082eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      unicode += c - '0';
7092eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    else if (c >= 'a' && c <= 'f')
7102eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      unicode += c - 'a' + 10;
7112eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    else if (c >= 'A' && c <= 'F')
7122eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      unicode += c - 'A' + 10;
7132eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    else
7142eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      return addError(
7152eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger          "Bad unicode escape sequence in string: hexadecimal digit expected.",
7162eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger          token,
7172eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger          current);
7182eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
7192eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return true;
720f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
721f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
722f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIbool
7232eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek SollenbergerReader::addError(const std::string& message, Token& token, Location extra) {
7242eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  ErrorInfo info;
7252eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  info.token_ = token;
7262eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  info.message_ = message;
7272eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  info.extra_ = extra;
7282eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  errors_.push_back(info);
7292eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return false;
7302eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
7312eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
7322eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::recoverFromError(TokenType skipUntilToken) {
7332eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  int errorCount = int(errors_.size());
7342eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Token skip;
7352eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  for (;;) {
7362eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (!readToken(skip))
7372eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      errors_.resize(errorCount); // discard errors caused by recovery
7382eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
7392eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      break;
7402eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
7412eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  errors_.resize(errorCount);
7422eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return false;
7432eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
7442eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
7452eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::addErrorAndRecover(const std::string& message,
7462eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                                Token& token,
7472eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                                TokenType skipUntilToken) {
7482eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  addError(message, token);
7492eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return recoverFromError(skipUntilToken);
7502eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
7512eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
7522eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek SollenbergerValue& Reader::currentValue() { return *(nodes_.top()); }
7532eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
7542eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek SollenbergerReader::Char Reader::getNextChar() {
7552eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (current_ == end_)
7562eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    return 0;
7572eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return *current_++;
7582eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
7592eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
7602eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergervoid Reader::getLocationLineAndColumn(Location location,
7612eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                                      int& line,
7622eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger                                      int& column) const {
7632eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Location current = begin_;
7642eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Location lastLineStart = current;
7652eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  line = 0;
7662eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  while (current < location && current != end_) {
7672eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    Char c = *current++;
7682eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (c == '\r') {
7692eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      if (*current == '\n')
7702eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        ++current;
7712eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      lastLineStart = current;
7722eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      ++line;
7732eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    } else if (c == '\n') {
7742eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      lastLineStart = current;
7752eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      ++line;
7762eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    }
7772eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
7782eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  // column & line start at 1
7792eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  column = int(location - lastLineStart) + 1;
7802eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  ++line;
7812eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
7822eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
7832eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerstd::string Reader::getLocationLineAndColumn(Location location) const {
7842eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  int line, column;
7852eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  getLocationLineAndColumn(location, line, column);
7862eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  char buffer[18 + 16 + 16 + 1];
7872eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
7882eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger#if defined(WINCE)
7892eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  _snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
7902eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger#else
7912eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  sprintf_s(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
7922eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger#endif
7932eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger#else
7942eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
7952eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger#endif
7962eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return buffer;
797f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
798f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
799f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III// Deprecated. Preserved for backward compatibility
8002eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerstd::string Reader::getFormatedErrorMessages() const {
8012eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return getFormattedErrorMessages();
8022eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
8032eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
8042eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerstd::string Reader::getFormattedErrorMessages() const {
8052eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  std::string formattedMessage;
8062eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  for (Errors::const_iterator itError = errors_.begin();
8072eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger       itError != errors_.end();
8082eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger       ++itError) {
8092eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    const ErrorInfo& error = *itError;
8102eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    formattedMessage +=
8112eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger        "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
8122eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    formattedMessage += "  " + error.message_ + "\n";
8132eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    if (error.extra_)
8142eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger      formattedMessage +=
8152eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger          "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
8162eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
8172eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return formattedMessage;
8182eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
8192eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
8202eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerstd::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
8212eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  std::vector<Reader::StructuredError> allErrors;
8222eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  for (Errors::const_iterator itError = errors_.begin();
8232eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger       itError != errors_.end();
8242eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger       ++itError) {
8252eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    const ErrorInfo& error = *itError;
8262eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    Reader::StructuredError structured;
8272eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    structured.offset_start = error.token_.start_ - begin_;
8282eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    structured.offset_limit = error.token_.end_ - begin_;
8292eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    structured.message = error.message_;
8302eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    allErrors.push_back(structured);
8312eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
8322eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return allErrors;
8332eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
8342eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
8352eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::pushError(const Value& value, const std::string& message) {
8362eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  size_t length = end_ - begin_;
8372eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if(value.getOffsetStart() > length
8382eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    || value.getOffsetLimit() > length)
8392eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    return false;
8402eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Token token;
8412eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  token.type_ = tokenError;
8422eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  token.start_ = begin_ + value.getOffsetStart();
8432eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  token.end_ = end_ + value.getOffsetLimit();
8442eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  ErrorInfo info;
8452eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  info.token_ = token;
8462eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  info.message_ = message;
8472eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  info.extra_ = 0;
8482eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  errors_.push_back(info);
8492eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return true;
8502eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
8512eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
8522eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::pushError(const Value& value, const std::string& message, const Value& extra) {
8532eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  size_t length = end_ - begin_;
8542eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if(value.getOffsetStart() > length
8552eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    || value.getOffsetLimit() > length
8562eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    || extra.getOffsetLimit() > length)
8572eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    return false;
8582eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Token token;
8592eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  token.type_ = tokenError;
8602eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  token.start_ = begin_ + value.getOffsetStart();
8612eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  token.end_ = begin_ + value.getOffsetLimit();
8622eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  ErrorInfo info;
8632eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  info.token_ = token;
8642eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  info.message_ = message;
8652eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  info.extra_ = begin_ + extra.getOffsetStart();
8662eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  errors_.push_back(info);
8672eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return true;
8682eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
8692eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
8702eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerbool Reader::good() const {
8712eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return !errors_.size();
8722eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger}
8732eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
8742eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerstd::istream& operator>>(std::istream& sin, Value& root) {
8752eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  Json::Reader reader;
8762eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  bool ok = reader.parse(sin, root, true);
8772eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  if (!ok) {
8782eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    fprintf(stderr,
8792eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger            "Error from reader: %s",
8802eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger            reader.getFormattedErrorMessages().c_str());
8812eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger
8822eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger    JSON_FAIL_MESSAGE("reader error");
8832eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  }
8842eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger  return sin;
885f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
886f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
887f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III} // namespace Json
888