1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/values.h"
6
7 #include "base/logging.h"
8 #include "base/string_util.h"
9 #include "base/utf_string_conversions.h"
10
11 namespace {
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.
CopyWithoutEmptyChildren(Value * node)16 Value* 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
61
62 ///////////////////// Value ////////////////////
63
~Value()64 Value::~Value() {
65 }
66
67 // static
CreateNullValue()68 Value* Value::CreateNullValue() {
69 return new Value(TYPE_NULL);
70 }
71
72 // static
CreateBooleanValue(bool in_value)73 Value* Value::CreateBooleanValue(bool in_value) {
74 return new FundamentalValue(in_value);
75 }
76
77 // static
CreateIntegerValue(int in_value)78 Value* Value::CreateIntegerValue(int in_value) {
79 return new FundamentalValue(in_value);
80 }
81
82 // static
CreateRealValue(double in_value)83 Value* Value::CreateRealValue(double in_value) {
84 return new FundamentalValue(in_value);
85 }
86
87 // static
CreateStringValue(const std::string & in_value)88 Value* Value::CreateStringValue(const std::string& in_value) {
89 return new StringValue(in_value);
90 }
91
92 // static
CreateStringValue(const std::wstring & in_value)93 Value* Value::CreateStringValue(const std::wstring& in_value) {
94 return new StringValue(in_value);
95 }
96
97 // static
CreateStringValueFromUTF16(const string16 & in_value)98 Value* Value::CreateStringValueFromUTF16(const string16& in_value) {
99 return new StringValue(in_value);
100 }
101
102 // static
CreateBinaryValue(char * buffer,size_t size)103 BinaryValue* Value::CreateBinaryValue(char* buffer, size_t size) {
104 return BinaryValue::Create(buffer, size);
105 }
106
GetAsBoolean(bool * in_value) const107 bool Value::GetAsBoolean(bool* in_value) const {
108 return false;
109 }
110
GetAsInteger(int * in_value) const111 bool Value::GetAsInteger(int* in_value) const {
112 return false;
113 }
114
GetAsReal(double * in_value) const115 bool Value::GetAsReal(double* in_value) const {
116 return false;
117 }
118
GetAsString(std::string * in_value) const119 bool Value::GetAsString(std::string* in_value) const {
120 return false;
121 }
122
GetAsString(std::wstring * in_value) const123 bool Value::GetAsString(std::wstring* in_value) const {
124 return false;
125 }
126
GetAsUTF16(string16 * out_value) const127 bool Value::GetAsUTF16(string16* out_value) const {
128 return false;
129 }
130
DeepCopy() const131 Value* 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
Equals(const Value * other) const138 bool 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
145 ///////////////////// FundamentalValue ////////////////////
146
~FundamentalValue()147 FundamentalValue::~FundamentalValue() {
148 }
149
GetAsBoolean(bool * out_value) const150 bool FundamentalValue::GetAsBoolean(bool* out_value) const {
151 if (out_value && IsType(TYPE_BOOLEAN))
152 *out_value = boolean_value_;
153 return (IsType(TYPE_BOOLEAN));
154 }
155
GetAsInteger(int * out_value) const156 bool FundamentalValue::GetAsInteger(int* out_value) const {
157 if (out_value && IsType(TYPE_INTEGER))
158 *out_value = integer_value_;
159 return (IsType(TYPE_INTEGER));
160 }
161
GetAsReal(double * out_value) const162 bool FundamentalValue::GetAsReal(double* out_value) const {
163 if (out_value && IsType(TYPE_REAL))
164 *out_value = real_value_;
165 return (IsType(TYPE_REAL));
166 }
167
DeepCopy() const168 Value* FundamentalValue::DeepCopy() const {
169 switch (GetType()) {
170 case TYPE_BOOLEAN:
171 return CreateBooleanValue(boolean_value_);
172
173 case TYPE_INTEGER:
174 return CreateIntegerValue(integer_value_);
175
176 case TYPE_REAL:
177 return CreateRealValue(real_value_);
178
179 default:
180 NOTREACHED();
181 return NULL;
182 }
183 }
184
Equals(const Value * other) const185 bool FundamentalValue::Equals(const Value* other) const {
186 if (other->GetType() != GetType())
187 return false;
188
189 switch (GetType()) {
190 case TYPE_BOOLEAN: {
191 bool lhs, rhs;
192 return GetAsBoolean(&lhs) && other->GetAsBoolean(&rhs) && lhs == rhs;
193 }
194 case TYPE_INTEGER: {
195 int lhs, rhs;
196 return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs;
197 }
198 case TYPE_REAL: {
199 double lhs, rhs;
200 return GetAsReal(&lhs) && other->GetAsReal(&rhs) && lhs == rhs;
201 }
202 default:
203 NOTREACHED();
204 return false;
205 }
206 }
207
208 ///////////////////// StringValue ////////////////////
209
StringValue(const std::string & in_value)210 StringValue::StringValue(const std::string& in_value)
211 : Value(TYPE_STRING),
212 value_(in_value) {
213 DCHECK(IsStringUTF8(in_value));
214 }
215
StringValue(const std::wstring & in_value)216 StringValue::StringValue(const std::wstring& in_value)
217 : Value(TYPE_STRING),
218 value_(WideToUTF8(in_value)) {
219 }
220
221 #if !defined(WCHAR_T_IS_UTF16)
StringValue(const string16 & in_value)222 StringValue::StringValue(const string16& in_value)
223 : Value(TYPE_STRING),
224 value_(UTF16ToUTF8(in_value)) {
225 }
226 #endif
227
~StringValue()228 StringValue::~StringValue() {
229 }
230
GetAsString(std::string * out_value) const231 bool StringValue::GetAsString(std::string* out_value) const {
232 if (out_value)
233 *out_value = value_;
234 return true;
235 }
236
GetAsString(std::wstring * out_value) const237 bool StringValue::GetAsString(std::wstring* out_value) const {
238 if (out_value)
239 *out_value = UTF8ToWide(value_);
240 return true;
241 }
242
GetAsUTF16(string16 * out_value) const243 bool StringValue::GetAsUTF16(string16* out_value) const {
244 if (out_value)
245 *out_value = UTF8ToUTF16(value_);
246 return true;
247 }
248
DeepCopy() const249 Value* StringValue::DeepCopy() const {
250 return CreateStringValue(value_);
251 }
252
Equals(const Value * other) const253 bool StringValue::Equals(const Value* other) const {
254 if (other->GetType() != GetType())
255 return false;
256 std::string lhs, rhs;
257 return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs;
258 }
259
260 ///////////////////// BinaryValue ////////////////////
261
262 // static
Create(char * buffer,size_t size)263 BinaryValue* BinaryValue::Create(char* buffer, size_t size) {
264 if (!buffer)
265 return NULL;
266
267 return new BinaryValue(buffer, size);
268 }
269
270 // static
CreateWithCopiedBuffer(const char * buffer,size_t size)271 BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer,
272 size_t size) {
273 if (!buffer)
274 return NULL;
275
276 char* buffer_copy = new char[size];
277 memcpy(buffer_copy, buffer, size);
278 return new BinaryValue(buffer_copy, size);
279 }
280
281
BinaryValue(char * buffer,size_t size)282 BinaryValue::BinaryValue(char* buffer, size_t size)
283 : Value(TYPE_BINARY),
284 buffer_(buffer),
285 size_(size) {
286 DCHECK(buffer_);
287 }
288
~BinaryValue()289 BinaryValue::~BinaryValue() {
290 DCHECK(buffer_);
291 if (buffer_)
292 delete[] buffer_;
293 }
294
DeepCopy() const295 Value* BinaryValue::DeepCopy() const {
296 return CreateWithCopiedBuffer(buffer_, size_);
297 }
298
Equals(const Value * other) const299 bool BinaryValue::Equals(const Value* other) const {
300 if (other->GetType() != GetType())
301 return false;
302 const BinaryValue* other_binary = static_cast<const BinaryValue*>(other);
303 if (other_binary->size_ != size_)
304 return false;
305 return !memcmp(buffer_, other_binary->buffer_, size_);
306 }
307
308 ///////////////////// DictionaryValue ////////////////////
309
~DictionaryValue()310 DictionaryValue::~DictionaryValue() {
311 Clear();
312 }
313
DeepCopy() const314 Value* DictionaryValue::DeepCopy() const {
315 DictionaryValue* result = new DictionaryValue;
316
317 for (ValueMap::const_iterator current_entry(dictionary_.begin());
318 current_entry != dictionary_.end(); ++current_entry) {
319 result->SetWithoutPathExpansion(current_entry->first,
320 current_entry->second->DeepCopy());
321 }
322
323 return result;
324 }
325
Equals(const Value * other) const326 bool DictionaryValue::Equals(const Value* other) const {
327 if (other->GetType() != GetType())
328 return false;
329
330 const DictionaryValue* other_dict =
331 static_cast<const DictionaryValue*>(other);
332 key_iterator lhs_it(begin_keys());
333 key_iterator rhs_it(other_dict->begin_keys());
334 while (lhs_it != end_keys() && rhs_it != other_dict->end_keys()) {
335 Value* lhs;
336 Value* rhs;
337 if (!GetWithoutPathExpansion(*lhs_it, &lhs) ||
338 !other_dict->GetWithoutPathExpansion(*rhs_it, &rhs) ||
339 !lhs->Equals(rhs)) {
340 return false;
341 }
342 ++lhs_it;
343 ++rhs_it;
344 }
345 if (lhs_it != end_keys() || rhs_it != other_dict->end_keys())
346 return false;
347
348 return true;
349 }
350
HasKey(const std::wstring & key) const351 bool DictionaryValue::HasKey(const std::wstring& key) const {
352 ValueMap::const_iterator current_entry = dictionary_.find(key);
353 DCHECK((current_entry == dictionary_.end()) || current_entry->second);
354 return current_entry != dictionary_.end();
355 }
356
Clear()357 void DictionaryValue::Clear() {
358 ValueMap::iterator dict_iterator = dictionary_.begin();
359 while (dict_iterator != dictionary_.end()) {
360 delete dict_iterator->second;
361 ++dict_iterator;
362 }
363
364 dictionary_.clear();
365 }
366
Set(const std::wstring & path,Value * in_value)367 void DictionaryValue::Set(const std::wstring& path, Value* in_value) {
368 DCHECK(in_value);
369
370 std::wstring current_path(path);
371 DictionaryValue* current_dictionary = this;
372 for (size_t delimiter_position = current_path.find('.');
373 delimiter_position != std::wstring::npos;
374 delimiter_position = current_path.find('.')) {
375 // Assume that we're indexing into a dictionary.
376 std::wstring key(current_path, 0, delimiter_position);
377 DictionaryValue* child_dictionary = NULL;
378 if (!current_dictionary->GetDictionary(key, &child_dictionary)) {
379 child_dictionary = new DictionaryValue;
380 current_dictionary->SetWithoutPathExpansion(key, child_dictionary);
381 }
382
383 current_dictionary = child_dictionary;
384 current_path.erase(0, delimiter_position + 1);
385 }
386
387 current_dictionary->SetWithoutPathExpansion(current_path, in_value);
388 }
389
SetBoolean(const std::wstring & path,bool in_value)390 void DictionaryValue::SetBoolean(const std::wstring& path, bool in_value) {
391 Set(path, CreateBooleanValue(in_value));
392 }
393
SetInteger(const std::wstring & path,int in_value)394 void DictionaryValue::SetInteger(const std::wstring& path, int in_value) {
395 Set(path, CreateIntegerValue(in_value));
396 }
397
SetReal(const std::wstring & path,double in_value)398 void DictionaryValue::SetReal(const std::wstring& path, double in_value) {
399 Set(path, CreateRealValue(in_value));
400 }
401
SetString(const std::wstring & path,const std::string & in_value)402 void DictionaryValue::SetString(const std::wstring& path,
403 const std::string& in_value) {
404 Set(path, CreateStringValue(in_value));
405 }
406
SetString(const std::wstring & path,const std::wstring & in_value)407 void DictionaryValue::SetString(const std::wstring& path,
408 const std::wstring& in_value) {
409 Set(path, CreateStringValue(in_value));
410 }
411
SetStringFromUTF16(const std::wstring & path,const string16 & in_value)412 void DictionaryValue::SetStringFromUTF16(const std::wstring& path,
413 const string16& in_value) {
414 Set(path, CreateStringValueFromUTF16(in_value));
415 }
416
SetWithoutPathExpansion(const std::wstring & key,Value * in_value)417 void DictionaryValue::SetWithoutPathExpansion(const std::wstring& key,
418 Value* in_value) {
419 // If there's an existing value here, we need to delete it, because
420 // we own all our children.
421 if (HasKey(key)) {
422 DCHECK(dictionary_[key] != in_value); // This would be bogus
423 delete dictionary_[key];
424 }
425
426 dictionary_[key] = in_value;
427 }
428
Get(const std::wstring & path,Value ** out_value) const429 bool DictionaryValue::Get(const std::wstring& path, Value** out_value) const {
430 std::wstring current_path(path);
431 const DictionaryValue* current_dictionary = this;
432 for (size_t delimiter_position = current_path.find('.');
433 delimiter_position != std::wstring::npos;
434 delimiter_position = current_path.find('.')) {
435 DictionaryValue* child_dictionary = NULL;
436 if (!current_dictionary->GetDictionary(
437 current_path.substr(0, delimiter_position), &child_dictionary))
438 return false;
439
440 current_dictionary = child_dictionary;
441 current_path.erase(0, delimiter_position + 1);
442 }
443
444 return current_dictionary->GetWithoutPathExpansion(current_path, out_value);
445 }
446
GetBoolean(const std::wstring & path,bool * bool_value) const447 bool DictionaryValue::GetBoolean(const std::wstring& path,
448 bool* bool_value) const {
449 Value* value;
450 if (!Get(path, &value))
451 return false;
452
453 return value->GetAsBoolean(bool_value);
454 }
455
GetInteger(const std::wstring & path,int * out_value) const456 bool DictionaryValue::GetInteger(const std::wstring& path,
457 int* out_value) const {
458 Value* value;
459 if (!Get(path, &value))
460 return false;
461
462 return value->GetAsInteger(out_value);
463 }
464
GetReal(const std::wstring & path,double * out_value) const465 bool DictionaryValue::GetReal(const std::wstring& path,
466 double* out_value) const {
467 Value* value;
468 if (!Get(path, &value))
469 return false;
470
471 return value->GetAsReal(out_value);
472 }
473
GetString(const std::wstring & path,std::string * out_value) const474 bool DictionaryValue::GetString(const std::wstring& path,
475 std::string* out_value) const {
476 Value* value;
477 if (!Get(path, &value))
478 return false;
479
480 return value->GetAsString(out_value);
481 }
482
GetString(const std::wstring & path,std::wstring * out_value) const483 bool DictionaryValue::GetString(const std::wstring& path,
484 std::wstring* out_value) const {
485 Value* value;
486 if (!Get(path, &value))
487 return false;
488
489 return value->GetAsString(out_value);
490 }
491
GetStringAsUTF16(const std::wstring & path,string16 * out_value) const492 bool DictionaryValue::GetStringAsUTF16(const std::wstring& path,
493 string16* out_value) const {
494 Value* value;
495 if (!Get(path, &value))
496 return false;
497
498 return value->GetAsUTF16(out_value);
499 }
500
GetBinary(const std::wstring & path,BinaryValue ** out_value) const501 bool DictionaryValue::GetBinary(const std::wstring& path,
502 BinaryValue** out_value) const {
503 Value* value;
504 bool result = Get(path, &value);
505 if (!result || !value->IsType(TYPE_BINARY))
506 return false;
507
508 if (out_value)
509 *out_value = static_cast<BinaryValue*>(value);
510
511 return true;
512 }
513
GetDictionary(const std::wstring & path,DictionaryValue ** out_value) const514 bool DictionaryValue::GetDictionary(const std::wstring& path,
515 DictionaryValue** out_value) const {
516 Value* value;
517 bool result = Get(path, &value);
518 if (!result || !value->IsType(TYPE_DICTIONARY))
519 return false;
520
521 if (out_value)
522 *out_value = static_cast<DictionaryValue*>(value);
523
524 return true;
525 }
526
GetList(const std::wstring & path,ListValue ** out_value) const527 bool DictionaryValue::GetList(const std::wstring& path,
528 ListValue** out_value) const {
529 Value* value;
530 bool result = Get(path, &value);
531 if (!result || !value->IsType(TYPE_LIST))
532 return false;
533
534 if (out_value)
535 *out_value = static_cast<ListValue*>(value);
536
537 return true;
538 }
539
GetWithoutPathExpansion(const std::wstring & key,Value ** out_value) const540 bool DictionaryValue::GetWithoutPathExpansion(const std::wstring& key,
541 Value** out_value) const {
542 ValueMap::const_iterator entry_iterator = dictionary_.find(key);
543 if (entry_iterator == dictionary_.end())
544 return false;
545
546 Value* entry = entry_iterator->second;
547 if (out_value)
548 *out_value = entry;
549 return true;
550 }
551
GetIntegerWithoutPathExpansion(const std::wstring & path,int * out_value) const552 bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::wstring& path,
553 int* out_value) const {
554 Value* value;
555 if (!GetWithoutPathExpansion(path, &value))
556 return false;
557
558 return value->GetAsInteger(out_value);
559 }
560
GetStringWithoutPathExpansion(const std::wstring & path,std::string * out_value) const561 bool DictionaryValue::GetStringWithoutPathExpansion(
562 const std::wstring& path,
563 std::string* out_value) const {
564 Value* value;
565 if (!GetWithoutPathExpansion(path, &value))
566 return false;
567
568 return value->GetAsString(out_value);
569 }
570
GetStringWithoutPathExpansion(const std::wstring & path,std::wstring * out_value) const571 bool DictionaryValue::GetStringWithoutPathExpansion(
572 const std::wstring& path,
573 std::wstring* out_value) const {
574 Value* value;
575 if (!GetWithoutPathExpansion(path, &value))
576 return false;
577
578 return value->GetAsString(out_value);
579 }
580
GetStringAsUTF16WithoutPathExpansion(const std::wstring & path,string16 * out_value) const581 bool DictionaryValue::GetStringAsUTF16WithoutPathExpansion(
582 const std::wstring& path,
583 string16* out_value) const {
584 Value* value;
585 if (!GetWithoutPathExpansion(path, &value))
586 return false;
587
588 return value->GetAsUTF16(out_value);
589 }
590
GetDictionaryWithoutPathExpansion(const std::wstring & path,DictionaryValue ** out_value) const591 bool DictionaryValue::GetDictionaryWithoutPathExpansion(
592 const std::wstring& path,
593 DictionaryValue** out_value) const {
594 Value* value;
595 bool result = GetWithoutPathExpansion(path, &value);
596 if (!result || !value->IsType(TYPE_DICTIONARY))
597 return false;
598
599 if (out_value)
600 *out_value = static_cast<DictionaryValue*>(value);
601
602 return true;
603 }
604
GetListWithoutPathExpansion(const std::wstring & path,ListValue ** out_value) const605 bool DictionaryValue::GetListWithoutPathExpansion(const std::wstring& path,
606 ListValue** out_value) const {
607 Value* value;
608 bool result = GetWithoutPathExpansion(path, &value);
609 if (!result || !value->IsType(TYPE_LIST))
610 return false;
611
612 if (out_value)
613 *out_value = static_cast<ListValue*>(value);
614
615 return true;
616 }
617
Remove(const std::wstring & path,Value ** out_value)618 bool DictionaryValue::Remove(const std::wstring& path, Value** out_value) {
619 std::wstring current_path(path);
620 DictionaryValue* current_dictionary = this;
621 size_t delimiter_position = current_path.rfind('.');
622 if (delimiter_position != std::wstring::npos) {
623 if (!GetDictionary(current_path.substr(0, delimiter_position),
624 ¤t_dictionary))
625 return false;
626 current_path.erase(0, delimiter_position + 1);
627 }
628
629 return current_dictionary->RemoveWithoutPathExpansion(current_path,
630 out_value);
631 }
632
RemoveWithoutPathExpansion(const std::wstring & key,Value ** out_value)633 bool DictionaryValue::RemoveWithoutPathExpansion(const std::wstring& key,
634 Value** out_value) {
635 ValueMap::iterator entry_iterator = dictionary_.find(key);
636 if (entry_iterator == dictionary_.end())
637 return false;
638
639 Value* entry = entry_iterator->second;
640 if (out_value)
641 *out_value = entry;
642 else
643 delete entry;
644 dictionary_.erase(entry_iterator);
645 return true;
646 }
647
DeepCopyWithoutEmptyChildren()648 DictionaryValue* DictionaryValue::DeepCopyWithoutEmptyChildren() {
649 Value* copy = CopyWithoutEmptyChildren(this);
650 return copy ? static_cast<DictionaryValue*>(copy) : new DictionaryValue;
651 }
652
653 ///////////////////// ListValue ////////////////////
654
~ListValue()655 ListValue::~ListValue() {
656 Clear();
657 }
658
Clear()659 void ListValue::Clear() {
660 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i)
661 delete *i;
662 list_.clear();
663 }
664
Set(size_t index,Value * in_value)665 bool ListValue::Set(size_t index, Value* in_value) {
666 if (!in_value)
667 return false;
668
669 if (index >= list_.size()) {
670 // Pad out any intermediate indexes with null settings
671 while (index > list_.size())
672 Append(CreateNullValue());
673 Append(in_value);
674 } else {
675 DCHECK(list_[index] != in_value);
676 delete list_[index];
677 list_[index] = in_value;
678 }
679 return true;
680 }
681
Get(size_t index,Value ** out_value) const682 bool ListValue::Get(size_t index, Value** out_value) const {
683 if (index >= list_.size())
684 return false;
685
686 if (out_value)
687 *out_value = list_[index];
688
689 return true;
690 }
691
GetBoolean(size_t index,bool * bool_value) const692 bool ListValue::GetBoolean(size_t index, bool* bool_value) const {
693 Value* value;
694 if (!Get(index, &value))
695 return false;
696
697 return value->GetAsBoolean(bool_value);
698 }
699
GetInteger(size_t index,int * out_value) const700 bool ListValue::GetInteger(size_t index, int* out_value) const {
701 Value* value;
702 if (!Get(index, &value))
703 return false;
704
705 return value->GetAsInteger(out_value);
706 }
707
GetReal(size_t index,double * out_value) const708 bool ListValue::GetReal(size_t index, double* out_value) const {
709 Value* value;
710 if (!Get(index, &value))
711 return false;
712
713 return value->GetAsReal(out_value);
714 }
715
GetString(size_t index,std::string * out_value) const716 bool ListValue::GetString(size_t index, std::string* out_value) const {
717 Value* value;
718 if (!Get(index, &value))
719 return false;
720
721 return value->GetAsString(out_value);
722 }
723
GetString(size_t index,std::wstring * out_value) const724 bool ListValue::GetString(size_t index, std::wstring* out_value) const {
725 Value* value;
726 if (!Get(index, &value))
727 return false;
728
729 return value->GetAsString(out_value);
730 }
731
GetStringAsUTF16(size_t index,string16 * out_value) const732 bool ListValue::GetStringAsUTF16(size_t index, string16* out_value) const {
733 Value* value;
734 if (!Get(index, &value))
735 return false;
736
737 return value->GetAsUTF16(out_value);
738 }
739
GetBinary(size_t index,BinaryValue ** out_value) const740 bool ListValue::GetBinary(size_t index, BinaryValue** out_value) const {
741 Value* value;
742 bool result = Get(index, &value);
743 if (!result || !value->IsType(TYPE_BINARY))
744 return false;
745
746 if (out_value)
747 *out_value = static_cast<BinaryValue*>(value);
748
749 return true;
750 }
751
GetDictionary(size_t index,DictionaryValue ** out_value) const752 bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) const {
753 Value* value;
754 bool result = Get(index, &value);
755 if (!result || !value->IsType(TYPE_DICTIONARY))
756 return false;
757
758 if (out_value)
759 *out_value = static_cast<DictionaryValue*>(value);
760
761 return true;
762 }
763
GetList(size_t index,ListValue ** out_value) const764 bool ListValue::GetList(size_t index, ListValue** out_value) const {
765 Value* value;
766 bool result = Get(index, &value);
767 if (!result || !value->IsType(TYPE_LIST))
768 return false;
769
770 if (out_value)
771 *out_value = static_cast<ListValue*>(value);
772
773 return true;
774 }
775
Remove(size_t index,Value ** out_value)776 bool ListValue::Remove(size_t index, Value** out_value) {
777 if (index >= list_.size())
778 return false;
779
780 if (out_value)
781 *out_value = list_[index];
782 else
783 delete list_[index];
784
785 list_.erase(list_.begin() + index);
786 return true;
787 }
788
Remove(const Value & value)789 int ListValue::Remove(const Value& value) {
790 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) {
791 if ((*i)->Equals(&value)) {
792 size_t index = i - list_.begin();
793 delete *i;
794 list_.erase(i);
795 return index;
796 }
797 }
798 return -1;
799 }
800
Append(Value * in_value)801 void ListValue::Append(Value* in_value) {
802 DCHECK(in_value);
803 list_.push_back(in_value);
804 }
805
Insert(size_t index,Value * in_value)806 bool ListValue::Insert(size_t index, Value* in_value) {
807 DCHECK(in_value);
808 if (index > list_.size())
809 return false;
810
811 list_.insert(list_.begin() + index, in_value);
812 return true;
813 }
814
DeepCopy() const815 Value* ListValue::DeepCopy() const {
816 ListValue* result = new ListValue;
817
818 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i)
819 result->Append((*i)->DeepCopy());
820
821 return result;
822 }
823
Equals(const Value * other) const824 bool ListValue::Equals(const Value* other) const {
825 if (other->GetType() != GetType())
826 return false;
827
828 const ListValue* other_list =
829 static_cast<const ListValue*>(other);
830 const_iterator lhs_it, rhs_it;
831 for (lhs_it = begin(), rhs_it = other_list->begin();
832 lhs_it != end() && rhs_it != other_list->end();
833 ++lhs_it, ++rhs_it) {
834 if (!(*lhs_it)->Equals(*rhs_it))
835 return false;
836 }
837 if (lhs_it != end() || rhs_it != other_list->end())
838 return false;
839
840 return true;
841 }
842