blob: 9c96f26a99e7be5566e5909281d4e7061c17fddd [file] [log] [blame]
mnissler@chromium.org17cee0e2010-05-14 22:17:40 +09001// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botf003cfe2008-08-24 09:55:55 +09002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit3f4a7322008-07-27 06:49:38 +09004
tony@chromium.orge4948ab2009-12-02 09:20:32 +09005#include "base/values.h"
6
initial.commit3f4a7322008-07-27 06:49:38 +09007#include "base/logging.h"
scherkus@chromium.org2b923e72008-12-11 10:23:17 +09008#include "base/string_util.h"
brettw@chromium.org50c94652009-10-07 11:10:20 +09009#include "base/utf_string_conversions.h"
tony@chromium.orge4948ab2009-12-02 09:20:32 +090010
11namespace {
12
13// Make a deep copy of |node|, but don't include empty lists or dictionaries
14// in the copy. It's possible for this function to return NULL and it
15// expects |node| to always be non-NULL.
16Value* CopyWithoutEmptyChildren(Value* node) {
17 DCHECK(node);
18 switch (node->GetType()) {
19 case Value::TYPE_LIST: {
20 ListValue* list = static_cast<ListValue*>(node);
21 ListValue* copy = new ListValue;
22 for (ListValue::const_iterator it = list->begin(); it != list->end();
23 ++it) {
24 Value* child_copy = CopyWithoutEmptyChildren(*it);
25 if (child_copy)
26 copy->Append(child_copy);
27 }
28 if (!copy->empty())
29 return copy;
30
31 delete copy;
32 return NULL;
33 }
34
35 case Value::TYPE_DICTIONARY: {
36 DictionaryValue* dict = static_cast<DictionaryValue*>(node);
37 DictionaryValue* copy = new DictionaryValue;
38 for (DictionaryValue::key_iterator it = dict->begin_keys();
39 it != dict->end_keys(); ++it) {
40 Value* child = NULL;
41 bool rv = dict->GetWithoutPathExpansion(*it, &child);
42 DCHECK(rv);
43 Value* child_copy = CopyWithoutEmptyChildren(child);
44 if (child_copy)
45 copy->SetWithoutPathExpansion(*it, child_copy);
46 }
47 if (!copy->empty())
48 return copy;
49
50 delete copy;
51 return NULL;
52 }
53
54 default:
55 // For everything else, just make a copy.
56 return node->DeepCopy();
57 }
58}
59
60} // namespace
initial.commit3f4a7322008-07-27 06:49:38 +090061
62///////////////////// Value ////////////////////
63
64Value::~Value() {
65}
66
67// static
68Value* Value::CreateNullValue() {
69 return new Value(TYPE_NULL);
70}
71
72// static
akalin@chromium.org810f92f2011-01-18 11:16:59 +090073FundamentalValue* Value::CreateBooleanValue(bool in_value) {
initial.commit3f4a7322008-07-27 06:49:38 +090074 return new FundamentalValue(in_value);
75}
76
77// static
akalin@chromium.org810f92f2011-01-18 11:16:59 +090078FundamentalValue* Value::CreateIntegerValue(int in_value) {
initial.commit3f4a7322008-07-27 06:49:38 +090079 return new FundamentalValue(in_value);
80}
81
82// static
arv@chromium.org13413eb2011-02-01 10:02:07 +090083FundamentalValue* Value::CreateDoubleValue(double in_value) {
initial.commit3f4a7322008-07-27 06:49:38 +090084 return new FundamentalValue(in_value);
85}
86
87// static
akalin@chromium.org810f92f2011-01-18 11:16:59 +090088StringValue* Value::CreateStringValue(const std::string& in_value) {
scherkus@chromium.org2b923e72008-12-11 10:23:17 +090089 return new StringValue(in_value);
90}
91
92// static
akalin@chromium.org810f92f2011-01-18 11:16:59 +090093StringValue* Value::CreateStringValue(const string16& in_value) {
scherkus@chromium.org5ad62762008-12-11 07:30:57 +090094 return new StringValue(in_value);
scherkus@chromium.org92bc0d42008-12-11 07:18:47 +090095}
96
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +090097// static
initial.commit3f4a7322008-07-27 06:49:38 +090098BinaryValue* Value::CreateBinaryValue(char* buffer, size_t size) {
99 return BinaryValue::Create(buffer, size);
100}
101
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900102bool Value::GetAsBoolean(bool* out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900103 return false;
104}
105
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900106bool Value::GetAsInteger(int* out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900107 return false;
108}
109
arv@chromium.org13413eb2011-02-01 10:02:07 +0900110bool Value::GetAsDouble(double* out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900111 return false;
112}
113
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900114bool Value::GetAsString(std::string* out_value) const {
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900115 return false;
116}
117
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900118bool Value::GetAsString(string16* out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900119 return false;
120}
121
scottbyer@google.com673b8762010-12-07 09:35:29 +0900122bool Value::GetAsList(ListValue** out_value) {
123 return false;
124}
125
initial.commit3f4a7322008-07-27 06:49:38 +0900126Value* Value::DeepCopy() const {
127 // This method should only be getting called for null Values--all subclasses
128 // need to provide their own implementation;.
129 DCHECK(IsType(TYPE_NULL));
130 return CreateNullValue();
131}
132
133bool Value::Equals(const Value* other) const {
134 // This method should only be getting called for null Values--all subclasses
135 // need to provide their own implementation;.
136 DCHECK(IsType(TYPE_NULL));
137 return other->IsType(TYPE_NULL);
138}
139
bauerb@chromium.orgfbd55e12010-12-07 03:13:43 +0900140// static
141bool Value::Equals(const Value* a, const Value* b) {
142 if ((a == NULL) && (b == NULL)) return true;
143 if ((a == NULL) ^ (b == NULL)) return false;
144 return a->Equals(b);
145}
146
erg@chromium.org493f5f62010-07-16 06:03:54 +0900147Value::Value(ValueType type) : type_(type) {
148}
149
initial.commit3f4a7322008-07-27 06:49:38 +0900150///////////////////// FundamentalValue ////////////////////
151
erg@chromium.org493f5f62010-07-16 06:03:54 +0900152FundamentalValue::FundamentalValue(bool in_value)
153 : Value(TYPE_BOOLEAN), boolean_value_(in_value) {
154}
155
156FundamentalValue::FundamentalValue(int in_value)
157 : Value(TYPE_INTEGER), integer_value_(in_value) {
158}
159
160FundamentalValue::FundamentalValue(double in_value)
arv@chromium.org13413eb2011-02-01 10:02:07 +0900161 : Value(TYPE_DOUBLE), double_value_(in_value) {
erg@chromium.org493f5f62010-07-16 06:03:54 +0900162}
163
initial.commit3f4a7322008-07-27 06:49:38 +0900164FundamentalValue::~FundamentalValue() {
165}
166
167bool FundamentalValue::GetAsBoolean(bool* out_value) const {
168 if (out_value && IsType(TYPE_BOOLEAN))
169 *out_value = boolean_value_;
170 return (IsType(TYPE_BOOLEAN));
171}
172
173bool FundamentalValue::GetAsInteger(int* out_value) const {
174 if (out_value && IsType(TYPE_INTEGER))
175 *out_value = integer_value_;
176 return (IsType(TYPE_INTEGER));
177}
178
arv@chromium.org13413eb2011-02-01 10:02:07 +0900179bool FundamentalValue::GetAsDouble(double* out_value) const {
180 if (out_value && IsType(TYPE_DOUBLE))
181 *out_value = double_value_;
182 return (IsType(TYPE_DOUBLE));
initial.commit3f4a7322008-07-27 06:49:38 +0900183}
184
akalin@chromium.org810f92f2011-01-18 11:16:59 +0900185FundamentalValue* FundamentalValue::DeepCopy() const {
initial.commit3f4a7322008-07-27 06:49:38 +0900186 switch (GetType()) {
187 case TYPE_BOOLEAN:
188 return CreateBooleanValue(boolean_value_);
189
190 case TYPE_INTEGER:
191 return CreateIntegerValue(integer_value_);
192
arv@chromium.org13413eb2011-02-01 10:02:07 +0900193 case TYPE_DOUBLE:
194 return CreateDoubleValue(double_value_);
initial.commit3f4a7322008-07-27 06:49:38 +0900195
196 default:
197 NOTREACHED();
198 return NULL;
199 }
200}
201
202bool FundamentalValue::Equals(const Value* other) const {
203 if (other->GetType() != GetType())
204 return false;
205
206 switch (GetType()) {
207 case TYPE_BOOLEAN: {
208 bool lhs, rhs;
209 return GetAsBoolean(&lhs) && other->GetAsBoolean(&rhs) && lhs == rhs;
210 }
211 case TYPE_INTEGER: {
212 int lhs, rhs;
213 return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs;
214 }
arv@chromium.org13413eb2011-02-01 10:02:07 +0900215 case TYPE_DOUBLE: {
initial.commit3f4a7322008-07-27 06:49:38 +0900216 double lhs, rhs;
arv@chromium.org13413eb2011-02-01 10:02:07 +0900217 return GetAsDouble(&lhs) && other->GetAsDouble(&rhs) && lhs == rhs;
initial.commit3f4a7322008-07-27 06:49:38 +0900218 }
219 default:
220 NOTREACHED();
221 return false;
222 }
223}
224
225///////////////////// StringValue ////////////////////
226
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900227StringValue::StringValue(const std::string& in_value)
228 : Value(TYPE_STRING),
229 value_(in_value) {
230 DCHECK(IsStringUTF8(in_value));
231}
232
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900233StringValue::StringValue(const string16& in_value)
234 : Value(TYPE_STRING),
235 value_(UTF16ToUTF8(in_value)) {
236}
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900237
initial.commit3f4a7322008-07-27 06:49:38 +0900238StringValue::~StringValue() {
239}
240
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900241bool StringValue::GetAsString(std::string* out_value) const {
242 if (out_value)
243 *out_value = value_;
244 return true;
245}
246
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900247bool StringValue::GetAsString(string16* out_value) const {
248 if (out_value)
249 *out_value = UTF8ToUTF16(value_);
250 return true;
251}
252
akalin@chromium.org810f92f2011-01-18 11:16:59 +0900253StringValue* StringValue::DeepCopy() const {
initial.commit3f4a7322008-07-27 06:49:38 +0900254 return CreateStringValue(value_);
255}
256
257bool StringValue::Equals(const Value* other) const {
258 if (other->GetType() != GetType())
259 return false;
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900260 std::string lhs, rhs;
initial.commit3f4a7322008-07-27 06:49:38 +0900261 return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs;
262}
263
264///////////////////// BinaryValue ////////////////////
265
erg@google.com67a25432011-01-08 05:23:43 +0900266BinaryValue::~BinaryValue() {
267 DCHECK(buffer_);
268 if (buffer_)
269 delete[] buffer_;
270}
271
jcampan@chromium.orgd1105672009-09-15 01:56:12 +0900272// static
initial.commit3f4a7322008-07-27 06:49:38 +0900273BinaryValue* BinaryValue::Create(char* buffer, size_t size) {
274 if (!buffer)
275 return NULL;
276
277 return new BinaryValue(buffer, size);
278}
279
jcampan@chromium.orgd1105672009-09-15 01:56:12 +0900280// static
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900281BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer,
282 size_t size) {
initial.commit3f4a7322008-07-27 06:49:38 +0900283 if (!buffer)
284 return NULL;
285
286 char* buffer_copy = new char[size];
mmentovai@google.com4a5b6272008-08-07 00:46:59 +0900287 memcpy(buffer_copy, buffer, size);
initial.commit3f4a7322008-07-27 06:49:38 +0900288 return new BinaryValue(buffer_copy, size);
289}
290
akalin@chromium.org810f92f2011-01-18 11:16:59 +0900291BinaryValue* BinaryValue::DeepCopy() const {
initial.commit3f4a7322008-07-27 06:49:38 +0900292 return CreateWithCopiedBuffer(buffer_, size_);
293}
294
295bool BinaryValue::Equals(const Value* other) const {
296 if (other->GetType() != GetType())
297 return false;
298 const BinaryValue* other_binary = static_cast<const BinaryValue*>(other);
299 if (other_binary->size_ != size_)
300 return false;
301 return !memcmp(buffer_, other_binary->buffer_, size_);
302}
303
erg@google.com67a25432011-01-08 05:23:43 +0900304BinaryValue::BinaryValue(char* buffer, size_t size)
305 : Value(TYPE_BINARY),
306 buffer_(buffer),
307 size_(size) {
308 DCHECK(buffer_);
309}
310
initial.commit3f4a7322008-07-27 06:49:38 +0900311///////////////////// DictionaryValue ////////////////////
312
erg@chromium.org493f5f62010-07-16 06:03:54 +0900313DictionaryValue::DictionaryValue()
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900314 : Value(TYPE_DICTIONARY) {
erg@chromium.org493f5f62010-07-16 06:03:54 +0900315}
316
initial.commit3f4a7322008-07-27 06:49:38 +0900317DictionaryValue::~DictionaryValue() {
318 Clear();
319}
320
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900321bool DictionaryValue::HasKey(const std::string& key) const {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900322 DCHECK(IsStringUTF8(key));
tony@chromium.orge4948ab2009-12-02 09:20:32 +0900323 ValueMap::const_iterator current_entry = dictionary_.find(key);
324 DCHECK((current_entry == dictionary_.end()) || current_entry->second);
325 return current_entry != dictionary_.end();
326}
327
initial.commit3f4a7322008-07-27 06:49:38 +0900328void DictionaryValue::Clear() {
329 ValueMap::iterator dict_iterator = dictionary_.begin();
330 while (dict_iterator != dictionary_.end()) {
331 delete dict_iterator->second;
332 ++dict_iterator;
333 }
334
335 dictionary_.clear();
336}
337
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900338void DictionaryValue::Set(const std::string& path, Value* in_value) {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900339 DCHECK(IsStringUTF8(path));
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900340 DCHECK(in_value);
341
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900342 std::string current_path(path);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900343 DictionaryValue* current_dictionary = this;
344 for (size_t delimiter_position = current_path.find('.');
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900345 delimiter_position != std::string::npos;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900346 delimiter_position = current_path.find('.')) {
347 // Assume that we're indexing into a dictionary.
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900348 std::string key(current_path, 0, delimiter_position);
pkasting@chromium.org8535dc22009-11-26 06:02:24 +0900349 DictionaryValue* child_dictionary = NULL;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900350 if (!current_dictionary->GetDictionary(key, &child_dictionary)) {
351 child_dictionary = new DictionaryValue;
352 current_dictionary->SetWithoutPathExpansion(key, child_dictionary);
353 }
354
355 current_dictionary = child_dictionary;
356 current_path.erase(0, delimiter_position + 1);
357 }
358
359 current_dictionary->SetWithoutPathExpansion(current_path, in_value);
360}
361
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900362void DictionaryValue::SetBoolean(const std::string& path, bool in_value) {
363 Set(path, CreateBooleanValue(in_value));
364}
365
366void DictionaryValue::SetInteger(const std::string& path, int in_value) {
367 Set(path, CreateIntegerValue(in_value));
368}
369
arv@chromium.org13413eb2011-02-01 10:02:07 +0900370void DictionaryValue::SetDouble(const std::string& path, double in_value) {
371 Set(path, CreateDoubleValue(in_value));
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900372}
373
374void DictionaryValue::SetString(const std::string& path,
375 const std::string& in_value) {
376 Set(path, CreateStringValue(in_value));
377}
378
viettrungluu@chromium.orgb7b6aa02010-08-05 01:58:12 +0900379void DictionaryValue::SetString(const std::string& path,
380 const string16& in_value) {
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900381 Set(path, CreateStringValue(in_value));
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900382}
383
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900384void DictionaryValue::SetWithoutPathExpansion(const std::string& key,
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900385 Value* in_value) {
initial.commit3f4a7322008-07-27 06:49:38 +0900386 // If there's an existing value here, we need to delete it, because
387 // we own all our children.
388 if (HasKey(key)) {
389 DCHECK(dictionary_[key] != in_value); // This would be bogus
390 delete dictionary_[key];
391 }
392
393 dictionary_[key] = in_value;
394}
395
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900396bool DictionaryValue::Get(const std::string& path, Value** out_value) const {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900397 DCHECK(IsStringUTF8(path));
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900398 std::string current_path(path);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900399 const DictionaryValue* current_dictionary = this;
400 for (size_t delimiter_position = current_path.find('.');
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900401 delimiter_position != std::string::npos;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900402 delimiter_position = current_path.find('.')) {
pkasting@chromium.org8535dc22009-11-26 06:02:24 +0900403 DictionaryValue* child_dictionary = NULL;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900404 if (!current_dictionary->GetDictionary(
405 current_path.substr(0, delimiter_position), &child_dictionary))
406 return false;
initial.commit3f4a7322008-07-27 06:49:38 +0900407
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900408 current_dictionary = child_dictionary;
409 current_path.erase(0, delimiter_position + 1);
initial.commit3f4a7322008-07-27 06:49:38 +0900410 }
411
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900412 return current_dictionary->GetWithoutPathExpansion(current_path, out_value);
initial.commit3f4a7322008-07-27 06:49:38 +0900413}
414
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900415bool DictionaryValue::GetBoolean(const std::string& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900416 bool* bool_value) const {
417 Value* value;
418 if (!Get(path, &value))
419 return false;
420
421 return value->GetAsBoolean(bool_value);
422}
423
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900424bool DictionaryValue::GetInteger(const std::string& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900425 int* out_value) const {
426 Value* value;
427 if (!Get(path, &value))
428 return false;
429
430 return value->GetAsInteger(out_value);
431}
432
arv@chromium.org13413eb2011-02-01 10:02:07 +0900433bool DictionaryValue::GetDouble(const std::string& path,
434 double* out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900435 Value* value;
436 if (!Get(path, &value))
437 return false;
438
arv@chromium.org13413eb2011-02-01 10:02:07 +0900439 return value->GetAsDouble(out_value);
initial.commit3f4a7322008-07-27 06:49:38 +0900440}
441
evan@chromium.orgd9ab8de2010-02-19 22:32:16 +0900442bool DictionaryValue::GetString(const std::string& path,
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900443 std::string* out_value) const {
444 Value* value;
445 if (!Get(path, &value))
446 return false;
447
448 return value->GetAsString(out_value);
449}
450
viettrungluu@chromium.org58767ef2010-08-05 04:35:33 +0900451bool DictionaryValue::GetString(const std::string& path,
452 string16* out_value) const {
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900453 Value* value;
454 if (!Get(path, &value))
455 return false;
456
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900457 return value->GetAsString(out_value);
evan@chromium.orgd9ab8de2010-02-19 22:32:16 +0900458}
459
460bool DictionaryValue::GetStringASCII(const std::string& path,
461 std::string* out_value) const {
462 std::string out;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900463 if (!GetString(path, &out))
evan@chromium.orgd9ab8de2010-02-19 22:32:16 +0900464 return false;
465
466 if (!IsStringASCII(out)) {
467 NOTREACHED();
468 return false;
469 }
470
471 out_value->assign(out);
472 return true;
473}
474
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900475bool DictionaryValue::GetBinary(const std::string& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900476 BinaryValue** out_value) const {
477 Value* value;
478 bool result = Get(path, &value);
479 if (!result || !value->IsType(TYPE_BINARY))
480 return false;
481
482 if (out_value)
483 *out_value = static_cast<BinaryValue*>(value);
484
485 return true;
486}
487
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900488bool DictionaryValue::GetDictionary(const std::string& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900489 DictionaryValue** out_value) const {
490 Value* value;
491 bool result = Get(path, &value);
492 if (!result || !value->IsType(TYPE_DICTIONARY))
493 return false;
494
495 if (out_value)
496 *out_value = static_cast<DictionaryValue*>(value);
497
498 return true;
499}
500
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900501bool DictionaryValue::GetList(const std::string& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900502 ListValue** out_value) const {
503 Value* value;
504 bool result = Get(path, &value);
505 if (!result || !value->IsType(TYPE_LIST))
506 return false;
507
508 if (out_value)
509 *out_value = static_cast<ListValue*>(value);
510
511 return true;
512}
513
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900514bool DictionaryValue::GetWithoutPathExpansion(const std::string& key,
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900515 Value** out_value) const {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900516 DCHECK(IsStringUTF8(key));
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900517 ValueMap::const_iterator entry_iterator = dictionary_.find(key);
518 if (entry_iterator == dictionary_.end())
519 return false;
initial.commit3f4a7322008-07-27 06:49:38 +0900520
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900521 Value* entry = entry_iterator->second;
522 if (out_value)
523 *out_value = entry;
524 return true;
525}
526
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900527bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::string& key,
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900528 int* out_value) const {
529 Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900530 if (!GetWithoutPathExpansion(key, &value))
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900531 return false;
532
533 return value->GetAsInteger(out_value);
534}
535
arv@chromium.org13413eb2011-02-01 10:02:07 +0900536bool DictionaryValue::GetDoubleWithoutPathExpansion(const std::string& key,
537 double* out_value) const {
jam@chromium.org5bd53922010-10-01 16:28:25 +0900538 Value* value;
539 if (!GetWithoutPathExpansion(key, &value))
540 return false;
541
arv@chromium.org13413eb2011-02-01 10:02:07 +0900542 return value->GetAsDouble(out_value);
jam@chromium.org5bd53922010-10-01 16:28:25 +0900543}
544
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900545bool DictionaryValue::GetStringWithoutPathExpansion(
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900546 const std::string& key,
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900547 std::string* out_value) const {
548 Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900549 if (!GetWithoutPathExpansion(key, &value))
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900550 return false;
551
552 return value->GetAsString(out_value);
553}
554
viettrungluu@chromium.org58767ef2010-08-05 04:35:33 +0900555bool DictionaryValue::GetStringWithoutPathExpansion(
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900556 const std::string& key,
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900557 string16* out_value) const {
558 Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900559 if (!GetWithoutPathExpansion(key, &value))
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900560 return false;
561
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900562 return value->GetAsString(out_value);
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900563}
564
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900565bool DictionaryValue::GetDictionaryWithoutPathExpansion(
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900566 const std::string& key,
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900567 DictionaryValue** out_value) const {
568 Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900569 bool result = GetWithoutPathExpansion(key, &value);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900570 if (!result || !value->IsType(TYPE_DICTIONARY))
571 return false;
572
573 if (out_value)
574 *out_value = static_cast<DictionaryValue*>(value);
575
576 return true;
577}
578
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900579bool DictionaryValue::GetListWithoutPathExpansion(const std::string& key,
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900580 ListValue** out_value) const {
581 Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900582 bool result = GetWithoutPathExpansion(key, &value);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900583 if (!result || !value->IsType(TYPE_LIST))
584 return false;
585
586 if (out_value)
587 *out_value = static_cast<ListValue*>(value);
588
589 return true;
590}
591
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900592bool DictionaryValue::Remove(const std::string& path, Value** out_value) {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900593 DCHECK(IsStringUTF8(path));
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900594 std::string current_path(path);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900595 DictionaryValue* current_dictionary = this;
596 size_t delimiter_position = current_path.rfind('.');
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900597 if (delimiter_position != std::string::npos) {
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900598 if (!GetDictionary(current_path.substr(0, delimiter_position),
599 &current_dictionary))
600 return false;
601 current_path.erase(0, delimiter_position + 1);
initial.commit3f4a7322008-07-27 06:49:38 +0900602 }
603
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900604 return current_dictionary->RemoveWithoutPathExpansion(current_path,
605 out_value);
606}
607
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900608bool DictionaryValue::RemoveWithoutPathExpansion(const std::string& key,
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900609 Value** out_value) {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900610 DCHECK(IsStringUTF8(key));
initial.commit3f4a7322008-07-27 06:49:38 +0900611 ValueMap::iterator entry_iterator = dictionary_.find(key);
612 if (entry_iterator == dictionary_.end())
613 return false;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900614
initial.commit3f4a7322008-07-27 06:49:38 +0900615 Value* entry = entry_iterator->second;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900616 if (out_value)
617 *out_value = entry;
618 else
619 delete entry;
620 dictionary_.erase(entry_iterator);
621 return true;
initial.commit3f4a7322008-07-27 06:49:38 +0900622}
623
tony@chromium.orge4948ab2009-12-02 09:20:32 +0900624DictionaryValue* DictionaryValue::DeepCopyWithoutEmptyChildren() {
625 Value* copy = CopyWithoutEmptyChildren(this);
626 return copy ? static_cast<DictionaryValue*>(copy) : new DictionaryValue;
initial.commit3f4a7322008-07-27 06:49:38 +0900627}
628
mnissler@chromium.org17cee0e2010-05-14 22:17:40 +0900629void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) {
630 for (DictionaryValue::key_iterator key(dictionary->begin_keys());
631 key != dictionary->end_keys(); ++key) {
632 Value* merge_value;
633 if (dictionary->GetWithoutPathExpansion(*key, &merge_value)) {
634 // Check whether we have to merge dictionaries.
635 if (merge_value->IsType(Value::TYPE_DICTIONARY)) {
636 DictionaryValue* sub_dict;
637 if (GetDictionaryWithoutPathExpansion(*key, &sub_dict)) {
638 sub_dict->MergeDictionary(
639 static_cast<const DictionaryValue*>(merge_value));
640 continue;
641 }
642 }
643 // All other cases: Make a copy and hook it up.
644 SetWithoutPathExpansion(*key, merge_value->DeepCopy());
645 }
646 }
647}
648
akalin@chromium.org810f92f2011-01-18 11:16:59 +0900649DictionaryValue* DictionaryValue::DeepCopy() const {
erg@google.com67a25432011-01-08 05:23:43 +0900650 DictionaryValue* result = new DictionaryValue;
651
652 for (ValueMap::const_iterator current_entry(dictionary_.begin());
653 current_entry != dictionary_.end(); ++current_entry) {
654 result->SetWithoutPathExpansion(current_entry->first,
655 current_entry->second->DeepCopy());
656 }
657
658 return result;
659}
660
661bool DictionaryValue::Equals(const Value* other) const {
662 if (other->GetType() != GetType())
663 return false;
664
665 const DictionaryValue* other_dict =
666 static_cast<const DictionaryValue*>(other);
667 key_iterator lhs_it(begin_keys());
668 key_iterator rhs_it(other_dict->begin_keys());
669 while (lhs_it != end_keys() && rhs_it != other_dict->end_keys()) {
670 Value* lhs;
671 Value* rhs;
672 if (*lhs_it != *rhs_it ||
673 !GetWithoutPathExpansion(*lhs_it, &lhs) ||
674 !other_dict->GetWithoutPathExpansion(*rhs_it, &rhs) ||
675 !lhs->Equals(rhs)) {
676 return false;
677 }
678 ++lhs_it;
679 ++rhs_it;
680 }
681 if (lhs_it != end_keys() || rhs_it != other_dict->end_keys())
682 return false;
683
684 return true;
685}
686
initial.commit3f4a7322008-07-27 06:49:38 +0900687///////////////////// ListValue ////////////////////
688
erg@chromium.org493f5f62010-07-16 06:03:54 +0900689ListValue::ListValue() : Value(TYPE_LIST) {
690}
691
initial.commit3f4a7322008-07-27 06:49:38 +0900692ListValue::~ListValue() {
693 Clear();
694}
695
696void ListValue::Clear() {
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900697 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i)
698 delete *i;
initial.commit3f4a7322008-07-27 06:49:38 +0900699 list_.clear();
700}
701
702bool ListValue::Set(size_t index, Value* in_value) {
703 if (!in_value)
704 return false;
705
706 if (index >= list_.size()) {
707 // Pad out any intermediate indexes with null settings
708 while (index > list_.size())
709 Append(CreateNullValue());
710 Append(in_value);
711 } else {
712 DCHECK(list_[index] != in_value);
713 delete list_[index];
714 list_[index] = in_value;
715 }
716 return true;
717}
718
719bool ListValue::Get(size_t index, Value** out_value) const {
720 if (index >= list_.size())
721 return false;
722
723 if (out_value)
724 *out_value = list_[index];
725
726 return true;
727}
728
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900729bool ListValue::GetBoolean(size_t index, bool* bool_value) const {
730 Value* value;
731 if (!Get(index, &value))
732 return false;
733
734 return value->GetAsBoolean(bool_value);
735}
736
737bool ListValue::GetInteger(size_t index, int* out_value) const {
738 Value* value;
739 if (!Get(index, &value))
740 return false;
741
742 return value->GetAsInteger(out_value);
743}
744
arv@chromium.org13413eb2011-02-01 10:02:07 +0900745bool ListValue::GetDouble(size_t index, double* out_value) const {
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900746 Value* value;
747 if (!Get(index, &value))
748 return false;
749
arv@chromium.org13413eb2011-02-01 10:02:07 +0900750 return value->GetAsDouble(out_value);
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900751}
752
753bool ListValue::GetString(size_t index, std::string* out_value) const {
754 Value* value;
755 if (!Get(index, &value))
756 return false;
757
758 return value->GetAsString(out_value);
759}
760
viettrungluu@chromium.org58767ef2010-08-05 04:35:33 +0900761bool ListValue::GetString(size_t index, string16* out_value) const {
762 Value* value;
763 if (!Get(index, &value))
764 return false;
765
766 return value->GetAsString(out_value);
767}
768
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900769bool ListValue::GetBinary(size_t index, BinaryValue** out_value) const {
770 Value* value;
771 bool result = Get(index, &value);
772 if (!result || !value->IsType(TYPE_BINARY))
773 return false;
774
775 if (out_value)
776 *out_value = static_cast<BinaryValue*>(value);
777
778 return true;
779}
780
781bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900782 Value* value;
783 bool result = Get(index, &value);
784 if (!result || !value->IsType(TYPE_DICTIONARY))
785 return false;
786
787 if (out_value)
788 *out_value = static_cast<DictionaryValue*>(value);
789
790 return true;
791}
792
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900793bool ListValue::GetList(size_t index, ListValue** out_value) const {
794 Value* value;
795 bool result = Get(index, &value);
796 if (!result || !value->IsType(TYPE_LIST))
797 return false;
798
799 if (out_value)
800 *out_value = static_cast<ListValue*>(value);
801
802 return true;
803}
804
initial.commit3f4a7322008-07-27 06:49:38 +0900805bool ListValue::Remove(size_t index, Value** out_value) {
806 if (index >= list_.size())
807 return false;
808
809 if (out_value)
810 *out_value = list_[index];
811 else
812 delete list_[index];
813
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900814 list_.erase(list_.begin() + index);
initial.commit3f4a7322008-07-27 06:49:38 +0900815 return true;
816}
817
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900818int ListValue::Remove(const Value& value) {
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900819 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) {
820 if ((*i)->Equals(&value)) {
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900821 size_t index = i - list_.begin();
pkasting@chromium.orgdfe6a692009-12-01 04:59:11 +0900822 delete *i;
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900823 list_.erase(i);
robertshield@chromium.org9fb9e372010-03-23 05:12:50 +0900824
825 // TODO(anyone): Returning a signed int type here is just wrong.
826 // Change this interface to return a size_t.
827 DCHECK(index <= INT_MAX);
828 int return_index = static_cast<int>(index);
829 return return_index;
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900830 }
831 }
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900832 return -1;
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900833}
834
initial.commit3f4a7322008-07-27 06:49:38 +0900835void ListValue::Append(Value* in_value) {
836 DCHECK(in_value);
837 list_.push_back(in_value);
838}
839
zork@chromium.orgb5f742b2010-04-13 06:48:10 +0900840bool ListValue::AppendIfNotPresent(Value* in_value) {
841 DCHECK(in_value);
ziadh@chromium.org5c7f6312010-07-19 17:00:42 +0900842 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i) {
zork@chromium.orgb5f742b2010-04-13 06:48:10 +0900843 if ((*i)->Equals(in_value))
844 return false;
845 }
846 list_.push_back(in_value);
847 return true;
848}
849
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900850bool ListValue::Insert(size_t index, Value* in_value) {
851 DCHECK(in_value);
jhawkins@chromium.org33edb6b2009-10-01 06:36:37 +0900852 if (index > list_.size())
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900853 return false;
854
855 list_.insert(list_.begin() + index, in_value);
856 return true;
857}
858
scottbyer@google.com673b8762010-12-07 09:35:29 +0900859bool ListValue::GetAsList(ListValue** out_value) {
860 if (out_value)
861 *out_value = this;
862 return true;
863}
864
akalin@chromium.org810f92f2011-01-18 11:16:59 +0900865ListValue* ListValue::DeepCopy() const {
initial.commit3f4a7322008-07-27 06:49:38 +0900866 ListValue* result = new ListValue;
867
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900868 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i)
869 result->Append((*i)->DeepCopy());
initial.commit3f4a7322008-07-27 06:49:38 +0900870
871 return result;
872}
873
874bool ListValue::Equals(const Value* other) const {
875 if (other->GetType() != GetType())
876 return false;
877
878 const ListValue* other_list =
879 static_cast<const ListValue*>(other);
880 const_iterator lhs_it, rhs_it;
881 for (lhs_it = begin(), rhs_it = other_list->begin();
882 lhs_it != end() && rhs_it != other_list->end();
883 ++lhs_it, ++rhs_it) {
884 if (!(*lhs_it)->Equals(*rhs_it))
885 return false;
886 }
887 if (lhs_it != end() || rhs_it != other_list->end())
888 return false;
889
890 return true;
891}
erg@chromium.org493f5f62010-07-16 06:03:54 +0900892
893ValueSerializer::~ValueSerializer() {
894}