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 |