Home | History | Annotate | Download | only in base
      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.
     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 
     64 Value::~Value() {
     65 }
     66 
     67 // static
     68 Value* Value::CreateNullValue() {
     69   return new Value(TYPE_NULL);
     70 }
     71 
     72 // static
     73 FundamentalValue* Value::CreateBooleanValue(bool in_value) {
     74   return new FundamentalValue(in_value);
     75 }
     76 
     77 // static
     78 FundamentalValue* Value::CreateIntegerValue(int in_value) {
     79   return new FundamentalValue(in_value);
     80 }
     81 
     82 // static
     83 FundamentalValue* Value::CreateDoubleValue(double in_value) {
     84   return new FundamentalValue(in_value);
     85 }
     86 
     87 // static
     88 StringValue* Value::CreateStringValue(const std::string& in_value) {
     89   return new StringValue(in_value);
     90 }
     91 
     92 // static
     93 StringValue* Value::CreateStringValue(const string16& in_value) {
     94   return new StringValue(in_value);
     95 }
     96 
     97 // static
     98 BinaryValue* Value::CreateBinaryValue(char* buffer, size_t size) {
     99   return BinaryValue::Create(buffer, size);
    100 }
    101 
    102 bool Value::GetAsBoolean(bool* out_value) const {
    103   return false;
    104 }
    105 
    106 bool Value::GetAsInteger(int* out_value) const {
    107   return false;
    108 }
    109 
    110 bool Value::GetAsDouble(double* out_value) const {
    111   return false;
    112 }
    113 
    114 bool Value::GetAsString(std::string* out_value) const {
    115   return false;
    116 }
    117 
    118 bool Value::GetAsString(string16* out_value) const {
    119   return false;
    120 }
    121 
    122 bool Value::GetAsList(ListValue** out_value) {
    123   return false;
    124 }
    125 
    126 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 
    133 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
    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 
    147 Value::Value(ValueType type) : type_(type) {
    148 }
    149 
    150 ///////////////////// FundamentalValue ////////////////////
    151 
    152 FundamentalValue::FundamentalValue(bool in_value)
    153     : Value(TYPE_BOOLEAN), boolean_value_(in_value) {
    154 }
    155 
    156 FundamentalValue::FundamentalValue(int in_value)
    157     : Value(TYPE_INTEGER), integer_value_(in_value) {
    158 }
    159 
    160 FundamentalValue::FundamentalValue(double in_value)
    161     : Value(TYPE_DOUBLE), double_value_(in_value) {
    162 }
    163 
    164 FundamentalValue::~FundamentalValue() {
    165 }
    166 
    167 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 
    173 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 
    179 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 
    185 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 
    202 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 
    227 StringValue::StringValue(const std::string& in_value)
    228     : Value(TYPE_STRING),
    229       value_(in_value) {
    230   DCHECK(IsStringUTF8(in_value));
    231 }
    232 
    233 StringValue::StringValue(const string16& in_value)
    234     : Value(TYPE_STRING),
    235       value_(UTF16ToUTF8(in_value)) {
    236 }
    237 
    238 StringValue::~StringValue() {
    239 }
    240 
    241 bool StringValue::GetAsString(std::string* out_value) const {
    242   if (out_value)
    243     *out_value = value_;
    244   return true;
    245 }
    246 
    247 bool StringValue::GetAsString(string16* out_value) const {
    248   if (out_value)
    249     *out_value = UTF8ToUTF16(value_);
    250   return true;
    251 }
    252 
    253 StringValue* StringValue::DeepCopy() const {
    254   return CreateStringValue(value_);
    255 }
    256 
    257 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 
    266 BinaryValue::~BinaryValue() {
    267   DCHECK(buffer_);
    268   if (buffer_)
    269     delete[] buffer_;
    270 }
    271 
    272 // static
    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
    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 
    291 BinaryValue* BinaryValue::DeepCopy() const {
    292   return CreateWithCopiedBuffer(buffer_, size_);
    293 }
    294 
    295 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 
    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 
    313 DictionaryValue::DictionaryValue()
    314     : Value(TYPE_DICTIONARY) {
    315 }
    316 
    317 DictionaryValue::~DictionaryValue() {
    318   Clear();
    319 }
    320 
    321 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 
    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 
    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 
    362 void DictionaryValue::SetBoolean(const std::string& path, bool in_value) {
    363   Set(path, CreateBooleanValue(in_value));
    364 }
    365 
    366 void DictionaryValue::SetInteger(const std::string& path, int in_value) {
    367   Set(path, CreateIntegerValue(in_value));
    368 }
    369 
    370 void DictionaryValue::SetDouble(const std::string& path, double in_value) {
    371   Set(path, CreateDoubleValue(in_value));
    372 }
    373 
    374 void DictionaryValue::SetString(const std::string& path,
    375                                 const std::string& in_value) {
    376   Set(path, CreateStringValue(in_value));
    377 }
    378 
    379 void DictionaryValue::SetString(const std::string& path,
    380                                 const string16& in_value) {
    381   Set(path, CreateStringValue(in_value));
    382 }
    383 
    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 
    396 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 
    415 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 
    424 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 
    433 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 
    442 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 
    451 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 
    460 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 
    475 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 
    488 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 
    501 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 
    514 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 
    527 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 
    536 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 
    545 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 
    555 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 
    565 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 
    579 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 
    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 
    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 
    624 DictionaryValue* DictionaryValue::DeepCopyWithoutEmptyChildren() {
    625   Value* copy = CopyWithoutEmptyChildren(this);
    626   return copy ? static_cast<DictionaryValue*>(copy) : new DictionaryValue;
    627 }
    628 
    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 
    649 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 
    661 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 
    689 ListValue::ListValue() : Value(TYPE_LIST) {
    690 }
    691 
    692 ListValue::~ListValue() {
    693   Clear();
    694 }
    695 
    696 void ListValue::Clear() {
    697   for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i)
    698     delete *i;
    699   list_.clear();
    700 }
    701 
    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 
    719 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 
    729 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 
    737 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 
    745 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 
    753 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 
    761 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 
    769 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 
    781 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 
    793 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 
    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 
    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 
    835 void ListValue::Append(Value* in_value) {
    836   DCHECK(in_value);
    837   list_.push_back(in_value);
    838 }
    839 
    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 
    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 
    861 bool ListValue::GetAsList(ListValue** out_value) {
    862   if (out_value)
    863     *out_value = this;
    864   return true;
    865 }
    866 
    867 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 
    876 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 
    895 ValueSerializer::~ValueSerializer() {
    896 }
    897