blob: eebd7eb2f1b369d970999065a3d59f32dc4efcbe [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
73Value* Value::CreateBooleanValue(bool in_value) {
74 return new FundamentalValue(in_value);
75}
76
77// static
78Value* Value::CreateIntegerValue(int in_value) {
79 return new FundamentalValue(in_value);
80}
81
82// static
83Value* Value::CreateRealValue(double in_value) {
84 return new FundamentalValue(in_value);
85}
86
87// static
scherkus@chromium.org2b923e72008-12-11 10:23:17 +090088Value* Value::CreateStringValue(const std::string& in_value) {
89 return new StringValue(in_value);
90}
91
92// static
scherkus@chromium.org92bc0d42008-12-11 07:18:47 +090093Value* Value::CreateStringValue(const std::wstring& 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
97// static
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +090098Value* Value::CreateStringValueFromUTF16(const string16& in_value) {
99 return new StringValue(in_value);
100}
101
102// static
initial.commit3f4a7322008-07-27 06:49:38 +0900103BinaryValue* Value::CreateBinaryValue(char* buffer, size_t size) {
104 return BinaryValue::Create(buffer, size);
105}
106
107bool Value::GetAsBoolean(bool* in_value) const {
108 return false;
109}
110
111bool Value::GetAsInteger(int* in_value) const {
112 return false;
113}
114
115bool Value::GetAsReal(double* in_value) const {
116 return false;
117}
118
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900119bool Value::GetAsString(std::string* in_value) const {
120 return false;
121}
122
initial.commit3f4a7322008-07-27 06:49:38 +0900123bool Value::GetAsString(std::wstring* in_value) const {
124 return false;
125}
126
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900127bool Value::GetAsUTF16(string16* out_value) const {
128 return false;
129}
130
initial.commit3f4a7322008-07-27 06:49:38 +0900131Value* Value::DeepCopy() const {
132 // This method should only be getting called for null Values--all subclasses
133 // need to provide their own implementation;.
134 DCHECK(IsType(TYPE_NULL));
135 return CreateNullValue();
136}
137
138bool Value::Equals(const Value* other) const {
139 // This method should only be getting called for null Values--all subclasses
140 // need to provide their own implementation;.
141 DCHECK(IsType(TYPE_NULL));
142 return other->IsType(TYPE_NULL);
143}
144
erg@chromium.org493f5f62010-07-16 06:03:54 +0900145Value::Value(ValueType type) : type_(type) {
146}
147
initial.commit3f4a7322008-07-27 06:49:38 +0900148///////////////////// FundamentalValue ////////////////////
149
erg@chromium.org493f5f62010-07-16 06:03:54 +0900150FundamentalValue::FundamentalValue(bool in_value)
151 : Value(TYPE_BOOLEAN), boolean_value_(in_value) {
152}
153
154FundamentalValue::FundamentalValue(int in_value)
155 : Value(TYPE_INTEGER), integer_value_(in_value) {
156}
157
158FundamentalValue::FundamentalValue(double in_value)
159 : Value(TYPE_REAL), real_value_(in_value) {
160}
161
initial.commit3f4a7322008-07-27 06:49:38 +0900162FundamentalValue::~FundamentalValue() {
163}
164
165bool FundamentalValue::GetAsBoolean(bool* out_value) const {
166 if (out_value && IsType(TYPE_BOOLEAN))
167 *out_value = boolean_value_;
168 return (IsType(TYPE_BOOLEAN));
169}
170
171bool FundamentalValue::GetAsInteger(int* out_value) const {
172 if (out_value && IsType(TYPE_INTEGER))
173 *out_value = integer_value_;
174 return (IsType(TYPE_INTEGER));
175}
176
177bool FundamentalValue::GetAsReal(double* out_value) const {
178 if (out_value && IsType(TYPE_REAL))
179 *out_value = real_value_;
180 return (IsType(TYPE_REAL));
181}
182
183Value* FundamentalValue::DeepCopy() const {
184 switch (GetType()) {
185 case TYPE_BOOLEAN:
186 return CreateBooleanValue(boolean_value_);
187
188 case TYPE_INTEGER:
189 return CreateIntegerValue(integer_value_);
190
191 case TYPE_REAL:
192 return CreateRealValue(real_value_);
193
194 default:
195 NOTREACHED();
196 return NULL;
197 }
198}
199
200bool FundamentalValue::Equals(const Value* other) const {
201 if (other->GetType() != GetType())
202 return false;
203
204 switch (GetType()) {
205 case TYPE_BOOLEAN: {
206 bool lhs, rhs;
207 return GetAsBoolean(&lhs) && other->GetAsBoolean(&rhs) && lhs == rhs;
208 }
209 case TYPE_INTEGER: {
210 int lhs, rhs;
211 return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs;
212 }
213 case TYPE_REAL: {
214 double lhs, rhs;
215 return GetAsReal(&lhs) && other->GetAsReal(&rhs) && lhs == rhs;
216 }
217 default:
218 NOTREACHED();
219 return false;
220 }
221}
222
223///////////////////// StringValue ////////////////////
224
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900225StringValue::StringValue(const std::string& in_value)
226 : Value(TYPE_STRING),
227 value_(in_value) {
228 DCHECK(IsStringUTF8(in_value));
229}
230
231StringValue::StringValue(const std::wstring& in_value)
232 : Value(TYPE_STRING),
233 value_(WideToUTF8(in_value)) {
234}
235
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900236#if !defined(WCHAR_T_IS_UTF16)
237StringValue::StringValue(const string16& in_value)
238 : Value(TYPE_STRING),
239 value_(UTF16ToUTF8(in_value)) {
240}
241#endif
242
initial.commit3f4a7322008-07-27 06:49:38 +0900243StringValue::~StringValue() {
244}
245
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900246bool StringValue::GetAsString(std::string* out_value) const {
247 if (out_value)
248 *out_value = value_;
249 return true;
250}
251
initial.commit3f4a7322008-07-27 06:49:38 +0900252bool StringValue::GetAsString(std::wstring* out_value) const {
253 if (out_value)
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900254 *out_value = UTF8ToWide(value_);
initial.commit3f4a7322008-07-27 06:49:38 +0900255 return true;
256}
257
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900258bool StringValue::GetAsUTF16(string16* out_value) const {
259 if (out_value)
260 *out_value = UTF8ToUTF16(value_);
261 return true;
262}
263
initial.commit3f4a7322008-07-27 06:49:38 +0900264Value* StringValue::DeepCopy() const {
265 return CreateStringValue(value_);
266}
267
268bool StringValue::Equals(const Value* other) const {
269 if (other->GetType() != GetType())
270 return false;
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900271 std::string lhs, rhs;
initial.commit3f4a7322008-07-27 06:49:38 +0900272 return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs;
273}
274
275///////////////////// BinaryValue ////////////////////
276
jcampan@chromium.orgd1105672009-09-15 01:56:12 +0900277// static
initial.commit3f4a7322008-07-27 06:49:38 +0900278BinaryValue* BinaryValue::Create(char* buffer, size_t size) {
279 if (!buffer)
280 return NULL;
281
282 return new BinaryValue(buffer, size);
283}
284
jcampan@chromium.orgd1105672009-09-15 01:56:12 +0900285// static
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900286BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer,
287 size_t size) {
initial.commit3f4a7322008-07-27 06:49:38 +0900288 if (!buffer)
289 return NULL;
290
291 char* buffer_copy = new char[size];
mmentovai@google.com4a5b6272008-08-07 00:46:59 +0900292 memcpy(buffer_copy, buffer, size);
initial.commit3f4a7322008-07-27 06:49:38 +0900293 return new BinaryValue(buffer_copy, size);
294}
295
296
297BinaryValue::BinaryValue(char* buffer, size_t size)
298 : Value(TYPE_BINARY),
299 buffer_(buffer),
300 size_(size) {
301 DCHECK(buffer_);
302}
303
304BinaryValue::~BinaryValue() {
305 DCHECK(buffer_);
306 if (buffer_)
307 delete[] buffer_;
308}
309
310Value* BinaryValue::DeepCopy() const {
311 return CreateWithCopiedBuffer(buffer_, size_);
312}
313
314bool BinaryValue::Equals(const Value* other) const {
315 if (other->GetType() != GetType())
316 return false;
317 const BinaryValue* other_binary = static_cast<const BinaryValue*>(other);
318 if (other_binary->size_ != size_)
319 return false;
320 return !memcmp(buffer_, other_binary->buffer_, size_);
321}
322
323///////////////////// DictionaryValue ////////////////////
324
erg@chromium.org493f5f62010-07-16 06:03:54 +0900325DictionaryValue::DictionaryValue()
326 : Value(TYPE_DICTIONARY) {
327}
328
initial.commit3f4a7322008-07-27 06:49:38 +0900329DictionaryValue::~DictionaryValue() {
330 Clear();
331}
332
tony@chromium.orge4948ab2009-12-02 09:20:32 +0900333Value* DictionaryValue::DeepCopy() const {
334 DictionaryValue* result = new DictionaryValue;
335
336 for (ValueMap::const_iterator current_entry(dictionary_.begin());
337 current_entry != dictionary_.end(); ++current_entry) {
338 result->SetWithoutPathExpansion(current_entry->first,
339 current_entry->second->DeepCopy());
340 }
341
342 return result;
343}
344
345bool DictionaryValue::Equals(const Value* other) const {
346 if (other->GetType() != GetType())
347 return false;
348
349 const DictionaryValue* other_dict =
350 static_cast<const DictionaryValue*>(other);
351 key_iterator lhs_it(begin_keys());
352 key_iterator rhs_it(other_dict->begin_keys());
353 while (lhs_it != end_keys() && rhs_it != other_dict->end_keys()) {
354 Value* lhs;
355 Value* rhs;
356 if (!GetWithoutPathExpansion(*lhs_it, &lhs) ||
357 !other_dict->GetWithoutPathExpansion(*rhs_it, &rhs) ||
358 !lhs->Equals(rhs)) {
359 return false;
360 }
361 ++lhs_it;
362 ++rhs_it;
363 }
364 if (lhs_it != end_keys() || rhs_it != other_dict->end_keys())
365 return false;
366
367 return true;
368}
369
370bool DictionaryValue::HasKey(const std::wstring& key) const {
371 ValueMap::const_iterator current_entry = dictionary_.find(key);
372 DCHECK((current_entry == dictionary_.end()) || current_entry->second);
373 return current_entry != dictionary_.end();
374}
375
evan@chromium.orgd9ab8de2010-02-19 22:32:16 +0900376bool DictionaryValue::HasKeyASCII(const std::string& key) const {
377 return HasKey(ASCIIToWide(key));
378}
379
initial.commit3f4a7322008-07-27 06:49:38 +0900380void DictionaryValue::Clear() {
381 ValueMap::iterator dict_iterator = dictionary_.begin();
382 while (dict_iterator != dictionary_.end()) {
383 delete dict_iterator->second;
384 ++dict_iterator;
385 }
386
387 dictionary_.clear();
388}
389
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900390void DictionaryValue::Set(const std::wstring& path, Value* in_value) {
391 DCHECK(in_value);
392
393 std::wstring current_path(path);
394 DictionaryValue* current_dictionary = this;
395 for (size_t delimiter_position = current_path.find('.');
396 delimiter_position != std::wstring::npos;
397 delimiter_position = current_path.find('.')) {
398 // Assume that we're indexing into a dictionary.
399 std::wstring key(current_path, 0, delimiter_position);
pkasting@chromium.org8535dc22009-11-26 06:02:24 +0900400 DictionaryValue* child_dictionary = NULL;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900401 if (!current_dictionary->GetDictionary(key, &child_dictionary)) {
402 child_dictionary = new DictionaryValue;
403 current_dictionary->SetWithoutPathExpansion(key, child_dictionary);
404 }
405
406 current_dictionary = child_dictionary;
407 current_path.erase(0, delimiter_position + 1);
408 }
409
410 current_dictionary->SetWithoutPathExpansion(current_path, in_value);
411}
412
413void DictionaryValue::SetBoolean(const std::wstring& path, bool in_value) {
414 Set(path, CreateBooleanValue(in_value));
415}
416
417void DictionaryValue::SetInteger(const std::wstring& path, int in_value) {
418 Set(path, CreateIntegerValue(in_value));
419}
420
421void DictionaryValue::SetReal(const std::wstring& path, double in_value) {
422 Set(path, CreateRealValue(in_value));
423}
424
425void DictionaryValue::SetString(const std::wstring& path,
426 const std::string& in_value) {
427 Set(path, CreateStringValue(in_value));
428}
429
430void DictionaryValue::SetString(const std::wstring& path,
431 const std::wstring& in_value) {
432 Set(path, CreateStringValue(in_value));
433}
434
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900435void DictionaryValue::SetStringFromUTF16(const std::wstring& path,
436 const string16& in_value) {
437 Set(path, CreateStringValueFromUTF16(in_value));
438}
439
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900440void DictionaryValue::SetWithoutPathExpansion(const std::wstring& key,
441 Value* in_value) {
initial.commit3f4a7322008-07-27 06:49:38 +0900442 // If there's an existing value here, we need to delete it, because
443 // we own all our children.
444 if (HasKey(key)) {
445 DCHECK(dictionary_[key] != in_value); // This would be bogus
446 delete dictionary_[key];
447 }
448
449 dictionary_[key] = in_value;
450}
451
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900452bool DictionaryValue::Get(const std::wstring& path, Value** out_value) const {
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900453 std::wstring current_path(path);
454 const DictionaryValue* current_dictionary = this;
455 for (size_t delimiter_position = current_path.find('.');
456 delimiter_position != std::wstring::npos;
457 delimiter_position = current_path.find('.')) {
pkasting@chromium.org8535dc22009-11-26 06:02:24 +0900458 DictionaryValue* child_dictionary = NULL;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900459 if (!current_dictionary->GetDictionary(
460 current_path.substr(0, delimiter_position), &child_dictionary))
461 return false;
initial.commit3f4a7322008-07-27 06:49:38 +0900462
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900463 current_dictionary = child_dictionary;
464 current_path.erase(0, delimiter_position + 1);
initial.commit3f4a7322008-07-27 06:49:38 +0900465 }
466
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900467 return current_dictionary->GetWithoutPathExpansion(current_path, out_value);
initial.commit3f4a7322008-07-27 06:49:38 +0900468}
469
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900470bool DictionaryValue::GetBoolean(const std::wstring& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900471 bool* bool_value) const {
472 Value* value;
473 if (!Get(path, &value))
474 return false;
475
476 return value->GetAsBoolean(bool_value);
477}
478
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900479bool DictionaryValue::GetInteger(const std::wstring& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900480 int* out_value) const {
481 Value* value;
482 if (!Get(path, &value))
483 return false;
484
485 return value->GetAsInteger(out_value);
486}
487
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900488bool DictionaryValue::GetReal(const std::wstring& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900489 double* out_value) const {
490 Value* value;
491 if (!Get(path, &value))
492 return false;
493
494 return value->GetAsReal(out_value);
495}
496
evan@chromium.orgd9ab8de2010-02-19 22:32:16 +0900497bool DictionaryValue::GetString(const std::string& path,
498 string16* out_value) const {
499 return GetStringAsUTF16(ASCIIToWide(path), out_value);
500}
501
502bool DictionaryValue::GetStringASCII(const std::string& path,
503 std::string* out_value) const {
504 std::string out;
505 if (!GetString(ASCIIToWide(path), &out))
506 return false;
507
508 if (!IsStringASCII(out)) {
509 NOTREACHED();
510 return false;
511 }
512
513 out_value->assign(out);
514 return true;
515}
516
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900517bool DictionaryValue::GetString(const std::wstring& path,
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900518 std::string* out_value) const {
519 Value* value;
520 if (!Get(path, &value))
521 return false;
522
523 return value->GetAsString(out_value);
524}
525
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900526bool DictionaryValue::GetString(const std::wstring& path,
527 std::wstring* out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900528 Value* value;
529 if (!Get(path, &value))
530 return false;
531
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900532 return value->GetAsString(out_value);
initial.commit3f4a7322008-07-27 06:49:38 +0900533}
534
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900535bool DictionaryValue::GetStringAsUTF16(const std::wstring& path,
536 string16* out_value) const {
537 Value* value;
538 if (!Get(path, &value))
539 return false;
540
541 return value->GetAsUTF16(out_value);
542}
543
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900544bool DictionaryValue::GetBinary(const std::wstring& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900545 BinaryValue** out_value) const {
546 Value* value;
547 bool result = Get(path, &value);
548 if (!result || !value->IsType(TYPE_BINARY))
549 return false;
550
551 if (out_value)
552 *out_value = static_cast<BinaryValue*>(value);
553
554 return true;
555}
556
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900557bool DictionaryValue::GetDictionary(const std::wstring& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900558 DictionaryValue** out_value) const {
559 Value* value;
560 bool result = Get(path, &value);
561 if (!result || !value->IsType(TYPE_DICTIONARY))
562 return false;
563
564 if (out_value)
565 *out_value = static_cast<DictionaryValue*>(value);
566
567 return true;
568}
569
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900570bool DictionaryValue::GetList(const std::wstring& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900571 ListValue** out_value) const {
572 Value* value;
573 bool result = Get(path, &value);
574 if (!result || !value->IsType(TYPE_LIST))
575 return false;
576
577 if (out_value)
578 *out_value = static_cast<ListValue*>(value);
579
580 return true;
581}
582
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900583bool DictionaryValue::GetWithoutPathExpansion(const std::wstring& key,
584 Value** out_value) const {
585 ValueMap::const_iterator entry_iterator = dictionary_.find(key);
586 if (entry_iterator == dictionary_.end())
587 return false;
initial.commit3f4a7322008-07-27 06:49:38 +0900588
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900589 Value* entry = entry_iterator->second;
590 if (out_value)
591 *out_value = entry;
592 return true;
593}
594
595bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::wstring& path,
596 int* out_value) const {
597 Value* value;
598 if (!GetWithoutPathExpansion(path, &value))
599 return false;
600
601 return value->GetAsInteger(out_value);
602}
603
604bool DictionaryValue::GetStringWithoutPathExpansion(
605 const std::wstring& path,
606 std::string* out_value) const {
607 Value* value;
608 if (!GetWithoutPathExpansion(path, &value))
609 return false;
610
611 return value->GetAsString(out_value);
612}
613
614bool DictionaryValue::GetStringWithoutPathExpansion(
615 const std::wstring& path,
616 std::wstring* out_value) const {
617 Value* value;
618 if (!GetWithoutPathExpansion(path, &value))
619 return false;
620
621 return value->GetAsString(out_value);
622}
623
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900624bool DictionaryValue::GetStringAsUTF16WithoutPathExpansion(
625 const std::wstring& path,
626 string16* out_value) const {
627 Value* value;
628 if (!GetWithoutPathExpansion(path, &value))
629 return false;
630
631 return value->GetAsUTF16(out_value);
632}
633
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900634bool DictionaryValue::GetDictionaryWithoutPathExpansion(
635 const std::wstring& path,
636 DictionaryValue** out_value) const {
637 Value* value;
638 bool result = GetWithoutPathExpansion(path, &value);
639 if (!result || !value->IsType(TYPE_DICTIONARY))
640 return false;
641
642 if (out_value)
643 *out_value = static_cast<DictionaryValue*>(value);
644
645 return true;
646}
647
648bool DictionaryValue::GetListWithoutPathExpansion(const std::wstring& path,
649 ListValue** out_value) const {
650 Value* value;
651 bool result = GetWithoutPathExpansion(path, &value);
652 if (!result || !value->IsType(TYPE_LIST))
653 return false;
654
655 if (out_value)
656 *out_value = static_cast<ListValue*>(value);
657
658 return true;
659}
660
661bool DictionaryValue::Remove(const std::wstring& path, Value** out_value) {
662 std::wstring current_path(path);
663 DictionaryValue* current_dictionary = this;
664 size_t delimiter_position = current_path.rfind('.');
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900665 if (delimiter_position != std::wstring::npos) {
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900666 if (!GetDictionary(current_path.substr(0, delimiter_position),
667 &current_dictionary))
668 return false;
669 current_path.erase(0, delimiter_position + 1);
initial.commit3f4a7322008-07-27 06:49:38 +0900670 }
671
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900672 return current_dictionary->RemoveWithoutPathExpansion(current_path,
673 out_value);
674}
675
676bool DictionaryValue::RemoveWithoutPathExpansion(const std::wstring& key,
677 Value** out_value) {
initial.commit3f4a7322008-07-27 06:49:38 +0900678 ValueMap::iterator entry_iterator = dictionary_.find(key);
679 if (entry_iterator == dictionary_.end())
680 return false;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900681
initial.commit3f4a7322008-07-27 06:49:38 +0900682 Value* entry = entry_iterator->second;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900683 if (out_value)
684 *out_value = entry;
685 else
686 delete entry;
687 dictionary_.erase(entry_iterator);
688 return true;
initial.commit3f4a7322008-07-27 06:49:38 +0900689}
690
tony@chromium.orge4948ab2009-12-02 09:20:32 +0900691DictionaryValue* DictionaryValue::DeepCopyWithoutEmptyChildren() {
692 Value* copy = CopyWithoutEmptyChildren(this);
693 return copy ? static_cast<DictionaryValue*>(copy) : new DictionaryValue;
initial.commit3f4a7322008-07-27 06:49:38 +0900694}
695
mnissler@chromium.org17cee0e2010-05-14 22:17:40 +0900696void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) {
697 for (DictionaryValue::key_iterator key(dictionary->begin_keys());
698 key != dictionary->end_keys(); ++key) {
699 Value* merge_value;
700 if (dictionary->GetWithoutPathExpansion(*key, &merge_value)) {
701 // Check whether we have to merge dictionaries.
702 if (merge_value->IsType(Value::TYPE_DICTIONARY)) {
703 DictionaryValue* sub_dict;
704 if (GetDictionaryWithoutPathExpansion(*key, &sub_dict)) {
705 sub_dict->MergeDictionary(
706 static_cast<const DictionaryValue*>(merge_value));
707 continue;
708 }
709 }
710 // All other cases: Make a copy and hook it up.
711 SetWithoutPathExpansion(*key, merge_value->DeepCopy());
712 }
713 }
714}
715
initial.commit3f4a7322008-07-27 06:49:38 +0900716///////////////////// ListValue ////////////////////
717
erg@chromium.org493f5f62010-07-16 06:03:54 +0900718ListValue::ListValue() : Value(TYPE_LIST) {
719}
720
initial.commit3f4a7322008-07-27 06:49:38 +0900721ListValue::~ListValue() {
722 Clear();
723}
724
725void ListValue::Clear() {
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900726 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i)
727 delete *i;
initial.commit3f4a7322008-07-27 06:49:38 +0900728 list_.clear();
729}
730
731bool ListValue::Set(size_t index, Value* in_value) {
732 if (!in_value)
733 return false;
734
735 if (index >= list_.size()) {
736 // Pad out any intermediate indexes with null settings
737 while (index > list_.size())
738 Append(CreateNullValue());
739 Append(in_value);
740 } else {
741 DCHECK(list_[index] != in_value);
742 delete list_[index];
743 list_[index] = in_value;
744 }
745 return true;
746}
747
748bool ListValue::Get(size_t index, Value** out_value) const {
749 if (index >= list_.size())
750 return false;
751
752 if (out_value)
753 *out_value = list_[index];
754
755 return true;
756}
757
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900758bool ListValue::GetBoolean(size_t index, bool* bool_value) const {
759 Value* value;
760 if (!Get(index, &value))
761 return false;
762
763 return value->GetAsBoolean(bool_value);
764}
765
766bool ListValue::GetInteger(size_t index, int* out_value) const {
767 Value* value;
768 if (!Get(index, &value))
769 return false;
770
771 return value->GetAsInteger(out_value);
772}
773
774bool ListValue::GetReal(size_t index, double* out_value) const {
775 Value* value;
776 if (!Get(index, &value))
777 return false;
778
779 return value->GetAsReal(out_value);
780}
781
782bool ListValue::GetString(size_t index, std::string* out_value) const {
783 Value* value;
784 if (!Get(index, &value))
785 return false;
786
787 return value->GetAsString(out_value);
788}
789
estade@chromium.org8f158c32009-12-18 11:39:16 +0900790bool ListValue::GetString(size_t index, std::wstring* out_value) const {
791 Value* value;
792 if (!Get(index, &value))
793 return false;
794
795 return value->GetAsString(out_value);
796}
797
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900798bool ListValue::GetStringAsUTF16(size_t index, string16* out_value) const {
799 Value* value;
800 if (!Get(index, &value))
801 return false;
802
803 return value->GetAsUTF16(out_value);
804}
805
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900806bool ListValue::GetBinary(size_t index, BinaryValue** out_value) const {
807 Value* value;
808 bool result = Get(index, &value);
809 if (!result || !value->IsType(TYPE_BINARY))
810 return false;
811
812 if (out_value)
813 *out_value = static_cast<BinaryValue*>(value);
814
815 return true;
816}
817
818bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900819 Value* value;
820 bool result = Get(index, &value);
821 if (!result || !value->IsType(TYPE_DICTIONARY))
822 return false;
823
824 if (out_value)
825 *out_value = static_cast<DictionaryValue*>(value);
826
827 return true;
828}
829
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900830bool ListValue::GetList(size_t index, ListValue** out_value) const {
831 Value* value;
832 bool result = Get(index, &value);
833 if (!result || !value->IsType(TYPE_LIST))
834 return false;
835
836 if (out_value)
837 *out_value = static_cast<ListValue*>(value);
838
839 return true;
840}
841
initial.commit3f4a7322008-07-27 06:49:38 +0900842bool ListValue::Remove(size_t index, Value** out_value) {
843 if (index >= list_.size())
844 return false;
845
846 if (out_value)
847 *out_value = list_[index];
848 else
849 delete list_[index];
850
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900851 list_.erase(list_.begin() + index);
initial.commit3f4a7322008-07-27 06:49:38 +0900852 return true;
853}
854
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900855int ListValue::Remove(const Value& value) {
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900856 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) {
857 if ((*i)->Equals(&value)) {
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900858 size_t index = i - list_.begin();
pkasting@chromium.orgdfe6a692009-12-01 04:59:11 +0900859 delete *i;
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900860 list_.erase(i);
robertshield@chromium.org9fb9e372010-03-23 05:12:50 +0900861
862 // TODO(anyone): Returning a signed int type here is just wrong.
863 // Change this interface to return a size_t.
864 DCHECK(index <= INT_MAX);
865 int return_index = static_cast<int>(index);
866 return return_index;
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900867 }
868 }
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900869 return -1;
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900870}
871
initial.commit3f4a7322008-07-27 06:49:38 +0900872void ListValue::Append(Value* in_value) {
873 DCHECK(in_value);
874 list_.push_back(in_value);
875}
876
zork@chromium.orgb5f742b2010-04-13 06:48:10 +0900877bool ListValue::AppendIfNotPresent(Value* in_value) {
878 DCHECK(in_value);
ziadh@chromium.org5c7f6312010-07-19 17:00:42 +0900879 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i) {
zork@chromium.orgb5f742b2010-04-13 06:48:10 +0900880 if ((*i)->Equals(in_value))
881 return false;
882 }
883 list_.push_back(in_value);
884 return true;
885}
886
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900887bool ListValue::Insert(size_t index, Value* in_value) {
888 DCHECK(in_value);
jhawkins@chromium.org33edb6b2009-10-01 06:36:37 +0900889 if (index > list_.size())
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900890 return false;
891
892 list_.insert(list_.begin() + index, in_value);
893 return true;
894}
895
initial.commit3f4a7322008-07-27 06:49:38 +0900896Value* ListValue::DeepCopy() const {
897 ListValue* result = new ListValue;
898
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900899 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i)
900 result->Append((*i)->DeepCopy());
initial.commit3f4a7322008-07-27 06:49:38 +0900901
902 return result;
903}
904
905bool ListValue::Equals(const Value* other) const {
906 if (other->GetType() != GetType())
907 return false;
908
909 const ListValue* other_list =
910 static_cast<const ListValue*>(other);
911 const_iterator lhs_it, rhs_it;
912 for (lhs_it = begin(), rhs_it = other_list->begin();
913 lhs_it != end() && rhs_it != other_list->end();
914 ++lhs_it, ++rhs_it) {
915 if (!(*lhs_it)->Equals(*rhs_it))
916 return false;
917 }
918 if (lhs_it != end() || rhs_it != other_list->end())
919 return false;
920
921 return true;
922}
erg@chromium.org493f5f62010-07-16 06:03:54 +0900923
924ValueSerializer::~ValueSerializer() {
925}