• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 FundamentalValue* Value::CreateBooleanValue(bool in_value) {
74   return new FundamentalValue(in_value);
75 }
76 
77 // static
CreateIntegerValue(int in_value)78 FundamentalValue* Value::CreateIntegerValue(int in_value) {
79   return new FundamentalValue(in_value);
80 }
81 
82 // static
CreateDoubleValue(double in_value)83 FundamentalValue* Value::CreateDoubleValue(double in_value) {
84   return new FundamentalValue(in_value);
85 }
86 
87 // static
CreateStringValue(const std::string & in_value)88 StringValue* Value::CreateStringValue(const std::string& in_value) {
89   return new StringValue(in_value);
90 }
91 
92 // static
CreateStringValue(const string16 & in_value)93 StringValue* Value::CreateStringValue(const string16& in_value) {
94   return new StringValue(in_value);
95 }
96 
97 // static
CreateBinaryValue(char * buffer,size_t size)98 BinaryValue* Value::CreateBinaryValue(char* buffer, size_t size) {
99   return BinaryValue::Create(buffer, size);
100 }
101 
GetAsBoolean(bool * out_value) const102 bool Value::GetAsBoolean(bool* out_value) const {
103   return false;
104 }
105 
GetAsInteger(int * out_value) const106 bool Value::GetAsInteger(int* out_value) const {
107   return false;
108 }
109 
GetAsDouble(double * out_value) const110 bool Value::GetAsDouble(double* out_value) const {
111   return false;
112 }
113 
GetAsString(std::string * out_value) const114 bool Value::GetAsString(std::string* out_value) const {
115   return false;
116 }
117 
GetAsString(string16 * out_value) const118 bool Value::GetAsString(string16* out_value) const {
119   return false;
120 }
121 
GetAsList(ListValue ** out_value)122 bool Value::GetAsList(ListValue** out_value) {
123   return false;
124 }
125 
DeepCopy() const126 Value* 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 
Equals(const Value * other) const133 bool 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 
140 // static
Equals(const Value * a,const Value * b)141 bool 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 
Value(ValueType type)147 Value::Value(ValueType type) : type_(type) {
148 }
149 
150 ///////////////////// FundamentalValue ////////////////////
151 
FundamentalValue(bool in_value)152 FundamentalValue::FundamentalValue(bool in_value)
153     : Value(TYPE_BOOLEAN), boolean_value_(in_value) {
154 }
155 
FundamentalValue(int in_value)156 FundamentalValue::FundamentalValue(int in_value)
157     : Value(TYPE_INTEGER), integer_value_(in_value) {
158 }
159 
FundamentalValue(double in_value)160 FundamentalValue::FundamentalValue(double in_value)
161     : Value(TYPE_DOUBLE), double_value_(in_value) {
162 }
163 
~FundamentalValue()164 FundamentalValue::~FundamentalValue() {
165 }
166 
GetAsBoolean(bool * out_value) const167 bool 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 
GetAsInteger(int * out_value) const173 bool 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 
GetAsDouble(double * out_value) const179 bool FundamentalValue::GetAsDouble(double* out_value) const {
180   if (out_value && IsType(TYPE_DOUBLE))
181     *out_value = double_value_;
182   return (IsType(TYPE_DOUBLE));
183 }
184 
DeepCopy() const185 FundamentalValue* FundamentalValue::DeepCopy() const {
186   switch (GetType()) {
187     case TYPE_BOOLEAN:
188       return CreateBooleanValue(boolean_value_);
189 
190     case TYPE_INTEGER:
191       return CreateIntegerValue(integer_value_);
192 
193     case TYPE_DOUBLE:
194       return CreateDoubleValue(double_value_);
195 
196     default:
197       NOTREACHED();
198       return NULL;
199   }
200 }
201 
Equals(const Value * other) const202 bool 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     }
215     case TYPE_DOUBLE: {
216       double lhs, rhs;
217       return GetAsDouble(&lhs) && other->GetAsDouble(&rhs) && lhs == rhs;
218     }
219     default:
220       NOTREACHED();
221       return false;
222   }
223 }
224 
225 ///////////////////// StringValue ////////////////////
226 
StringValue(const std::string & in_value)227 StringValue::StringValue(const std::string& in_value)
228     : Value(TYPE_STRING),
229       value_(in_value) {
230   DCHECK(IsStringUTF8(in_value));
231 }
232 
StringValue(const string16 & in_value)233 StringValue::StringValue(const string16& in_value)
234     : Value(TYPE_STRING),
235       value_(UTF16ToUTF8(in_value)) {
236 }
237 
~StringValue()238 StringValue::~StringValue() {
239 }
240 
GetAsString(std::string * out_value) const241 bool StringValue::GetAsString(std::string* out_value) const {
242   if (out_value)
243     *out_value = value_;
244   return true;
245 }
246 
GetAsString(string16 * out_value) const247 bool StringValue::GetAsString(string16* out_value) const {
248   if (out_value)
249     *out_value = UTF8ToUTF16(value_);
250   return true;
251 }
252 
DeepCopy() const253 StringValue* StringValue::DeepCopy() const {
254   return CreateStringValue(value_);
255 }
256 
Equals(const Value * other) const257 bool StringValue::Equals(const Value* other) const {
258   if (other->GetType() != GetType())
259     return false;
260   std::string lhs, rhs;
261   return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs;
262 }
263 
264 ///////////////////// BinaryValue ////////////////////
265 
~BinaryValue()266 BinaryValue::~BinaryValue() {
267   DCHECK(buffer_);
268   if (buffer_)
269     delete[] buffer_;
270 }
271 
272 // static
Create(char * buffer,size_t size)273 BinaryValue* BinaryValue::Create(char* buffer, size_t size) {
274   if (!buffer)
275     return NULL;
276 
277   return new BinaryValue(buffer, size);
278 }
279 
280 // static
CreateWithCopiedBuffer(const char * buffer,size_t size)281 BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer,
282                                                  size_t size) {
283   if (!buffer)
284     return NULL;
285 
286   char* buffer_copy = new char[size];
287   memcpy(buffer_copy, buffer, size);
288   return new BinaryValue(buffer_copy, size);
289 }
290 
DeepCopy() const291 BinaryValue* BinaryValue::DeepCopy() const {
292   return CreateWithCopiedBuffer(buffer_, size_);
293 }
294 
Equals(const Value * other) const295 bool 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 
BinaryValue(char * buffer,size_t size)304 BinaryValue::BinaryValue(char* buffer, size_t size)
305   : Value(TYPE_BINARY),
306     buffer_(buffer),
307     size_(size) {
308   DCHECK(buffer_);
309 }
310 
311 ///////////////////// DictionaryValue ////////////////////
312 
DictionaryValue()313 DictionaryValue::DictionaryValue()
314     : Value(TYPE_DICTIONARY) {
315 }
316 
~DictionaryValue()317 DictionaryValue::~DictionaryValue() {
318   Clear();
319 }
320 
HasKey(const std::string & key) const321 bool DictionaryValue::HasKey(const std::string& key) const {
322   DCHECK(IsStringUTF8(key));
323   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 
Clear()328 void 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 
Set(const std::string & path,Value * in_value)338 void DictionaryValue::Set(const std::string& path, Value* in_value) {
339   DCHECK(IsStringUTF8(path));
340   DCHECK(in_value);
341 
342   std::string current_path(path);
343   DictionaryValue* current_dictionary = this;
344   for (size_t delimiter_position = current_path.find('.');
345        delimiter_position != std::string::npos;
346        delimiter_position = current_path.find('.')) {
347     // Assume that we're indexing into a dictionary.
348     std::string key(current_path, 0, delimiter_position);
349     DictionaryValue* child_dictionary = NULL;
350     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 
SetBoolean(const std::string & path,bool in_value)362 void DictionaryValue::SetBoolean(const std::string& path, bool in_value) {
363   Set(path, CreateBooleanValue(in_value));
364 }
365 
SetInteger(const std::string & path,int in_value)366 void DictionaryValue::SetInteger(const std::string& path, int in_value) {
367   Set(path, CreateIntegerValue(in_value));
368 }
369 
SetDouble(const std::string & path,double in_value)370 void DictionaryValue::SetDouble(const std::string& path, double in_value) {
371   Set(path, CreateDoubleValue(in_value));
372 }
373 
SetString(const std::string & path,const std::string & in_value)374 void DictionaryValue::SetString(const std::string& path,
375                                 const std::string& in_value) {
376   Set(path, CreateStringValue(in_value));
377 }
378 
SetString(const std::string & path,const string16 & in_value)379 void DictionaryValue::SetString(const std::string& path,
380                                 const string16& in_value) {
381   Set(path, CreateStringValue(in_value));
382 }
383 
SetWithoutPathExpansion(const std::string & key,Value * in_value)384 void DictionaryValue::SetWithoutPathExpansion(const std::string& key,
385                                               Value* in_value) {
386   // 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 
Get(const std::string & path,Value ** out_value) const396 bool DictionaryValue::Get(const std::string& path, Value** out_value) const {
397   DCHECK(IsStringUTF8(path));
398   std::string current_path(path);
399   const DictionaryValue* current_dictionary = this;
400   for (size_t delimiter_position = current_path.find('.');
401        delimiter_position != std::string::npos;
402        delimiter_position = current_path.find('.')) {
403     DictionaryValue* child_dictionary = NULL;
404     if (!current_dictionary->GetDictionary(
405             current_path.substr(0, delimiter_position), &child_dictionary))
406       return false;
407 
408     current_dictionary = child_dictionary;
409     current_path.erase(0, delimiter_position + 1);
410   }
411 
412   return current_dictionary->GetWithoutPathExpansion(current_path, out_value);
413 }
414 
GetBoolean(const std::string & path,bool * bool_value) const415 bool DictionaryValue::GetBoolean(const std::string& path,
416                                  bool* bool_value) const {
417   Value* value;
418   if (!Get(path, &value))
419     return false;
420 
421   return value->GetAsBoolean(bool_value);
422 }
423 
GetInteger(const std::string & path,int * out_value) const424 bool DictionaryValue::GetInteger(const std::string& path,
425                                  int* out_value) const {
426   Value* value;
427   if (!Get(path, &value))
428     return false;
429 
430   return value->GetAsInteger(out_value);
431 }
432 
GetDouble(const std::string & path,double * out_value) const433 bool DictionaryValue::GetDouble(const std::string& path,
434                                 double* out_value) const {
435   Value* value;
436   if (!Get(path, &value))
437     return false;
438 
439   return value->GetAsDouble(out_value);
440 }
441 
GetString(const std::string & path,std::string * out_value) const442 bool DictionaryValue::GetString(const std::string& path,
443                                 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 
GetString(const std::string & path,string16 * out_value) const451 bool DictionaryValue::GetString(const std::string& path,
452                                 string16* out_value) const {
453   Value* value;
454   if (!Get(path, &value))
455     return false;
456 
457   return value->GetAsString(out_value);
458 }
459 
GetStringASCII(const std::string & path,std::string * out_value) const460 bool DictionaryValue::GetStringASCII(const std::string& path,
461                                      std::string* out_value) const {
462   std::string out;
463   if (!GetString(path, &out))
464     return false;
465 
466   if (!IsStringASCII(out)) {
467     NOTREACHED();
468     return false;
469   }
470 
471   out_value->assign(out);
472   return true;
473 }
474 
GetBinary(const std::string & path,BinaryValue ** out_value) const475 bool DictionaryValue::GetBinary(const std::string& path,
476                                 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 
GetDictionary(const std::string & path,DictionaryValue ** out_value) const488 bool DictionaryValue::GetDictionary(const std::string& path,
489                                     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 
GetList(const std::string & path,ListValue ** out_value) const501 bool DictionaryValue::GetList(const std::string& path,
502                               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 
GetWithoutPathExpansion(const std::string & key,Value ** out_value) const514 bool DictionaryValue::GetWithoutPathExpansion(const std::string& key,
515                                               Value** out_value) const {
516   DCHECK(IsStringUTF8(key));
517   ValueMap::const_iterator entry_iterator = dictionary_.find(key);
518   if (entry_iterator == dictionary_.end())
519     return false;
520 
521   Value* entry = entry_iterator->second;
522   if (out_value)
523     *out_value = entry;
524   return true;
525 }
526 
GetIntegerWithoutPathExpansion(const std::string & key,int * out_value) const527 bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::string& key,
528                                                      int* out_value) const {
529   Value* value;
530   if (!GetWithoutPathExpansion(key, &value))
531     return false;
532 
533   return value->GetAsInteger(out_value);
534 }
535 
GetDoubleWithoutPathExpansion(const std::string & key,double * out_value) const536 bool DictionaryValue::GetDoubleWithoutPathExpansion(const std::string& key,
537                                                     double* out_value) const {
538   Value* value;
539   if (!GetWithoutPathExpansion(key, &value))
540     return false;
541 
542   return value->GetAsDouble(out_value);
543 }
544 
GetStringWithoutPathExpansion(const std::string & key,std::string * out_value) const545 bool DictionaryValue::GetStringWithoutPathExpansion(
546     const std::string& key,
547     std::string* out_value) const {
548   Value* value;
549   if (!GetWithoutPathExpansion(key, &value))
550     return false;
551 
552   return value->GetAsString(out_value);
553 }
554 
GetStringWithoutPathExpansion(const std::string & key,string16 * out_value) const555 bool DictionaryValue::GetStringWithoutPathExpansion(
556     const std::string& key,
557     string16* out_value) const {
558   Value* value;
559   if (!GetWithoutPathExpansion(key, &value))
560     return false;
561 
562   return value->GetAsString(out_value);
563 }
564 
GetDictionaryWithoutPathExpansion(const std::string & key,DictionaryValue ** out_value) const565 bool DictionaryValue::GetDictionaryWithoutPathExpansion(
566     const std::string& key,
567     DictionaryValue** out_value) const {
568   Value* value;
569   bool result = GetWithoutPathExpansion(key, &value);
570   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 
GetListWithoutPathExpansion(const std::string & key,ListValue ** out_value) const579 bool DictionaryValue::GetListWithoutPathExpansion(const std::string& key,
580                                                   ListValue** out_value) const {
581   Value* value;
582   bool result = GetWithoutPathExpansion(key, &value);
583   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 
Remove(const std::string & path,Value ** out_value)592 bool DictionaryValue::Remove(const std::string& path, Value** out_value) {
593   DCHECK(IsStringUTF8(path));
594   std::string current_path(path);
595   DictionaryValue* current_dictionary = this;
596   size_t delimiter_position = current_path.rfind('.');
597   if (delimiter_position != std::string::npos) {
598     if (!GetDictionary(current_path.substr(0, delimiter_position),
599                        &current_dictionary))
600       return false;
601     current_path.erase(0, delimiter_position + 1);
602   }
603 
604   return current_dictionary->RemoveWithoutPathExpansion(current_path,
605                                                         out_value);
606 }
607 
RemoveWithoutPathExpansion(const std::string & key,Value ** out_value)608 bool DictionaryValue::RemoveWithoutPathExpansion(const std::string& key,
609                                                  Value** out_value) {
610   DCHECK(IsStringUTF8(key));
611   ValueMap::iterator entry_iterator = dictionary_.find(key);
612   if (entry_iterator == dictionary_.end())
613     return false;
614 
615   Value* entry = entry_iterator->second;
616   if (out_value)
617     *out_value = entry;
618   else
619     delete entry;
620   dictionary_.erase(entry_iterator);
621   return true;
622 }
623 
DeepCopyWithoutEmptyChildren()624 DictionaryValue* DictionaryValue::DeepCopyWithoutEmptyChildren() {
625   Value* copy = CopyWithoutEmptyChildren(this);
626   return copy ? static_cast<DictionaryValue*>(copy) : new DictionaryValue;
627 }
628 
MergeDictionary(const DictionaryValue * dictionary)629 void 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 
DeepCopy() const649 DictionaryValue* DictionaryValue::DeepCopy() const {
650   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 
Equals(const Value * other) const661 bool 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 
687 ///////////////////// ListValue ////////////////////
688 
ListValue()689 ListValue::ListValue() : Value(TYPE_LIST) {
690 }
691 
~ListValue()692 ListValue::~ListValue() {
693   Clear();
694 }
695 
Clear()696 void ListValue::Clear() {
697   for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i)
698     delete *i;
699   list_.clear();
700 }
701 
Set(size_t index,Value * in_value)702 bool 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 
Get(size_t index,Value ** out_value) const719 bool 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 
GetBoolean(size_t index,bool * bool_value) const729 bool 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 
GetInteger(size_t index,int * out_value) const737 bool 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 
GetDouble(size_t index,double * out_value) const745 bool ListValue::GetDouble(size_t index, double* out_value) const {
746   Value* value;
747   if (!Get(index, &value))
748     return false;
749 
750   return value->GetAsDouble(out_value);
751 }
752 
GetString(size_t index,std::string * out_value) const753 bool 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 
GetString(size_t index,string16 * out_value) const761 bool 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 
GetBinary(size_t index,BinaryValue ** out_value) const769 bool 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 
GetDictionary(size_t index,DictionaryValue ** out_value) const781 bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) const {
782   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 
GetList(size_t index,ListValue ** out_value) const793 bool 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 
Remove(size_t index,Value ** out_value)805 bool 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 
814   list_.erase(list_.begin() + index);
815   return true;
816 }
817 
Remove(const Value & value)818 int ListValue::Remove(const Value& value) {
819   for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) {
820     if ((*i)->Equals(&value)) {
821       size_t index = i - list_.begin();
822       delete *i;
823       list_.erase(i);
824 
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;
830     }
831   }
832   return -1;
833 }
834 
Append(Value * in_value)835 void ListValue::Append(Value* in_value) {
836   DCHECK(in_value);
837   list_.push_back(in_value);
838 }
839 
AppendIfNotPresent(Value * in_value)840 bool ListValue::AppendIfNotPresent(Value* in_value) {
841   DCHECK(in_value);
842   for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i) {
843     if ((*i)->Equals(in_value)) {
844       delete in_value;
845       return false;
846     }
847   }
848   list_.push_back(in_value);
849   return true;
850 }
851 
Insert(size_t index,Value * in_value)852 bool ListValue::Insert(size_t index, Value* in_value) {
853   DCHECK(in_value);
854   if (index > list_.size())
855     return false;
856 
857   list_.insert(list_.begin() + index, in_value);
858   return true;
859 }
860 
GetAsList(ListValue ** out_value)861 bool ListValue::GetAsList(ListValue** out_value) {
862   if (out_value)
863     *out_value = this;
864   return true;
865 }
866 
DeepCopy() const867 ListValue* ListValue::DeepCopy() const {
868   ListValue* result = new ListValue;
869 
870   for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i)
871     result->Append((*i)->DeepCopy());
872 
873   return result;
874 }
875 
Equals(const Value * other) const876 bool ListValue::Equals(const Value* other) const {
877   if (other->GetType() != GetType())
878     return false;
879 
880   const ListValue* other_list =
881       static_cast<const ListValue*>(other);
882   const_iterator lhs_it, rhs_it;
883   for (lhs_it = begin(), rhs_it = other_list->begin();
884        lhs_it != end() && rhs_it != other_list->end();
885        ++lhs_it, ++rhs_it) {
886     if (!(*lhs_it)->Equals(*rhs_it))
887       return false;
888   }
889   if (lhs_it != end() || rhs_it != other_list->end())
890     return false;
891 
892   return true;
893 }
894 
~ValueSerializer()895 ValueSerializer::~ValueSerializer() {
896 }
897