• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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                        &current_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