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