13f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A JSON parser.  Converts strings of JSON into a Value object (see
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// base/values.h).
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// http://www.ietf.org/rfc/rfc4627.txt?number=4627
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Known limitations/deviations from the RFC:
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// - Only knows how to parse ints within the range of a signed 32 bit int and
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   decimal numbers within a double.
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// - Assumes input is encoded as UTF8.  The spec says we should allow UTF-16
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   (BE or LE) and UTF-32 (BE or LE) as well.
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// - We limit nesting to 100 levels to prevent stack overflow (this is allowed
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   by the RFC).
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// - A Unicode FAQ ("http://unicode.org/faq/utf_bom.html") writes a data
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   stream may start with a Unicode Byte-Order-Mark (U+FEFF), i.e. the input
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   UTF-8 string for the JSONReader::JsonToValue() function may start with a
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   UTF-8 BOM (0xEF, 0xBB, 0xBF).
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   To avoid the function from mis-treating a UTF-8 BOM as an invalid
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   character, the function skips a Unicode BOM at the beginning of the
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   Unicode string (converted from the input UTF-8 string) before parsing it.
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// TODO(tc): Add a parsing option to to relax object keys being wrapped in
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   double quotes
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// TODO(tc): Add an option to disable comment stripping
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// TODO(aa): Consider making the constructor public and the static Read() method
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// only a convenience for the common uses with more complex configuration going
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// on the instance.
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef BASE_JSON_JSON_READER_H_
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define BASE_JSON_JSON_READER_H_
333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <string>
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/base_api.h"
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/basictypes.h"
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Chromium and Chromium OS check out gtest to different places, so we're
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// unable to compile on both if we include gtest_prod.h here.  Instead, include
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// its only contents -- this will need to be updated if the macro ever changes.
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define FRIEND_TEST(test_case_name, test_name)\
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottfriend class test_case_name##_##test_name##_Test
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass Value;
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace base {
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass BASE_API JSONReader {
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // A struct to hold a JS token.
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  class Token {
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott   public:
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    enum Type {
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     OBJECT_BEGIN,           // {
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     OBJECT_END,             // }
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     ARRAY_BEGIN,            // [
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     ARRAY_END,              // ]
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     STRING,
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     NUMBER,
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     BOOL_TRUE,              // true
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     BOOL_FALSE,             // false
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     NULL_TOKEN,             // null
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     LIST_SEPARATOR,         // ,
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     OBJECT_PAIR_SEPARATOR,  // :
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     END_OF_INPUT,
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     INVALID_TOKEN,
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    };
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Token(Type t, const wchar_t* b, int len)
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      : type(t), begin(b), length(len) {}
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    // Get the character that's one past the end of this token.
743f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    wchar_t NextChar() {
753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      return *(begin + length);
763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    }
773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Type type;
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // A pointer into JSONReader::json_pos_ that's the beginning of this token.
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const wchar_t* begin;
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // End should be one char past the end of the token.
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int length;
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Error codes during parsing.
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  enum JsonParseError {
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    JSON_NO_ERROR = 0,
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    JSON_BAD_ROOT_ELEMENT_TYPE,
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    JSON_INVALID_ESCAPE,
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    JSON_SYNTAX_ERROR,
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    JSON_TRAILING_COMMA,
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    JSON_TOO_MUCH_NESTING,
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    JSON_UNEXPECTED_DATA_AFTER_ROOT,
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    JSON_UNSUPPORTED_ENCODING,
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    JSON_UNQUOTED_DICTIONARY_KEY,
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // String versions of parse error codes.
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const char* kBadRootElementType;
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const char* kInvalidEscape;
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const char* kSyntaxError;
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const char* kTrailingComma;
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const char* kTooMuchNesting;
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const char* kUnexpectedDataAfterRoot;
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const char* kUnsupportedEncoding;
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const char* kUnquotedDictionaryKey;
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  JSONReader();
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Reads and parses |json|, returning a Value. The caller owns the returned
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // instance. If |json| is not a properly formed JSON string, returns NULL.
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If |allow_trailing_comma| is true, we will ignore trailing commas in
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // objects and arrays even though this goes against the RFC.
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static Value* Read(const std::string& json, bool allow_trailing_comma);
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Reads and parses |json| like Read(). |error_code_out| and |error_msg_out|
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // are optional. If specified and NULL is returned, they will be populated
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // an error code and a formatted error message (including error location if
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // appropriate). Otherwise, they will be unmodified.
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static Value* ReadAndReturnError(const std::string& json,
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   bool allow_trailing_comma,
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   int* error_code_out,
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   std::string* error_msg_out);
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Converts a JSON parse error code into a human readable message.
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns an empty string if error_code is JSON_NO_ERROR.
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static std::string ErrorCodeToString(JsonParseError error_code);
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns the error code if the last call to JsonToValue() failed.
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns JSON_NO_ERROR otherwise.
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  JsonParseError error_code() const { return error_code_; }
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Converts error_code_ to a human-readable string, including line and column
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // numbers if appropriate.
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string GetErrorMessage() const;
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Reads and parses |json|, returning a Value. The caller owns the returned
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // instance. If |json| is not a properly formed JSON string, returns NULL and
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // a detailed error can be retrieved from |error_message()|.
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If |check_root| is true, we require that the root object be an object or
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // array. Otherwise, it can be any valid JSON type.
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If |allow_trailing_comma| is true, we will ignore trailing commas in
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // objects and arrays even though this goes against the RFC.
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Value* JsonToValue(const std::string& json, bool check_root,
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                     bool allow_trailing_comma);
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FRIEND_TEST(JSONReaderTest, Reading);
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FRIEND_TEST(JSONReaderTest, ErrorMessages);
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
15372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  static std::string FormatErrorMessage(int line, int column,
15472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                        const std::string& description);
15572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Recursively build Value.  Returns NULL if we don't have a valid JSON
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // string.  If |is_root| is true, we verify that the root element is either
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // an object or an array.
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Value* BuildValue(bool is_root);
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Parses a sequence of characters into a Token::NUMBER. If the sequence of
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // characters is not a valid number, returns a Token::INVALID_TOKEN. Note
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // that DecodeNumber is used to actually convert from a string to an
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // int/double.
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Token ParseNumberToken();
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Try and convert the substring that token holds into an int or a double. If
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // we can (ie., no overflow), return the value, else return NULL.
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Value* DecodeNumber(const Token& token);
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Parses a sequence of characters into a Token::STRING. If the sequence of
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // characters is not a valid string, returns a Token::INVALID_TOKEN. Note
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // that DecodeString is used to actually decode the escaped string into an
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // actual wstring.
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Token ParseStringToken();
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Convert the substring into a value string.  This should always succeed
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // (otherwise ParseStringToken would have failed).
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Value* DecodeString(const Token& token);
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Grabs the next token in the JSON stream.  This does not increment the
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // stream so it can be used to look ahead at the next token.
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Token ParseToken();
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Increments |json_pos_| past leading whitespace and comments.
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void EatWhitespaceAndComments();
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If |json_pos_| is at the start of a comment, eat it, otherwise, returns
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // false.
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool EatComment();
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Checks if |json_pos_| matches str.
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool NextStringMatch(const std::wstring& str);
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Sets the error code that will be returned to the caller. The current
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // line and column are determined and added into the final message.
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void SetErrorCode(const JsonParseError error, const wchar_t* error_pos);
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Pointer to the starting position in the input string.
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const wchar_t* start_pos_;
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Pointer to the current position in the input string.
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const wchar_t* json_pos_;
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Used to keep track of how many nested lists/dicts there are.
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int stack_depth_;
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // A parser flag that allows trailing commas in objects and arrays.
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool allow_trailing_comma_;
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Contains the error code for the last call to JsonToValue(), if any.
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  JsonParseError error_code_;
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int error_line_;
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int error_col_;
21572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
21672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DISALLOW_COPY_AND_ASSIGN(JSONReader);
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace base
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif  // BASE_JSON_JSON_READER_H_
222