summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authorpkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-25 20:47:52 +0000
committerpkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-25 20:47:52 +0000
commit4dad9ad838f6671fbd67e1c5292525e739e31983 (patch)
tree4d79fc17f12752cc221e0e40d16951677da71f92 /base
parent2b3f0f59a6761a41e22007c2c3096e8e18517e08 (diff)
downloadchromium_src-4dad9ad838f6671fbd67e1c5292525e739e31983.zip
chromium_src-4dad9ad838f6671fbd67e1c5292525e739e31983.tar.gz
chromium_src-4dad9ad838f6671fbd67e1c5292525e739e31983.tar.bz2
Many changes to DictionaryValues:
* Add support for keys with "." in them via new XXXWithoutPathExpansion() APIs. * Use these APIs with all key iterator usage. * SetXXX() calls cannot fail, so change them from bool to void. * Change GetSize() to size() since it's cheap, and add empty(). Other: * Use standard for loop format in more places (e.g. instead of while loops when they're really doing a for loop). * Shorten a few bits of code. BUG=567 TEST=none Review URL: http://codereview.chromium.org/441008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@33109 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r--base/json/json_reader.cc3
-rw-r--r--base/json/json_reader_unittest.cc59
-rw-r--r--base/json/json_writer.cc2
-rw-r--r--base/json/json_writer_unittest.cc19
-rw-r--r--base/values.cc229
-rw-r--r--base/values.h53
-rw-r--r--base/values_unittest.cc26
7 files changed, 269 insertions, 122 deletions
diff --git a/base/json/json_reader.cc b/base/json/json_reader.cc
index 06d790c..bdc682b 100644
--- a/base/json/json_reader.cc
+++ b/base/json/json_reader.cc
@@ -281,7 +281,8 @@ Value* JSONReader::BuildValue(bool is_root) {
Value* dict_value = BuildValue(false);
if (!dict_value)
return NULL;
- static_cast<DictionaryValue*>(node.get())->Set(dict_key, dict_value);
+ static_cast<DictionaryValue*>(node.get())->SetWithoutPathExpansion(
+ dict_key, dict_value);
// After a key/value pair, we expect a comma or the end of the
// object.
diff --git a/base/json/json_reader_unittest.cc b/base/json/json_reader_unittest.cc
index 8ae51c5..17dea56 100644
--- a/base/json/json_reader_unittest.cc
+++ b/base/json/json_reader_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -297,8 +297,7 @@ TEST(JSONReaderTest, Reading) {
ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
root.reset(JSONReader::Read(
- "{\"number\":9.87654321, \"null\":null , \"\\x53\" : \"str\" }",
- false));
+ "{\"number\":9.87654321, \"null\":null , \"\\x53\" : \"str\" }", false));
ASSERT_TRUE(root.get());
ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
DictionaryValue* dict_val = static_cast<DictionaryValue*>(root.get());
@@ -313,32 +312,32 @@ TEST(JSONReaderTest, Reading) {
ASSERT_EQ(L"str", str_val);
root2.reset(JSONReader::Read(
- "{\"number\":9.87654321, \"null\":null , \"\\x53\" : \"str\", }", true));
+ "{\"number\":9.87654321, \"null\":null , \"\\x53\" : \"str\", }", true));
ASSERT_TRUE(root2.get());
EXPECT_TRUE(root->Equals(root2.get()));
// Test newline equivalence.
root2.reset(JSONReader::Read(
- "{\n"
- " \"number\":9.87654321,\n"
- " \"null\":null,\n"
- " \"\\x53\":\"str\",\n"
- "}\n", true));
+ "{\n"
+ " \"number\":9.87654321,\n"
+ " \"null\":null,\n"
+ " \"\\x53\":\"str\",\n"
+ "}\n", true));
ASSERT_TRUE(root2.get());
EXPECT_TRUE(root->Equals(root2.get()));
root2.reset(JSONReader::Read(
- "{\r\n"
- " \"number\":9.87654321,\r\n"
- " \"null\":null,\r\n"
- " \"\\x53\":\"str\",\r\n"
- "}\r\n", true));
+ "{\r\n"
+ " \"number\":9.87654321,\r\n"
+ " \"null\":null,\r\n"
+ " \"\\x53\":\"str\",\r\n"
+ "}\r\n", true));
ASSERT_TRUE(root2.get());
EXPECT_TRUE(root->Equals(root2.get()));
// Test nesting
root.reset(JSONReader::Read(
- "{\"inner\":{\"array\":[true]},\"false\":false,\"d\":{}}", false));
+ "{\"inner\":{\"array\":[true]},\"false\":false,\"d\":{}}", false));
ASSERT_TRUE(root.get());
ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
dict_val = static_cast<DictionaryValue*>(root.get());
@@ -354,9 +353,37 @@ TEST(JSONReaderTest, Reading) {
ASSERT_TRUE(dict_val->GetDictionary(L"d", &inner_dict));
root2.reset(JSONReader::Read(
- "{\"inner\": {\"array\":[true] , },\"false\":false,\"d\":{},}", true));
+ "{\"inner\": {\"array\":[true] , },\"false\":false,\"d\":{},}", true));
EXPECT_TRUE(root->Equals(root2.get()));
+ // Test keys with periods
+ root.reset(JSONReader::Read(
+ "{\"a.b\":3,\"c\":2,\"d.e.f\":{\"g.h.i.j\":1}}", false));
+ ASSERT_TRUE(root.get());
+ ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
+ dict_val = static_cast<DictionaryValue*>(root.get());
+ int integer_value = 0;
+ EXPECT_TRUE(dict_val->GetIntegerWithoutPathExpansion(L"a.b", &integer_value));
+ EXPECT_EQ(3, integer_value);
+ EXPECT_TRUE(dict_val->GetIntegerWithoutPathExpansion(L"c", &integer_value));
+ EXPECT_EQ(2, integer_value);
+ inner_dict = NULL;
+ ASSERT_TRUE(dict_val->GetDictionaryWithoutPathExpansion(L"d.e.f",
+ &inner_dict));
+ ASSERT_EQ(1U, inner_dict->size());
+ EXPECT_TRUE(inner_dict->GetIntegerWithoutPathExpansion(L"g.h.i.j",
+ &integer_value));
+ EXPECT_EQ(1, integer_value);
+
+ root.reset(JSONReader::Read("{\"a\":{\"b\":2},\"a.b\":1}", false));
+ ASSERT_TRUE(root.get());
+ ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
+ dict_val = static_cast<DictionaryValue*>(root.get());
+ EXPECT_TRUE(dict_val->GetInteger(L"a.b", &integer_value));
+ EXPECT_EQ(2, integer_value);
+ EXPECT_TRUE(dict_val->GetIntegerWithoutPathExpansion(L"a.b", &integer_value));
+ EXPECT_EQ(1, integer_value);
+
// Invalid, no closing brace
root.reset(JSONReader::Read("{\"a\": true", false));
ASSERT_FALSE(root.get());
diff --git a/base/json/json_writer.cc b/base/json/json_writer.cc
index 133b625..ffdad76 100644
--- a/base/json/json_writer.cc
+++ b/base/json/json_writer.cc
@@ -157,7 +157,7 @@ void JSONWriter::BuildJSONString(const Value* const node,
}
Value* value = NULL;
- bool result = dict->Get(*key_itr, &value);
+ bool result = dict->GetWithoutPathExpansion(*key_itr, &value);
DCHECK(result);
if (pretty_print_)
diff --git a/base/json/json_writer_unittest.cc b/base/json/json_writer_unittest.cc
index cd2a6fe..e7d0f05 100644
--- a/base/json/json_writer_unittest.cc
+++ b/base/json/json_writer_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -76,6 +76,23 @@ TEST(JSONWriterTest, Writing) {
"}" JSON_NEWLINE,
output_js);
#undef JSON_NEWLINE
+
+ // Test keys with periods
+ DictionaryValue period_dict;
+ period_dict.SetWithoutPathExpansion(L"a.b", Value::CreateIntegerValue(3));
+ period_dict.SetWithoutPathExpansion(L"c", Value::CreateIntegerValue(2));
+ DictionaryValue* period_dict2 = new DictionaryValue;
+ period_dict2->SetWithoutPathExpansion(L"g.h.i.j",
+ Value::CreateIntegerValue(1));
+ period_dict.SetWithoutPathExpansion(L"d.e.f", period_dict2);
+ JSONWriter::Write(&period_dict, false, &output_js);
+ ASSERT_EQ("{\"a.b\":3,\"c\":2,\"d.e.f\":{\"g.h.i.j\":1}}", output_js);
+
+ DictionaryValue period_dict3;
+ period_dict3.Set(L"a.b", Value::CreateIntegerValue(2));
+ period_dict3.SetWithoutPathExpansion(L"a.b", Value::CreateIntegerValue(1));
+ JSONWriter::Write(&period_dict3, false, &output_js);
+ ASSERT_EQ("{\"a\":{\"b\":2},\"a.b\":1}", output_js);
}
} // namespace base
diff --git a/base/values.cc b/base/values.cc
index 305f1cb..f66b5968 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -253,92 +253,79 @@ bool DictionaryValue::HasKey(const std::wstring& key) const {
return current_entry != dictionary_.end();
}
-void DictionaryValue::SetInCurrentNode(const std::wstring& key,
- Value* in_value) {
- // If there's an existing value here, we need to delete it, because
- // we own all our children.
- if (HasKey(key)) {
- DCHECK(dictionary_[key] != in_value); // This would be bogus
- delete dictionary_[key];
- }
-
- dictionary_[key] = in_value;
-}
-
-bool DictionaryValue::Set(const std::wstring& path, Value* in_value) {
+void DictionaryValue::Set(const std::wstring& path, Value* in_value) {
DCHECK(in_value);
- std::wstring key = path;
-
- size_t delimiter_position = path.find_first_of(L".", 0);
- // If there isn't a dictionary delimiter in the path, we're done.
- if (delimiter_position == std::wstring::npos) {
- SetInCurrentNode(key, in_value);
- return true;
- } else {
- key = path.substr(0, delimiter_position);
- }
+ std::wstring current_path(path);
+ DictionaryValue* current_dictionary = this;
+ for (size_t delimiter_position = current_path.find('.');
+ delimiter_position != std::wstring::npos;
+ delimiter_position = current_path.find('.')) {
+ // Assume that we're indexing into a dictionary.
+ std::wstring key(current_path, 0, delimiter_position);
+ DictionaryValue* child_dictionary;
+ if (!current_dictionary->GetDictionary(key, &child_dictionary)) {
+ child_dictionary = new DictionaryValue;
+ current_dictionary->SetWithoutPathExpansion(key, child_dictionary);
+ }
- // Assume that we're indexing into a dictionary.
- DictionaryValue* entry = NULL;
- if (!HasKey(key) || (dictionary_[key]->GetType() != TYPE_DICTIONARY)) {
- entry = new DictionaryValue;
- SetInCurrentNode(key, entry);
- } else {
- entry = static_cast<DictionaryValue*>(dictionary_[key]);
+ current_dictionary = child_dictionary;
+ current_path.erase(0, delimiter_position + 1);
}
- std::wstring remaining_path = path.substr(delimiter_position + 1);
- return entry->Set(remaining_path, in_value);
+ current_dictionary->SetWithoutPathExpansion(current_path, in_value);
}
-bool DictionaryValue::SetBoolean(const std::wstring& path, bool in_value) {
- return Set(path, CreateBooleanValue(in_value));
+void DictionaryValue::SetBoolean(const std::wstring& path, bool in_value) {
+ Set(path, CreateBooleanValue(in_value));
}
-bool DictionaryValue::SetInteger(const std::wstring& path, int in_value) {
- return Set(path, CreateIntegerValue(in_value));
+void DictionaryValue::SetInteger(const std::wstring& path, int in_value) {
+ Set(path, CreateIntegerValue(in_value));
}
-bool DictionaryValue::SetReal(const std::wstring& path, double in_value) {
- return Set(path, CreateRealValue(in_value));
+void DictionaryValue::SetReal(const std::wstring& path, double in_value) {
+ Set(path, CreateRealValue(in_value));
}
-bool DictionaryValue::SetString(const std::wstring& path,
+void DictionaryValue::SetString(const std::wstring& path,
const std::string& in_value) {
- return Set(path, CreateStringValue(in_value));
+ Set(path, CreateStringValue(in_value));
}
-bool DictionaryValue::SetString(const std::wstring& path,
+void DictionaryValue::SetString(const std::wstring& path,
const std::wstring& in_value) {
- return Set(path, CreateStringValue(in_value));
+ Set(path, CreateStringValue(in_value));
}
-bool DictionaryValue::Get(const std::wstring& path, Value** out_value) const {
- std::wstring key = path;
-
- size_t delimiter_position = path.find_first_of(L".", 0);
- if (delimiter_position != std::wstring::npos) {
- key = path.substr(0, delimiter_position);
+void DictionaryValue::SetWithoutPathExpansion(const std::wstring& key,
+ Value* in_value) {
+ // If there's an existing value here, we need to delete it, because
+ // we own all our children.
+ if (HasKey(key)) {
+ DCHECK(dictionary_[key] != in_value); // This would be bogus
+ delete dictionary_[key];
}
- ValueMap::const_iterator entry_iterator = dictionary_.find(key);
- if (entry_iterator == dictionary_.end())
- return false;
- Value* entry = entry_iterator->second;
+ dictionary_[key] = in_value;
+}
- if (delimiter_position == std::wstring::npos) {
- if (out_value)
- *out_value = entry;
- return true;
- }
+bool DictionaryValue::Get(const std::wstring& path, Value** out_value) const {
+ std::wstring current_path(path);
+ const DictionaryValue* current_dictionary = this;
+ for (size_t delimiter_position = current_path.find('.');
+ delimiter_position != std::wstring::npos;
+ delimiter_position = current_path.find('.')) {
+ DictionaryValue* child_dictionary;
+ if (!current_dictionary->GetDictionary(
+ current_path.substr(0, delimiter_position), &child_dictionary))
+ return false;
- if (entry->IsType(TYPE_DICTIONARY)) {
- DictionaryValue* dictionary = static_cast<DictionaryValue*>(entry);
- return dictionary->Get(path.substr(delimiter_position + 1), out_value);
+ current_dictionary = child_dictionary;
+ current_path.erase(0, delimiter_position + 1);
}
- return false;
+ return current_dictionary->GetWithoutPathExpansion(current_path, out_value);
}
bool DictionaryValue::GetBoolean(const std::wstring& path,
@@ -425,44 +412,111 @@ bool DictionaryValue::GetList(const std::wstring& path,
return true;
}
-bool DictionaryValue::Remove(const std::wstring& path, Value** out_value) {
- std::wstring key = path;
-
- size_t delimiter_position = path.find_first_of(L".", 0);
- if (delimiter_position != std::wstring::npos) {
- key = path.substr(0, delimiter_position);
- }
-
- ValueMap::iterator entry_iterator = dictionary_.find(key);
+bool DictionaryValue::GetWithoutPathExpansion(const std::wstring& key,
+ Value** out_value) const {
+ ValueMap::const_iterator entry_iterator = dictionary_.find(key);
if (entry_iterator == dictionary_.end())
return false;
+
Value* entry = entry_iterator->second;
+ if (out_value)
+ *out_value = entry;
+ return true;
+}
- if (delimiter_position == std::wstring::npos) {
- if (out_value)
- *out_value = entry;
- else
- delete entry;
+bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::wstring& path,
+ int* out_value) const {
+ Value* value;
+ if (!GetWithoutPathExpansion(path, &value))
+ return false;
- dictionary_.erase(entry_iterator);
- return true;
- }
+ return value->GetAsInteger(out_value);
+}
+
+bool DictionaryValue::GetStringWithoutPathExpansion(
+ const std::wstring& path,
+ std::string* out_value) const {
+ Value* value;
+ if (!GetWithoutPathExpansion(path, &value))
+ return false;
+
+ return value->GetAsString(out_value);
+}
+
+bool DictionaryValue::GetStringWithoutPathExpansion(
+ const std::wstring& path,
+ std::wstring* out_value) const {
+ Value* value;
+ if (!GetWithoutPathExpansion(path, &value))
+ return false;
+
+ return value->GetAsString(out_value);
+}
+
+bool DictionaryValue::GetDictionaryWithoutPathExpansion(
+ const std::wstring& path,
+ DictionaryValue** out_value) const {
+ Value* value;
+ bool result = GetWithoutPathExpansion(path, &value);
+ if (!result || !value->IsType(TYPE_DICTIONARY))
+ return false;
+
+ if (out_value)
+ *out_value = static_cast<DictionaryValue*>(value);
+
+ return true;
+}
- if (entry->IsType(TYPE_DICTIONARY)) {
- DictionaryValue* dictionary = static_cast<DictionaryValue*>(entry);
- return dictionary->Remove(path.substr(delimiter_position + 1), out_value);
+bool DictionaryValue::GetListWithoutPathExpansion(const std::wstring& path,
+ ListValue** out_value) const {
+ Value* value;
+ bool result = GetWithoutPathExpansion(path, &value);
+ if (!result || !value->IsType(TYPE_LIST))
+ return false;
+
+ if (out_value)
+ *out_value = static_cast<ListValue*>(value);
+
+ return true;
+}
+
+bool DictionaryValue::Remove(const std::wstring& path, Value** out_value) {
+ std::wstring current_path(path);
+ DictionaryValue* current_dictionary = this;
+ size_t delimiter_position = current_path.rfind('.');
+ if (delimiter_position != std::wstring::npos) {
+ if (!GetDictionary(current_path.substr(0, delimiter_position),
+ &current_dictionary))
+ return false;
+ current_path.erase(0, delimiter_position + 1);
}
- return false;
+ return current_dictionary->RemoveWithoutPathExpansion(current_path,
+ out_value);
+}
+
+bool DictionaryValue::RemoveWithoutPathExpansion(const std::wstring& key,
+ Value** out_value) {
+ ValueMap::iterator entry_iterator = dictionary_.find(key);
+ if (entry_iterator == dictionary_.end())
+ return false;
+
+ Value* entry = entry_iterator->second;
+ if (out_value)
+ *out_value = entry;
+ else
+ delete entry;
+ dictionary_.erase(entry_iterator);
+ return true;
}
Value* DictionaryValue::DeepCopy() const {
DictionaryValue* result = new DictionaryValue;
- ValueMap::const_iterator current_entry = dictionary_.begin();
- while (current_entry != dictionary_.end()) {
- result->Set(current_entry->first, current_entry->second->DeepCopy());
- ++current_entry;
+ for (ValueMap::const_iterator current_entry(dictionary_.begin());
+ current_entry != dictionary_.end(); ++current_entry) {
+ result->SetWithoutPathExpansion(current_entry->first,
+ current_entry->second->DeepCopy());
}
return result;
@@ -479,7 +533,8 @@ bool DictionaryValue::Equals(const Value* other) const {
while (lhs_it != end_keys() && rhs_it != other_dict->end_keys()) {
Value* lhs;
Value* rhs;
- if (!Get(*lhs_it, &lhs) || !other_dict->Get(*rhs_it, &rhs) ||
+ if (!GetWithoutPathExpansion(*lhs_it, &lhs) ||
+ !other_dict->GetWithoutPathExpansion(*rhs_it, &rhs) ||
!lhs->Equals(rhs)) {
return false;
}
diff --git a/base/values.h b/base/values.h
index b3c380c..49ce287 100644
--- a/base/values.h
+++ b/base/values.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -207,7 +207,10 @@ class DictionaryValue : public Value {
bool HasKey(const std::wstring& key) const;
// Returns the number of Values in this dictionary.
- size_t GetSize() const { return dictionary_.size(); }
+ size_t size() const { return dictionary_.size(); }
+
+ // Returns whether the dictionary is empty.
+ bool empty() const { return dictionary_.empty(); }
// Clears any current contents of this dictionary.
void Clear();
@@ -220,16 +223,20 @@ class DictionaryValue : public Value {
// a DictionaryValue, a new DictionaryValue will be created and attached
// to the path in that location.
// Note that the dictionary takes ownership of the value referenced by
- // |in_value|.
- bool Set(const std::wstring& path, Value* in_value);
+ // |in_value|, and therefore |in_value| must be non-NULL.
+ void Set(const std::wstring& path, Value* in_value);
// Convenience forms of Set(). These methods will replace any existing
// value at that path, even if it has a different type.
- bool SetBoolean(const std::wstring& path, bool in_value);
- bool SetInteger(const std::wstring& path, int in_value);
- bool SetReal(const std::wstring& path, double in_value);
- bool SetString(const std::wstring& path, const std::string& in_value);
- bool SetString(const std::wstring& path, const std::wstring& in_value);
+ void SetBoolean(const std::wstring& path, bool in_value);
+ void SetInteger(const std::wstring& path, int in_value);
+ void SetReal(const std::wstring& path, double in_value);
+ void SetString(const std::wstring& path, const std::string& in_value);
+ void SetString(const std::wstring& path, const std::wstring& in_value);
+
+ // Like Set(), but without special treatment of '.'. This allows e.g. URLs to
+ // be used as paths.
+ void SetWithoutPathExpansion(const std::wstring& key, Value* in_value);
// Gets the Value associated with the given path starting from this object.
// A path has the form "<key>" or "<key>.<key>.[...]", where "." indexes
@@ -253,6 +260,21 @@ class DictionaryValue : public Value {
DictionaryValue** out_value) const;
bool GetList(const std::wstring& path, ListValue** out_value) const;
+ // Like Get(), but without special treatment of '.'. This allows e.g. URLs to
+ // be used as paths.
+ bool GetWithoutPathExpansion(const std::wstring& key,
+ Value** out_value) const;
+ bool GetIntegerWithoutPathExpansion(const std::wstring& path,
+ int* out_value) const;
+ bool GetStringWithoutPathExpansion(const std::wstring& path,
+ std::string* out_value) const;
+ bool GetStringWithoutPathExpansion(const std::wstring& path,
+ std::wstring* out_value) const;
+ bool GetDictionaryWithoutPathExpansion(const std::wstring& path,
+ DictionaryValue** out_value) const;
+ bool GetListWithoutPathExpansion(const std::wstring& path,
+ ListValue** out_value) const;
+
// Removes the Value with the specified path from this dictionary (or one
// of its child dictionaries, if the path is more than just a local key).
// If |out_value| is non-NULL, the removed Value AND ITS OWNERSHIP will be
@@ -261,8 +283,16 @@ class DictionaryValue : public Value {
// it will return false and the DictionaryValue object will be unchanged.
bool Remove(const std::wstring& path, Value** out_value);
+ // Like Remove(), but without special treatment of '.'. This allows e.g. URLs
+ // to be used as paths.
+ bool RemoveWithoutPathExpansion(const std::wstring& key, Value** out_value);
+
// This class provides an iterator for the keys in the dictionary.
// It can't be used to modify the dictionary.
+ //
+ // YOU SHOULD ALWAYS USE THE XXXWithoutPathExpansion() APIs WITH THESE, NOT
+ // THE NORMAL XXX() APIs. This makes sure things will work correctly if any
+ // keys have '.'s in them.
class key_iterator
: private std::iterator<std::input_iterator_tag, const std::wstring> {
public:
@@ -280,11 +310,6 @@ class DictionaryValue : public Value {
key_iterator end_keys() const { return key_iterator(dictionary_.end()); }
private:
- // Associates the value |in_value| with the |key|. This method should be
- // used instead of "dictionary_[key] = foo" so that any previous value can
- // be properly deleted.
- void SetInCurrentNode(const std::wstring& key, Value* in_value);
-
ValueMap dictionary_;
DISALLOW_COPY_AND_ASSIGN(DictionaryValue);
diff --git a/base/values_unittest.cc b/base/values_unittest.cc
index 5253eca..0182d76 100644
--- a/base/values_unittest.cc
+++ b/base/values_unittest.cc
@@ -20,9 +20,9 @@ TEST(ValuesTest, Basic) {
ASSERT_EQ(std::wstring(L"http://google.com"), homepage);
ASSERT_FALSE(settings.Get(L"global", NULL));
- ASSERT_TRUE(settings.Set(L"global", Value::CreateBooleanValue(true)));
+ settings.Set(L"global", Value::CreateBooleanValue(true));
ASSERT_TRUE(settings.Get(L"global", NULL));
- ASSERT_TRUE(settings.SetString(L"global.homepage", L"http://scurvy.com"));
+ settings.SetString(L"global.homepage", L"http://scurvy.com");
ASSERT_TRUE(settings.Get(L"global", NULL));
homepage = L"http://google.com";
ASSERT_TRUE(settings.GetString(L"global.homepage", &homepage));
@@ -285,6 +285,28 @@ TEST(ValuesTest, DictionaryRemoval) {
}
}
+TEST(ValuesTest, DictionaryWithoutPathExpansion) {
+ DictionaryValue dict;
+ dict.Set(L"this.is.expanded", Value::CreateNullValue());
+ dict.SetWithoutPathExpansion(L"this.isnt.expanded", Value::CreateNullValue());
+
+ EXPECT_FALSE(dict.HasKey(L"this.is.expanded"));
+ EXPECT_TRUE(dict.HasKey(L"this"));
+ Value* value1;
+ EXPECT_TRUE(dict.Get(L"this", &value1));
+ DictionaryValue* value2;
+ ASSERT_TRUE(dict.GetDictionaryWithoutPathExpansion(L"this", &value2));
+ EXPECT_EQ(value1, value2);
+ EXPECT_EQ(1U, value2->size());
+
+ EXPECT_TRUE(dict.HasKey(L"this.isnt.expanded"));
+ Value* value3;
+ EXPECT_FALSE(dict.Get(L"this.isnt.expanded", &value3));
+ Value* value4;
+ ASSERT_TRUE(dict.GetWithoutPathExpansion(L"this.isnt.expanded", &value4));
+ EXPECT_EQ(Value::TYPE_NULL, value4->GetType());
+}
+
TEST(ValuesTest, DeepCopy) {
DictionaryValue original_dict;
Value* original_null = Value::CreateNullValue();