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..b2b868735e07adc091869d4b87966976ae434b27 100644 |
--- a/third_party/libaddressinput/chromium/json.cc |
+++ b/third_party/libaddressinput/chromium/json.cc |
@@ -2,121 +2,172 @@ |
// 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" |
+#include "third_party/libaddressinput/src/cpp/src/util/json.h" |
+ |
+#include <map> |
+#include <utility> |
#include "base/basictypes.h" |
#include "base/json/json_reader.h" |
#include "base/logging.h" |
#include "base/memory/scoped_ptr.h" |
+#include "base/stl_util.h" |
#include "base/values.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() {} |
+ // ::scoped_ptr is from "base/memory/scoped_ptr.h", which does not interfere |
+ // with ::i18n::addressinput::scoped_ptr from |
+ // <libaddressinput/util/scoped_ptr.h> |
Evan Stade
2014/07/07 21:59:08
remove this comment
please use gerrit instead
2014/07/08 22:47:59
Done.
|
+ 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) |
Evan Stade
2014/07/07 21:59:08
why not a const ref?
please use gerrit instead
2014/07/08 22:47:59
Done.
|
+ : 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; |
Evan Stade
2014/07/07 21:59:08
this whole function can be distilled down to:
if
please use gerrit instead
2014/07/08 22:47:59
This function is no longer necessary after moving
|
+ // 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_; |
Evan Stade
2014/07/07 21:59:07
why not a const ref?
please use gerrit instead
2014/07/08 22:47:59
Done.
|
-// 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<const base::Value> parsed(base::JSONReader::Read(json.c_str())); |
+ if (parsed && parsed->IsType(base::Value::TYPE_DICTIONARY)) { |
+ ::scoped_ptr<const base::DictionaryValue> dict( |
+ static_cast<const base::DictionaryValue*>(parsed.release())); |
+ impl_.reset(new JsonImpl(dict.Pass())); |
+ } |
-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); |
Evan Stade
2014/07/07 21:59:08
ditto
please use gerrit instead
2014/07/08 22:47:59
Done.
|
+ // 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_. |
Evan Stade
2014/07/07 21:59:08
I think it would be a bit less confusing if all th
please use gerrit instead
2014/07/08 22:47:59
Done.
|
+ 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); |
Evan Stade
2014/07/07 21:59:08
ditto
please use gerrit instead
2014/07/08 22:47:59
Done.
|
+ // 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 |