| Index: base/json/json_reader.cc
|
| diff --git a/base/json/json_reader.cc b/base/json/json_reader.cc
|
| index bdc682b33e54a3af34cd32ec3a68ca4280afbe40..cf9ce02b84839908e1b94a7ce71e72cd8bfb4eab 100644
|
| --- a/base/json/json_reader.cc
|
| +++ b/base/json/json_reader.cc
|
| @@ -95,40 +95,79 @@ const char* JSONReader::kUnquotedDictionaryKey =
|
| /* static */
|
| Value* JSONReader::Read(const std::string& json,
|
| bool allow_trailing_comma) {
|
| - return ReadAndReturnError(json, allow_trailing_comma, NULL);
|
| + return ReadAndReturnError(json, allow_trailing_comma, NULL, NULL);
|
| }
|
|
|
| /* static */
|
| Value* JSONReader::ReadAndReturnError(const std::string& json,
|
| bool allow_trailing_comma,
|
| - std::string *error_message_out) {
|
| + int* error_code_out,
|
| + std::string* error_msg_out) {
|
| JSONReader reader = JSONReader();
|
| Value* root = reader.JsonToValue(json, true, allow_trailing_comma);
|
| if (root)
|
| return root;
|
|
|
| - if (error_message_out)
|
| - *error_message_out = reader.error_message();
|
| + if (error_code_out)
|
| + *error_code_out = reader.error_code();
|
| + if (error_msg_out)
|
| + *error_msg_out = reader.GetErrorMessage();
|
|
|
| return NULL;
|
| }
|
|
|
| /* static */
|
| std::string JSONReader::FormatErrorMessage(int line, int column,
|
| - const char* description) {
|
| - return StringPrintf("Line: %i, column: %i, %s",
|
| - line, column, description);
|
| + const std::string& description) {
|
| + if (line || column) {
|
| + return StringPrintf("Line: %i, column: %i, %s",
|
| + line, column, description.c_str());
|
| + }
|
| + return description;
|
| +}
|
| +
|
| +/* static */
|
| +std::string JSONReader::ErrorCodeToString(JsonParseError error_code) {
|
| + switch (error_code) {
|
| + case JSON_NO_ERROR:
|
| + return std::string();
|
| + case JSON_BAD_ROOT_ELEMENT_TYPE:
|
| + return kBadRootElementType;
|
| + case JSON_INVALID_ESCAPE:
|
| + return kInvalidEscape;
|
| + case JSON_SYNTAX_ERROR:
|
| + return kSyntaxError;
|
| + case JSON_TRAILING_COMMA:
|
| + return kTrailingComma;
|
| + case JSON_TOO_MUCH_NESTING:
|
| + return kTooMuchNesting;
|
| + case JSON_UNEXPECTED_DATA_AFTER_ROOT:
|
| + return kUnexpectedDataAfterRoot;
|
| + case JSON_UNSUPPORTED_ENCODING:
|
| + return kUnsupportedEncoding;
|
| + case JSON_UNQUOTED_DICTIONARY_KEY:
|
| + return kUnquotedDictionaryKey;
|
| + default:
|
| + NOTREACHED();
|
| + return std::string();
|
| + }
|
| +}
|
| +
|
| +std::string JSONReader::GetErrorMessage() const {
|
| + return FormatErrorMessage(error_line_, error_col_,
|
| + ErrorCodeToString(error_code_));
|
| }
|
|
|
| JSONReader::JSONReader()
|
| : start_pos_(NULL), json_pos_(NULL), stack_depth_(0),
|
| - allow_trailing_comma_(false) {}
|
| + allow_trailing_comma_(false),
|
| + error_code_(JSON_NO_ERROR), error_line_(0), error_col_(0) {}
|
|
|
| Value* JSONReader::JsonToValue(const std::string& json, bool check_root,
|
| bool allow_trailing_comma) {
|
| // The input must be in UTF-8.
|
| if (!IsStringUTF8(json.c_str())) {
|
| - error_message_ = kUnsupportedEncoding;
|
| + error_code_ = JSON_UNSUPPORTED_ENCODING;
|
| return NULL;
|
| }
|
|
|
| @@ -149,20 +188,20 @@ Value* JSONReader::JsonToValue(const std::string& json, bool check_root,
|
| json_pos_ = start_pos_;
|
| allow_trailing_comma_ = allow_trailing_comma;
|
| stack_depth_ = 0;
|
| - error_message_.clear();
|
| + error_code_ = JSON_NO_ERROR;
|
|
|
| scoped_ptr<Value> root(BuildValue(check_root));
|
| if (root.get()) {
|
| if (ParseToken().type == Token::END_OF_INPUT) {
|
| return root.release();
|
| } else {
|
| - SetErrorMessage(kUnexpectedDataAfterRoot, json_pos_);
|
| + SetErrorCode(JSON_UNEXPECTED_DATA_AFTER_ROOT, json_pos_);
|
| }
|
| }
|
|
|
| // Default to calling errors "syntax errors".
|
| - if (error_message_.empty())
|
| - SetErrorMessage(kSyntaxError, json_pos_);
|
| + if (error_code_ == 0)
|
| + SetErrorCode(JSON_SYNTAX_ERROR, json_pos_);
|
|
|
| return NULL;
|
| }
|
| @@ -170,7 +209,7 @@ Value* JSONReader::JsonToValue(const std::string& json, bool check_root,
|
| Value* JSONReader::BuildValue(bool is_root) {
|
| ++stack_depth_;
|
| if (stack_depth_ > kStackLimit) {
|
| - SetErrorMessage(kTooMuchNesting, json_pos_);
|
| + SetErrorCode(JSON_TOO_MUCH_NESTING, json_pos_);
|
| return NULL;
|
| }
|
|
|
| @@ -178,7 +217,7 @@ Value* JSONReader::BuildValue(bool is_root) {
|
| // The root token must be an array or an object.
|
| if (is_root && token.type != Token::OBJECT_BEGIN &&
|
| token.type != Token::ARRAY_BEGIN) {
|
| - SetErrorMessage(kBadRootElementType, json_pos_);
|
| + SetErrorCode(JSON_BAD_ROOT_ELEMENT_TYPE, json_pos_);
|
| return NULL;
|
| }
|
|
|
| @@ -234,7 +273,7 @@ Value* JSONReader::BuildValue(bool is_root) {
|
| // consumers need the parsing leniency, so handle accordingly.
|
| if (token.type == Token::ARRAY_END) {
|
| if (!allow_trailing_comma_) {
|
| - SetErrorMessage(kTrailingComma, json_pos_);
|
| + SetErrorCode(JSON_TRAILING_COMMA, json_pos_);
|
| return NULL;
|
| }
|
| // Trailing comma OK, stop parsing the Array.
|
| @@ -259,7 +298,7 @@ Value* JSONReader::BuildValue(bool is_root) {
|
| node.reset(new DictionaryValue);
|
| while (token.type != Token::OBJECT_END) {
|
| if (token.type != Token::STRING) {
|
| - SetErrorMessage(kUnquotedDictionaryKey, json_pos_);
|
| + SetErrorCode(JSON_UNQUOTED_DICTIONARY_KEY, json_pos_);
|
| return NULL;
|
| }
|
| scoped_ptr<Value> dict_key_value(DecodeString(token));
|
| @@ -294,7 +333,7 @@ Value* JSONReader::BuildValue(bool is_root) {
|
| // consumers need the parsing leniency, so handle accordingly.
|
| if (token.type == Token::OBJECT_END) {
|
| if (!allow_trailing_comma_) {
|
| - SetErrorMessage(kTrailingComma, json_pos_);
|
| + SetErrorCode(JSON_TRAILING_COMMA, json_pos_);
|
| return NULL;
|
| }
|
| // Trailing comma OK, stop parsing the Object.
|
| @@ -384,13 +423,13 @@ JSONReader::Token JSONReader::ParseStringToken() {
|
| switch (c) {
|
| case 'x':
|
| if (!ReadHexDigits(token, 2)) {
|
| - SetErrorMessage(kInvalidEscape, json_pos_ + token.length);
|
| + SetErrorCode(JSON_INVALID_ESCAPE, json_pos_ + token.length);
|
| return kInvalidToken;
|
| }
|
| break;
|
| case 'u':
|
| if (!ReadHexDigits(token, 4)) {
|
| - SetErrorMessage(kInvalidEscape, json_pos_ + token.length);
|
| + SetErrorCode(JSON_INVALID_ESCAPE, json_pos_ + token.length);
|
| return kInvalidToken;
|
| }
|
| break;
|
| @@ -405,7 +444,7 @@ JSONReader::Token JSONReader::ParseStringToken() {
|
| case '"':
|
| break;
|
| default:
|
| - SetErrorMessage(kInvalidEscape, json_pos_ + token.length);
|
| + SetErrorCode(JSON_INVALID_ESCAPE, json_pos_ + token.length);
|
| return kInvalidToken;
|
| }
|
| } else if ('"' == c) {
|
| @@ -617,8 +656,8 @@ bool JSONReader::EatComment() {
|
| return true;
|
| }
|
|
|
| -void JSONReader::SetErrorMessage(const char* description,
|
| - const wchar_t* error_pos) {
|
| +void JSONReader::SetErrorCode(JsonParseError error,
|
| + const wchar_t* error_pos) {
|
| int line_number = 1;
|
| int column_number = 1;
|
|
|
| @@ -637,7 +676,9 @@ void JSONReader::SetErrorMessage(const char* description,
|
| }
|
| }
|
|
|
| - error_message_ = FormatErrorMessage(line_number, column_number, description);
|
| + error_line_ = line_number;
|
| + error_col_ = column_number;
|
| + error_code_ = error;
|
| }
|
|
|
| } // namespace base
|
|
|