Chromium Code Reviews| Index: third_party/libaddressinput/chromium/json.cc |
| diff --git a/third_party/libaddressinput/chromium/json.cc b/third_party/libaddressinput/chromium/json.cc |
| index 5437e1e55056ef4d2eec6158e54acf85c9f536ea..e2c8f9ac33fcbb1a1d03bcc1600b81ebaec409d5 100644 |
| --- a/third_party/libaddressinput/chromium/json.cc |
| +++ b/third_party/libaddressinput/chromium/json.cc |
| @@ -2,121 +2,173 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| -#include "cpp/src/util/json.h" |
| +// Use "base/memory/scoped_ptr.h" instead. |
|
please use gerrit instead
2014/06/05 22:22:48
Investigate: No longer necessary do this, is it?
please use gerrit instead
2014/06/09 23:28:17
Done.
|
| +#define I18N_ADDRESSINPUT_UTIL_SCOPED_PTR_H_ |
| + |
| +#include <map> |
| +#include <utility> |
| #include "base/basictypes.h" |
| #include "base/json/json_reader.h" |
| #include "base/logging.h" |
| +// Must be before json.h to be used in the Json class. |
|
please use gerrit instead
2014/06/05 22:22:48
Remove this comment.
please use gerrit instead
2014/06/09 23:28:17
Done.
|
| #include "base/memory/scoped_ptr.h" |
| +#include "base/stl_util.h" |
| #include "base/values.h" |
| +#include "third_party/libaddressinput/src/cpp/src/util/json.h" |
| namespace i18n { |
| namespace addressinput { |
| -namespace { |
| - |
| -// A base class for Chrome Json objects. JSON gets parsed into a |
| -// base::DictionaryValue and data is accessed via the Json interface. |
| -class ChromeJson : public Json { |
| +class Json::JsonImpl { |
| public: |
| - virtual bool GetStringValueForKey(const std::string& key, std::string* value) |
| - const OVERRIDE; |
| - virtual bool GetJsonValueForKey(const std::string& key, |
| - scoped_ptr<Json>* value) const OVERRIDE; |
| - protected: |
| - ChromeJson() {} |
| - virtual ~ChromeJson() {} |
| + explicit JsonImpl(scoped_ptr<const base::DictionaryValue> to_take_ownership) |
| + : owned_(to_take_ownership.Pass()), not_owned_(owned_.get()) { |
| + DCHECK(not_owned_); |
| + InitKeys(); |
| + } |
| - virtual const base::DictionaryValue* GetDict() const = 0; |
| + explicit JsonImpl(const base::DictionaryValue* do_not_take_ownership) |
| + : not_owned_(do_not_take_ownership) { |
| + DCHECK(not_owned_); |
| + InitKeys(); |
| + } |
| - DISALLOW_COPY_AND_ASSIGN(ChromeJson); |
| -}; |
| + ~JsonImpl() { |
| + STLDeleteValues(&dictionaries_); |
| + } |
| -// A Json object that will parse a string and own the parsed data. |
| -class JsonDataOwner : public ChromeJson { |
| - public: |
| - JsonDataOwner() {} |
| - virtual ~JsonDataOwner() {} |
| + const std::vector<std::string>& GetKeys() const { |
| + return keys_; |
| + } |
| - virtual bool ParseObject(const std::string& json) OVERRIDE { |
| - dict_.reset(); |
| + bool GetStringValueForKey(const std::string& key, std::string* value) const { |
| + return not_owned_->GetStringWithoutPathExpansion(key, value); |
| + } |
| - // |json| is converted to a |c_str()| here because rapidjson and other parts |
| - // of the standalone library use char* rather than std::string. |
| - scoped_ptr<base::Value> parsed(base::JSONReader::Read(json.c_str())); |
| - if (parsed && parsed->IsType(base::Value::TYPE_DICTIONARY)) |
| - dict_.reset(static_cast<base::DictionaryValue*>(parsed.release())); |
| + bool GetDictionaryValueForKey(const std::string& key, |
| + const base::DictionaryValue** value) const { |
| + return not_owned_->GetDictionaryWithoutPathExpansion(key, value); |
| + } |
| - return !!dict_; |
| + // The caller does not own the result. The result can be NULL if there's no |
| + // dictionary for |key|. |
| + const Json* FindDictionary(const std::string& key) const { |
| + std::map<std::string, const Json*>::const_iterator it = |
| + dictionaries_.find(key); |
| + return it != dictionaries_.end() ? it->second : NULL; |
| } |
| - protected: |
| - virtual const base::DictionaryValue* GetDict() const OVERRIDE { |
| - return dict_.get(); |
| + // Takes ownership of |dictionary|. Should be called only once per |key| and |
| + // per |dictionary|. |
| + void AddDictionary(const std::string& key, const Json* dictionary) { |
| + bool inserted = |
| + dictionaries_.insert(std::make_pair(key, dictionary)).second; |
| + // Cannot do work inside of DCHECK(), because the compiler can optimize it |
| + // away. |
| + DCHECK(inserted); |
| + // Avoid unused variable warning when DCHECK() is optimized away. |
| + (void)inserted; |
| } |
| private: |
| - scoped_ptr<base::DictionaryValue> dict_; |
| + void InitKeys() { |
| + DCHECK(keys_.empty()); |
| + for (base::DictionaryValue::Iterator it(*not_owned_); !it.IsAtEnd(); |
| + it.Advance()) { |
| + keys_.push_back(it.key()); |
| + } |
| + } |
| - DISALLOW_COPY_AND_ASSIGN(JsonDataOwner); |
| -}; |
| + const scoped_ptr<const base::DictionaryValue> owned_; |
| + const base::DictionaryValue* const not_owned_; |
| -// A Json object which will point to data that's been parsed by a different |
| -// ChromeJson. It does not own its data and is only valid as long as its parent |
| -// ChromeJson is valid. |
| -class JsonDataCopy : public ChromeJson { |
| - public: |
| - explicit JsonDataCopy(const base::DictionaryValue* dict) : |
| - dict_(dict) {} |
| - virtual ~JsonDataCopy() {} |
| + // Owned JSON objects. |
| + std::map<std::string, const Json*> dictionaries_; |
| - virtual bool ParseObject(const std::string& json) OVERRIDE { |
| - NOTREACHED(); |
| - return false; |
| - } |
| + std::vector<std::string> keys_; |
| - protected: |
| - virtual const base::DictionaryValue* GetDict() const OVERRIDE { |
| - return dict_; |
| - } |
| + DISALLOW_COPY_AND_ASSIGN(JsonImpl); |
| +}; |
| - private: |
| - const base::DictionaryValue* dict_; // weak reference. |
| +Json::Json() {} |
| - DISALLOW_COPY_AND_ASSIGN(JsonDataCopy); |
| -}; |
| +Json::~Json() {} |
| + |
| +bool Json::ParseObject(const std::string& json) { |
| + DCHECK(!impl_); |
| -// ChromeJson ------------------------------------------------------------------ |
| + // |json| is converted to a |c_str()| here because rapidjson and other parts |
| + // of the standalone library use char* rather than std::string. |
| + scoped_ptr<base::Value> parsed(base::JSONReader::Read(json.c_str())); |
| + if (parsed && parsed->IsType(base::Value::TYPE_DICTIONARY)) { |
| + impl_.reset( |
| + new JsonImpl(static_cast<base::DictionaryValue*>(parsed.release()))); |
| + } |
| -bool ChromeJson::GetStringValueForKey(const std::string& key, |
| - std::string* value) const { |
| - return GetDict()->GetStringWithoutPathExpansion(key, value); |
| + return !!impl_; |
| } |
| -bool ChromeJson::GetJsonValueForKey(const std::string& key, |
| - scoped_ptr<Json>* value) const { |
| - const base::DictionaryValue* sub_dict = NULL; |
| - if (!GetDict()->GetDictionaryWithoutPathExpansion(key, &sub_dict) || |
| - !sub_dict) { |
| - return false; |
| - } |
| +const std::vector<std::string>& Json::GetKeys() const { |
| + DCHECK(impl_); |
| + return impl_->GetKeys(); |
| +} |
| - if (value) |
| - value->reset(new JsonDataCopy(sub_dict)); |
| +bool Json::HasStringValueForKey(const std::string& key) const { |
| + DCHECK(impl_); |
| + std::string not_used; |
| + return impl_->GetStringValueForKey(key, ¬_used); |
| +} |
| - return true; |
| +std::string Json::GetStringValueForKey(const std::string& key) const { |
| + DCHECK(impl_); |
| + std::string value; |
| + bool found = impl_->GetStringValueForKey(key, &value); |
| + // Do not work inside of a DCHECK(), because it can be optimized away. |
| + DCHECK(found); |
| + // Avoid a compiler warning about unused variable when DCHECK() is optimized |
| + // away. |
| + (void)found; |
| + return value; |
| } |
| -} // namespace |
| +bool Json::HasDictionaryValueForKey(const std::string& key) const { |
| + DCHECK(impl_); |
| -Json::~Json() {} |
| + // The value returned by FindDictionary() is owned by impl_. |
| + if (impl_->FindDictionary(key)) |
| + return true; |
| -// static |
| -scoped_ptr<Json> Json::Build() { |
| - return scoped_ptr<Json>(new JsonDataOwner); |
| + // Value is owned by impl_. |
| + const base::DictionaryValue* value = NULL; |
| + return impl_->GetDictionaryValueForKey(key, &value) && value; |
| } |
| -Json::Json() {} |
| +const Json& Json::GetDictionaryValueForKey(const std::string& key) const { |
| + DCHECK(impl_); |
| + |
| + // The value returned by FindDictionary() is owned by impl_. |
| + const Json* existing_dictionary = impl_->FindDictionary(key); |
| + if (existing_dictionary) |
| + return *existing_dictionary; |
| + |
| + // Value is owned by impl_. |
| + const base::DictionaryValue* value = NULL; |
| + bool found = impl_->GetDictionaryValueForKey(key, &value); |
| + // Cannot do work inside of DCHECK(), because it can be optimized by the |
| + // compiler. |
| + DCHECK(found); |
| + // Avoid a compiler warning about an unused variable when the DCHECK() is |
| + // optimized away. |
| + (void)found; |
| + DCHECK(value); |
| + |
| + // Dictionary is owned by impl_. |
| + Json* dictionary = new Json; |
| + dictionary->impl_.reset(new JsonImpl(value)); |
| + impl_->AddDictionary(key, dictionary); |
| + return *dictionary; |
| +} |
| } // namespace addressinput |
| } // namespace i18n |