values.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
1// Copyright (c) 2010 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
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
61
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
88Value* Value::CreateStringValue(const std::string& in_value) {
89  return new StringValue(in_value);
90}
91
92// static
93Value* Value::CreateStringValue(const string16& in_value) {
94  return new StringValue(in_value);
95}
96
97// static
98BinaryValue* Value::CreateBinaryValue(char* buffer, size_t size) {
99  return BinaryValue::Create(buffer, size);
100}
101
102bool Value::GetAsBoolean(bool* out_value) const {
103  return false;
104}
105
106bool Value::GetAsInteger(int* out_value) const {
107  return false;
108}
109
110bool Value::GetAsReal(double* out_value) const {
111  return false;
112}
113
114bool Value::GetAsString(std::string* out_value) const {
115  return false;
116}
117
118bool Value::GetAsString(string16* out_value) const {
119  return false;
120}
121
122bool Value::GetAsList(ListValue** out_value) {
123  return false;
124}
125
126Value* Value::DeepCopy() const {
127  // This method should only be getting called for null Values--all subclasses
128  // need to provide their own implementation;.
129  DCHECK(IsType(TYPE_NULL));
130  return CreateNullValue();
131}
132
133bool Value::Equals(const Value* other) const {
134  // This method should only be getting called for null Values--all subclasses
135  // need to provide their own implementation;.
136  DCHECK(IsType(TYPE_NULL));
137  return other->IsType(TYPE_NULL);
138}
139
140// static
141bool Value::Equals(const Value* a, const Value* b) {
142  if ((a == NULL) && (b == NULL)) return true;
143  if ((a == NULL) ^  (b == NULL)) return false;
144  return a->Equals(b);
145}
146
147Value::Value(ValueType type) : type_(type) {
148}
149
150///////////////////// FundamentalValue ////////////////////
151
152FundamentalValue::FundamentalValue(bool in_value)
153    : Value(TYPE_BOOLEAN), boolean_value_(in_value) {
154}
155
156FundamentalValue::FundamentalValue(int in_value)
157    : Value(TYPE_INTEGER), integer_value_(in_value) {
158}
159
160FundamentalValue::FundamentalValue(double in_value)
161    : Value(TYPE_REAL), real_value_(in_value) {
162}
163
164FundamentalValue::~FundamentalValue() {
165}
166
167bool FundamentalValue::GetAsBoolean(bool* out_value) const {
168  if (out_value && IsType(TYPE_BOOLEAN))
169    *out_value = boolean_value_;
170  return (IsType(TYPE_BOOLEAN));
171}
172
173bool FundamentalValue::GetAsInteger(int* out_value) const {
174  if (out_value && IsType(TYPE_INTEGER))
175    *out_value = integer_value_;
176  return (IsType(TYPE_INTEGER));
177}
178
179bool FundamentalValue::GetAsReal(double* out_value) const {
180  if (out_value && IsType(TYPE_REAL))
181    *out_value = real_value_;
182  return (IsType(TYPE_REAL));
183}
184
185Value* 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_REAL:
194      return CreateRealValue(real_value_);
195
196    default:
197      NOTREACHED();
198      return NULL;
199  }
200}
201
202bool FundamentalValue::Equals(const Value* other) const {
203  if (other->GetType() != GetType())
204    return false;
205
206  switch (GetType()) {
207    case TYPE_BOOLEAN: {
208      bool lhs, rhs;
209      return GetAsBoolean(&lhs) && other->GetAsBoolean(&rhs) && lhs == rhs;
210    }
211    case TYPE_INTEGER: {
212      int lhs, rhs;
213      return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs;
214    }
215    case TYPE_REAL: {
216      double lhs, rhs;
217      return GetAsReal(&lhs) && other->GetAsReal(&rhs) && lhs == rhs;
218    }
219    default:
220      NOTREACHED();
221      return false;
222  }
223}
224
225///////////////////// StringValue ////////////////////
226
227StringValue::StringValue(const std::string& in_value)
228    : Value(TYPE_STRING),
229      value_(in_value) {
230  DCHECK(IsStringUTF8(in_value));
231}
232
233StringValue::StringValue(const string16& in_value)
234    : Value(TYPE_STRING),
235      value_(UTF16ToUTF8(in_value)) {
236}
237
238StringValue::~StringValue() {
239}
240
241bool StringValue::GetAsString(std::string* out_value) const {
242  if (out_value)
243    *out_value = value_;
244  return true;
245}
246
247bool StringValue::GetAsString(string16* out_value) const {
248  if (out_value)
249    *out_value = UTF8ToUTF16(value_);
250  return true;
251}
252
253Value* StringValue::DeepCopy() const {
254  return CreateStringValue(value_);
255}
256
257bool 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
266// static
267BinaryValue* BinaryValue::Create(char* buffer, size_t size) {
268  if (!buffer)
269    return NULL;
270
271  return new BinaryValue(buffer, size);
272}
273
274// static
275BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer,
276                                                 size_t size) {
277  if (!buffer)
278    return NULL;
279
280  char* buffer_copy = new char[size];
281  memcpy(buffer_copy, buffer, size);
282  return new BinaryValue(buffer_copy, size);
283}
284
285
286BinaryValue::BinaryValue(char* buffer, size_t size)
287  : Value(TYPE_BINARY),
288    buffer_(buffer),
289    size_(size) {
290  DCHECK(buffer_);
291}
292
293BinaryValue::~BinaryValue() {
294  DCHECK(buffer_);
295  if (buffer_)
296    delete[] buffer_;
297}
298
299Value* BinaryValue::DeepCopy() const {
300  return CreateWithCopiedBuffer(buffer_, size_);
301}
302
303bool BinaryValue::Equals(const Value* other) const {
304  if (other->GetType() != GetType())
305    return false;
306  const BinaryValue* other_binary = static_cast<const BinaryValue*>(other);
307  if (other_binary->size_ != size_)
308    return false;
309  return !memcmp(buffer_, other_binary->buffer_, size_);
310}
311
312///////////////////// DictionaryValue ////////////////////
313
314DictionaryValue::DictionaryValue()
315    : Value(TYPE_DICTIONARY) {
316}
317
318DictionaryValue::~DictionaryValue() {
319  Clear();
320}
321
322Value* DictionaryValue::DeepCopy() const {
323  DictionaryValue* result = new DictionaryValue;
324
325  for (ValueMap::const_iterator current_entry(dictionary_.begin());
326       current_entry != dictionary_.end(); ++current_entry) {
327    result->SetWithoutPathExpansion(current_entry->first,
328                                    current_entry->second->DeepCopy());
329  }
330
331  return result;
332}
333
334bool DictionaryValue::Equals(const Value* other) const {
335  if (other->GetType() != GetType())
336    return false;
337
338  const DictionaryValue* other_dict =
339      static_cast<const DictionaryValue*>(other);
340  key_iterator lhs_it(begin_keys());
341  key_iterator rhs_it(other_dict->begin_keys());
342  while (lhs_it != end_keys() && rhs_it != other_dict->end_keys()) {
343    Value* lhs;
344    Value* rhs;
345    if (*lhs_it != *rhs_it ||
346        !GetWithoutPathExpansion(*lhs_it, &lhs) ||
347        !other_dict->GetWithoutPathExpansion(*rhs_it, &rhs) ||
348        !lhs->Equals(rhs)) {
349      return false;
350    }
351    ++lhs_it;
352    ++rhs_it;
353  }
354  if (lhs_it != end_keys() || rhs_it != other_dict->end_keys())
355    return false;
356
357  return true;
358}
359
360bool DictionaryValue::HasKey(const std::string& key) const {
361  DCHECK(IsStringUTF8(key));
362  ValueMap::const_iterator current_entry = dictionary_.find(key);
363  DCHECK((current_entry == dictionary_.end()) || current_entry->second);
364  return current_entry != dictionary_.end();
365}
366
367void DictionaryValue::Clear() {
368  ValueMap::iterator dict_iterator = dictionary_.begin();
369  while (dict_iterator != dictionary_.end()) {
370    delete dict_iterator->second;
371    ++dict_iterator;
372  }
373
374  dictionary_.clear();
375}
376
377void DictionaryValue::Set(const std::string& path, Value* in_value) {
378  DCHECK(IsStringUTF8(path));
379  DCHECK(in_value);
380
381  std::string current_path(path);
382  DictionaryValue* current_dictionary = this;
383  for (size_t delimiter_position = current_path.find('.');
384       delimiter_position != std::string::npos;
385       delimiter_position = current_path.find('.')) {
386    // Assume that we're indexing into a dictionary.
387    std::string key(current_path, 0, delimiter_position);
388    DictionaryValue* child_dictionary = NULL;
389    if (!current_dictionary->GetDictionary(key, &child_dictionary)) {
390      child_dictionary = new DictionaryValue;
391      current_dictionary->SetWithoutPathExpansion(key, child_dictionary);
392    }
393
394    current_dictionary = child_dictionary;
395    current_path.erase(0, delimiter_position + 1);
396  }
397
398  current_dictionary->SetWithoutPathExpansion(current_path, in_value);
399}
400
401void DictionaryValue::SetBoolean(const std::string& path, bool in_value) {
402  Set(path, CreateBooleanValue(in_value));
403}
404
405void DictionaryValue::SetInteger(const std::string& path, int in_value) {
406  Set(path, CreateIntegerValue(in_value));
407}
408
409void DictionaryValue::SetReal(const std::string& path, double in_value) {
410  Set(path, CreateRealValue(in_value));
411}
412
413void DictionaryValue::SetString(const std::string& path,
414                                const std::string& in_value) {
415  Set(path, CreateStringValue(in_value));
416}
417
418void DictionaryValue::SetString(const std::string& path,
419                                const string16& in_value) {
420  Set(path, CreateStringValue(in_value));
421}
422
423void DictionaryValue::SetWithoutPathExpansion(const std::string& key,
424                                              Value* in_value) {
425  // If there's an existing value here, we need to delete it, because
426  // we own all our children.
427  if (HasKey(key)) {
428    DCHECK(dictionary_[key] != in_value);  // This would be bogus
429    delete dictionary_[key];
430  }
431
432  dictionary_[key] = in_value;
433}
434
435bool DictionaryValue::Get(const std::string& path, Value** out_value) const {
436  DCHECK(IsStringUTF8(path));
437  std::string current_path(path);
438  const DictionaryValue* current_dictionary = this;
439  for (size_t delimiter_position = current_path.find('.');
440       delimiter_position != std::string::npos;
441       delimiter_position = current_path.find('.')) {
442    DictionaryValue* child_dictionary = NULL;
443    if (!current_dictionary->GetDictionary(
444            current_path.substr(0, delimiter_position), &child_dictionary))
445      return false;
446
447    current_dictionary = child_dictionary;
448    current_path.erase(0, delimiter_position + 1);
449  }
450
451  return current_dictionary->GetWithoutPathExpansion(current_path, out_value);
452}
453
454bool DictionaryValue::GetBoolean(const std::string& path,
455                                 bool* bool_value) const {
456  Value* value;
457  if (!Get(path, &value))
458    return false;
459
460  return value->GetAsBoolean(bool_value);
461}
462
463bool DictionaryValue::GetInteger(const std::string& path,
464                                 int* out_value) const {
465  Value* value;
466  if (!Get(path, &value))
467    return false;
468
469  return value->GetAsInteger(out_value);
470}
471
472bool DictionaryValue::GetReal(const std::string& path,
473                              double* out_value) const {
474  Value* value;
475  if (!Get(path, &value))
476    return false;
477
478  return value->GetAsReal(out_value);
479}
480
481bool DictionaryValue::GetString(const std::string& path,
482                                std::string* out_value) const {
483  Value* value;
484  if (!Get(path, &value))
485    return false;
486
487  return value->GetAsString(out_value);
488}
489
490bool DictionaryValue::GetString(const std::string& path,
491                                string16* out_value) const {
492  Value* value;
493  if (!Get(path, &value))
494    return false;
495
496  return value->GetAsString(out_value);
497}
498
499bool DictionaryValue::GetStringASCII(const std::string& path,
500                                     std::string* out_value) const {
501  std::string out;
502  if (!GetString(path, &out))
503    return false;
504
505  if (!IsStringASCII(out)) {
506    NOTREACHED();
507    return false;
508  }
509
510  out_value->assign(out);
511  return true;
512}
513
514bool DictionaryValue::GetBinary(const std::string& path,
515                                BinaryValue** out_value) const {
516  Value* value;
517  bool result = Get(path, &value);
518  if (!result || !value->IsType(TYPE_BINARY))
519    return false;
520
521  if (out_value)
522    *out_value = static_cast<BinaryValue*>(value);
523
524  return true;
525}
526
527bool DictionaryValue::GetDictionary(const std::string& path,
528                                    DictionaryValue** out_value) const {
529  Value* value;
530  bool result = Get(path, &value);
531  if (!result || !value->IsType(TYPE_DICTIONARY))
532    return false;
533
534  if (out_value)
535    *out_value = static_cast<DictionaryValue*>(value);
536
537  return true;
538}
539
540bool DictionaryValue::GetList(const std::string& path,
541                              ListValue** out_value) const {
542  Value* value;
543  bool result = Get(path, &value);
544  if (!result || !value->IsType(TYPE_LIST))
545    return false;
546
547  if (out_value)
548    *out_value = static_cast<ListValue*>(value);
549
550  return true;
551}
552
553bool DictionaryValue::GetWithoutPathExpansion(const std::string& key,
554                                              Value** out_value) const {
555  DCHECK(IsStringUTF8(key));
556  ValueMap::const_iterator entry_iterator = dictionary_.find(key);
557  if (entry_iterator == dictionary_.end())
558    return false;
559
560  Value* entry = entry_iterator->second;
561  if (out_value)
562    *out_value = entry;
563  return true;
564}
565
566bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::string& key,
567                                                     int* out_value) const {
568  Value* value;
569  if (!GetWithoutPathExpansion(key, &value))
570    return false;
571
572  return value->GetAsInteger(out_value);
573}
574
575bool DictionaryValue::GetRealWithoutPathExpansion(const std::string& key,
576                                                  double* out_value) const {
577  Value* value;
578  if (!GetWithoutPathExpansion(key, &value))
579    return false;
580
581  return value->GetAsReal(out_value);
582}
583
584bool DictionaryValue::GetStringWithoutPathExpansion(
585    const std::string& key,
586    std::string* out_value) const {
587  Value* value;
588  if (!GetWithoutPathExpansion(key, &value))
589    return false;
590
591  return value->GetAsString(out_value);
592}
593
594bool DictionaryValue::GetStringWithoutPathExpansion(
595    const std::string& key,
596    string16* out_value) const {
597  Value* value;
598  if (!GetWithoutPathExpansion(key, &value))
599    return false;
600
601  return value->GetAsString(out_value);
602}
603
604bool DictionaryValue::GetDictionaryWithoutPathExpansion(
605    const std::string& key,
606    DictionaryValue** out_value) const {
607  Value* value;
608  bool result = GetWithoutPathExpansion(key, &value);
609  if (!result || !value->IsType(TYPE_DICTIONARY))
610    return false;
611
612  if (out_value)
613    *out_value = static_cast<DictionaryValue*>(value);
614
615  return true;
616}
617
618bool DictionaryValue::GetListWithoutPathExpansion(const std::string& key,
619                                                  ListValue** out_value) const {
620  Value* value;
621  bool result = GetWithoutPathExpansion(key, &value);
622  if (!result || !value->IsType(TYPE_LIST))
623    return false;
624
625  if (out_value)
626    *out_value = static_cast<ListValue*>(value);
627
628  return true;
629}
630
631bool DictionaryValue::Remove(const std::string& path, Value** out_value) {
632  DCHECK(IsStringUTF8(path));
633  std::string current_path(path);
634  DictionaryValue* current_dictionary = this;
635  size_t delimiter_position = current_path.rfind('.');
636  if (delimiter_position != std::string::npos) {
637    if (!GetDictionary(current_path.substr(0, delimiter_position),
638                       &current_dictionary))
639      return false;
640    current_path.erase(0, delimiter_position + 1);
641  }
642
643  return current_dictionary->RemoveWithoutPathExpansion(current_path,
644                                                        out_value);
645}
646
647bool DictionaryValue::RemoveWithoutPathExpansion(const std::string& key,
648                                                 Value** out_value) {
649  DCHECK(IsStringUTF8(key));
650  ValueMap::iterator entry_iterator = dictionary_.find(key);
651  if (entry_iterator == dictionary_.end())
652    return false;
653
654  Value* entry = entry_iterator->second;
655  if (out_value)
656    *out_value = entry;
657  else
658    delete entry;
659  dictionary_.erase(entry_iterator);
660  return true;
661}
662
663DictionaryValue* DictionaryValue::DeepCopyWithoutEmptyChildren() {
664  Value* copy = CopyWithoutEmptyChildren(this);
665  return copy ? static_cast<DictionaryValue*>(copy) : new DictionaryValue;
666}
667
668void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) {
669  for (DictionaryValue::key_iterator key(dictionary->begin_keys());
670       key != dictionary->end_keys(); ++key) {
671    Value* merge_value;
672    if (dictionary->GetWithoutPathExpansion(*key, &merge_value)) {
673      // Check whether we have to merge dictionaries.
674      if (merge_value->IsType(Value::TYPE_DICTIONARY)) {
675        DictionaryValue* sub_dict;
676        if (GetDictionaryWithoutPathExpansion(*key, &sub_dict)) {
677          sub_dict->MergeDictionary(
678              static_cast<const DictionaryValue*>(merge_value));
679          continue;
680        }
681      }
682      // All other cases: Make a copy and hook it up.
683      SetWithoutPathExpansion(*key, merge_value->DeepCopy());
684    }
685  }
686}
687
688///////////////////// ListValue ////////////////////
689
690ListValue::ListValue() : Value(TYPE_LIST) {
691}
692
693ListValue::~ListValue() {
694  Clear();
695}
696
697void ListValue::Clear() {
698  for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i)
699    delete *i;
700  list_.clear();
701}
702
703bool ListValue::Set(size_t index, Value* in_value) {
704  if (!in_value)
705    return false;
706
707  if (index >= list_.size()) {
708    // Pad out any intermediate indexes with null settings
709    while (index > list_.size())
710      Append(CreateNullValue());
711    Append(in_value);
712  } else {
713    DCHECK(list_[index] != in_value);
714    delete list_[index];
715    list_[index] = in_value;
716  }
717  return true;
718}
719
720bool ListValue::Get(size_t index, Value** out_value) const {
721  if (index >= list_.size())
722    return false;
723
724  if (out_value)
725    *out_value = list_[index];
726
727  return true;
728}
729
730bool ListValue::GetBoolean(size_t index, bool* bool_value) const {
731  Value* value;
732  if (!Get(index, &value))
733    return false;
734
735  return value->GetAsBoolean(bool_value);
736}
737
738bool ListValue::GetInteger(size_t index, int* out_value) const {
739  Value* value;
740  if (!Get(index, &value))
741    return false;
742
743  return value->GetAsInteger(out_value);
744}
745
746bool ListValue::GetReal(size_t index, double* out_value) const {
747  Value* value;
748  if (!Get(index, &value))
749    return false;
750
751  return value->GetAsReal(out_value);
752}
753
754bool ListValue::GetString(size_t index, std::string* out_value) const {
755  Value* value;
756  if (!Get(index, &value))
757    return false;
758
759  return value->GetAsString(out_value);
760}
761
762bool ListValue::GetString(size_t index, string16* out_value) const {
763  Value* value;
764  if (!Get(index, &value))
765    return false;
766
767  return value->GetAsString(out_value);
768}
769
770bool ListValue::GetBinary(size_t index, BinaryValue** out_value) const {
771  Value* value;
772  bool result = Get(index, &value);
773  if (!result || !value->IsType(TYPE_BINARY))
774    return false;
775
776  if (out_value)
777    *out_value = static_cast<BinaryValue*>(value);
778
779  return true;
780}
781
782bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) const {
783  Value* value;
784  bool result = Get(index, &value);
785  if (!result || !value->IsType(TYPE_DICTIONARY))
786    return false;
787
788  if (out_value)
789    *out_value = static_cast<DictionaryValue*>(value);
790
791  return true;
792}
793
794bool ListValue::GetList(size_t index, ListValue** out_value) const {
795  Value* value;
796  bool result = Get(index, &value);
797  if (!result || !value->IsType(TYPE_LIST))
798    return false;
799
800  if (out_value)
801    *out_value = static_cast<ListValue*>(value);
802
803  return true;
804}
805
806bool ListValue::Remove(size_t index, Value** out_value) {
807  if (index >= list_.size())
808    return false;
809
810  if (out_value)
811    *out_value = list_[index];
812  else
813    delete list_[index];
814
815  list_.erase(list_.begin() + index);
816  return true;
817}
818
819int ListValue::Remove(const Value& value) {
820  for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) {
821    if ((*i)->Equals(&value)) {
822      size_t index = i - list_.begin();
823      delete *i;
824      list_.erase(i);
825
826      // TODO(anyone): Returning a signed int type here is just wrong.
827      // Change this interface to return a size_t.
828      DCHECK(index <= INT_MAX);
829      int return_index = static_cast<int>(index);
830      return return_index;
831    }
832  }
833  return -1;
834}
835
836void ListValue::Append(Value* in_value) {
837  DCHECK(in_value);
838  list_.push_back(in_value);
839}
840
841bool ListValue::AppendIfNotPresent(Value* in_value) {
842  DCHECK(in_value);
843  for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i) {
844    if ((*i)->Equals(in_value))
845      return false;
846  }
847  list_.push_back(in_value);
848  return true;
849}
850
851bool ListValue::Insert(size_t index, Value* in_value) {
852  DCHECK(in_value);
853  if (index > list_.size())
854    return false;
855
856  list_.insert(list_.begin() + index, in_value);
857  return true;
858}
859
860bool ListValue::GetAsList(ListValue** out_value) {
861  if (out_value)
862    *out_value = this;
863  return true;
864}
865
866Value* ListValue::DeepCopy() const {
867  ListValue* result = new ListValue;
868
869  for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i)
870    result->Append((*i)->DeepCopy());
871
872  return result;
873}
874
875bool ListValue::Equals(const Value* other) const {
876  if (other->GetType() != GetType())
877    return false;
878
879  const ListValue* other_list =
880      static_cast<const ListValue*>(other);
881  const_iterator lhs_it, rhs_it;
882  for (lhs_it = begin(), rhs_it = other_list->begin();
883       lhs_it != end() && rhs_it != other_list->end();
884       ++lhs_it, ++rhs_it) {
885    if (!(*lhs_it)->Equals(*rhs_it))
886      return false;
887  }
888  if (lhs_it != end() || rhs_it != other_list->end())
889    return false;
890
891  return true;
892}
893
894ValueSerializer::~ValueSerializer() {
895}
896