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