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