Index: base/json_reader.cc |
diff --git a/base/json_reader.cc b/base/json_reader.cc |
index 2cea2393dfd277adfa61d55b98a0a09f08d83ad1..bf233a68004f9bb1951ae350434cb1ecca526ce4 100644 |
--- a/base/json_reader.cc |
+++ b/base/json_reader.cc |
@@ -89,25 +89,24 @@ const char* JSONReader::kUnquotedDictionaryKey = |
"Dictionary keys must be quoted."; |
/* static */ |
-bool JSONReader::Read(const std::string& json, |
- Value** root, |
- bool allow_trailing_comma) { |
- return ReadAndReturnError(json, root, allow_trailing_comma, NULL); |
+Value* JSONReader::Read(const std::string& json, |
+ bool allow_trailing_comma) { |
+ return ReadAndReturnError(json, allow_trailing_comma, NULL); |
} |
/* static */ |
-bool JSONReader::ReadAndReturnError(const std::string& json, |
- Value** root, |
- bool allow_trailing_comma, |
- std::string *error_message_out) { |
+Value* JSONReader::ReadAndReturnError(const std::string& json, |
+ bool allow_trailing_comma, |
+ std::string *error_message_out) { |
JSONReader reader = JSONReader(); |
- if (reader.JsonToValue(json, root, true, allow_trailing_comma)) { |
- return true; |
- } else { |
- if (error_message_out) |
- *error_message_out = reader.error_message(); |
- return false; |
- } |
+ Value* root = reader.JsonToValue(json, true, allow_trailing_comma); |
+ if (root) |
+ return root; |
+ |
+ if (error_message_out) |
+ *error_message_out = reader.error_message(); |
+ |
+ return NULL; |
} |
/* static */ |
@@ -121,12 +120,12 @@ JSONReader::JSONReader() |
: start_pos_(NULL), json_pos_(NULL), stack_depth_(0), |
allow_trailing_comma_(false) {} |
-bool JSONReader::JsonToValue(const std::string& json, Value** root, |
- bool check_root, bool allow_trailing_comma) { |
+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; |
- return false; |
+ return NULL; |
} |
// The conversion from UTF8 to wstring removes null bytes for us |
@@ -148,13 +147,10 @@ bool JSONReader::JsonToValue(const std::string& json, Value** root, |
stack_depth_ = 0; |
error_message_.clear(); |
- Value* temp_root = NULL; |
- |
- // Only modify root_ if we have valid JSON and nothing else. |
- if (BuildValue(&temp_root, check_root)) { |
+ scoped_ptr<Value> root(BuildValue(check_root)); |
+ if (root.get()) { |
if (ParseToken().type == Token::END_OF_INPUT) { |
- *root = temp_root; |
- return true; |
+ return root.release(); |
} else { |
SetErrorMessage(kUnexpectedDataAfterRoot, json_pos_); |
} |
@@ -164,16 +160,14 @@ bool JSONReader::JsonToValue(const std::string& json, Value** root, |
if (error_message_.empty()) |
SetErrorMessage(kSyntaxError, json_pos_); |
- if (temp_root) |
- delete temp_root; |
- return false; |
+ return NULL; |
} |
-bool JSONReader::BuildValue(Value** node, bool is_root) { |
+Value* JSONReader::BuildValue(bool is_root) { |
++stack_depth_; |
if (stack_depth_ > kStackLimit) { |
SetErrorMessage(kTooMuchNesting, json_pos_); |
- return false; |
+ return NULL; |
} |
Token token = ParseToken(); |
@@ -181,34 +175,38 @@ bool JSONReader::BuildValue(Value** node, bool is_root) { |
if (is_root && token.type != Token::OBJECT_BEGIN && |
token.type != Token::ARRAY_BEGIN) { |
SetErrorMessage(kBadRootElementType, json_pos_); |
- return false; |
+ return NULL; |
} |
+ scoped_ptr<Value> node; |
+ |
switch (token.type) { |
case Token::END_OF_INPUT: |
case Token::INVALID_TOKEN: |
- return false; |
+ return NULL; |
case Token::NULL_TOKEN: |
- *node = Value::CreateNullValue(); |
+ node.reset(Value::CreateNullValue()); |
break; |
case Token::BOOL_TRUE: |
- *node = Value::CreateBooleanValue(true); |
+ node.reset(Value::CreateBooleanValue(true)); |
break; |
case Token::BOOL_FALSE: |
- *node = Value::CreateBooleanValue(false); |
+ node.reset(Value::CreateBooleanValue(false)); |
break; |
case Token::NUMBER: |
- if (!DecodeNumber(token, node)) |
- return false; |
+ node.reset(DecodeNumber(token)); |
+ if (!node.get()) |
+ return NULL; |
break; |
case Token::STRING: |
- if (!DecodeString(token, node)) |
- return false; |
+ node.reset(DecodeString(token)); |
+ if (!node.get()) |
+ return NULL; |
break; |
case Token::ARRAY_BEGIN: |
@@ -216,14 +214,13 @@ bool JSONReader::BuildValue(Value** node, bool is_root) { |
json_pos_ += token.length; |
token = ParseToken(); |
- ListValue* array = new ListValue; |
+ node.reset(new ListValue()); |
while (token.type != Token::ARRAY_END) { |
- Value* array_node = NULL; |
- if (!BuildValue(&array_node, false)) { |
- delete array; |
- return false; |
+ Value* array_node = BuildValue(false); |
+ if (!array_node) { |
+ return NULL; |
} |
- array->Append(array_node); |
+ static_cast<ListValue*>(node.get())->Append(array_node); |
// After a list value, we expect a comma or the end of the list. |
token = ParseToken(); |
@@ -235,23 +232,19 @@ bool JSONReader::BuildValue(Value** node, bool is_root) { |
if (token.type == Token::ARRAY_END) { |
if (!allow_trailing_comma_) { |
SetErrorMessage(kTrailingComma, json_pos_); |
- delete array; |
- return false; |
+ return NULL; |
} |
// Trailing comma OK, stop parsing the Array. |
break; |
} |
} else if (token.type != Token::ARRAY_END) { |
// Unexpected value after list value. Bail out. |
- delete array; |
- return false; |
+ return NULL; |
} |
} |
if (token.type != Token::ARRAY_END) { |
- delete array; |
- return false; |
+ return NULL; |
} |
- *node = array; |
break; |
} |
@@ -260,39 +253,32 @@ bool JSONReader::BuildValue(Value** node, bool is_root) { |
json_pos_ += token.length; |
token = ParseToken(); |
- DictionaryValue* dict = new DictionaryValue; |
+ node.reset(new DictionaryValue); |
while (token.type != Token::OBJECT_END) { |
if (token.type != Token::STRING) { |
SetErrorMessage(kUnquotedDictionaryKey, json_pos_); |
- delete dict; |
- return false; |
- } |
- Value* dict_key_value = NULL; |
- if (!DecodeString(token, &dict_key_value)) { |
- delete dict; |
- return false; |
+ return NULL; |
} |
+ scoped_ptr<Value> dict_key_value(DecodeString(token)); |
+ if (!dict_key_value.get()) |
+ return NULL; |
+ |
// Convert the key into a wstring. |
std::wstring dict_key; |
bool success = dict_key_value->GetAsString(&dict_key); |
DCHECK(success); |
- delete dict_key_value; |
json_pos_ += token.length; |
token = ParseToken(); |
- if (token.type != Token::OBJECT_PAIR_SEPARATOR) { |
- delete dict; |
- return false; |
- } |
+ if (token.type != Token::OBJECT_PAIR_SEPARATOR) |
+ return NULL; |
json_pos_ += token.length; |
token = ParseToken(); |
- Value* dict_value = NULL; |
- if (!BuildValue(&dict_value, false)) { |
- delete dict; |
- return false; |
- } |
- dict->Set(dict_key, dict_value); |
+ Value* dict_value = BuildValue(false); |
+ if (!dict_value) |
+ return NULL; |
+ static_cast<DictionaryValue*>(node.get())->Set(dict_key, dict_value); |
// After a key/value pair, we expect a comma or the end of the |
// object. |
@@ -305,34 +291,30 @@ bool JSONReader::BuildValue(Value** node, bool is_root) { |
if (token.type == Token::OBJECT_END) { |
if (!allow_trailing_comma_) { |
SetErrorMessage(kTrailingComma, json_pos_); |
- delete dict; |
- return false; |
+ return NULL; |
} |
// Trailing comma OK, stop parsing the Object. |
break; |
} |
} else if (token.type != Token::OBJECT_END) { |
// Unexpected value after last object value. Bail out. |
- delete dict; |
- return false; |
+ return NULL; |
} |
} |
- if (token.type != Token::OBJECT_END) { |
- delete dict; |
- return false; |
- } |
- *node = dict; |
+ if (token.type != Token::OBJECT_END) |
+ return NULL; |
+ |
break; |
} |
default: |
// We got a token that's not a value. |
- return false; |
+ return NULL; |
} |
json_pos_ += token.length; |
--stack_depth_; |
- return true; |
+ return node.release(); |
} |
JSONReader::Token JSONReader::ParseNumberToken() { |
@@ -372,22 +354,18 @@ JSONReader::Token JSONReader::ParseNumberToken() { |
return token; |
} |
-bool JSONReader::DecodeNumber(const Token& token, Value** node) { |
+Value* JSONReader::DecodeNumber(const Token& token) { |
const std::wstring num_string(token.begin, token.length); |
int num_int; |
- if (StringToInt(num_string, &num_int)) { |
- *node = Value::CreateIntegerValue(num_int); |
- return true; |
- } |
+ if (StringToInt(num_string, &num_int)) |
+ return Value::CreateIntegerValue(num_int); |
double num_double; |
- if (StringToDouble(num_string, &num_double) && base::IsFinite(num_double)) { |
- *node = Value::CreateRealValue(num_double); |
- return true; |
- } |
+ if (StringToDouble(num_string, &num_double) && base::IsFinite(num_double)) |
+ return Value::CreateRealValue(num_double); |
- return false; |
+ return NULL; |
} |
JSONReader::Token JSONReader::ParseStringToken() { |
@@ -435,7 +413,7 @@ JSONReader::Token JSONReader::ParseStringToken() { |
return kInvalidToken; |
} |
-bool JSONReader::DecodeString(const Token& token, Value** node) { |
+Value* JSONReader::DecodeString(const Token& token) { |
std::wstring decoded_str; |
decoded_str.reserve(token.length - 2); |
@@ -486,16 +464,14 @@ bool JSONReader::DecodeString(const Token& token, Value** node) { |
// We should only have valid strings at this point. If not, |
// ParseStringToken didn't do it's job. |
NOTREACHED(); |
- return false; |
+ return NULL; |
} |
} else { |
// Not escaped |
decoded_str.push_back(c); |
} |
} |
- *node = Value::CreateStringValue(decoded_str); |
- |
- return true; |
+ return Value::CreateStringValue(decoded_str); |
} |
JSONReader::Token JSONReader::ParseToken() { |