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