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.
CopyWithoutEmptyChildren(Value * node)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
~Value()64 Value::~Value() {
65 }
66
67 // static
CreateNullValue()68 Value* Value::CreateNullValue() {
69 return new Value(TYPE_NULL);
70 }
71
72 // static
CreateBooleanValue(bool in_value)73 FundamentalValue* Value::CreateBooleanValue(bool in_value) {
74 return new FundamentalValue(in_value);
75 }
76
77 // static
CreateIntegerValue(int in_value)78 FundamentalValue* Value::CreateIntegerValue(int in_value) {
79 return new FundamentalValue(in_value);
80 }
81
82 // static
CreateDoubleValue(double in_value)83 FundamentalValue* Value::CreateDoubleValue(double in_value) {
84 return new FundamentalValue(in_value);
85 }
86
87 // static
CreateStringValue(const std::string & in_value)88 StringValue* Value::CreateStringValue(const std::string& in_value) {
89 return new StringValue(in_value);
90 }
91
92 // static
CreateStringValue(const string16 & in_value)93 StringValue* Value::CreateStringValue(const string16& in_value) {
94 return new StringValue(in_value);
95 }
96
97 // static
CreateBinaryValue(char * buffer,size_t size)98 BinaryValue* Value::CreateBinaryValue(char* buffer, size_t size) {
99 return BinaryValue::Create(buffer, size);
100 }
101
GetAsBoolean(bool * out_value) const102 bool Value::GetAsBoolean(bool* out_value) const {
103 return false;
104 }
105
GetAsInteger(int * out_value) const106 bool Value::GetAsInteger(int* out_value) const {
107 return false;
108 }
109
GetAsDouble(double * out_value) const110 bool Value::GetAsDouble(double* out_value) const {
111 return false;
112 }
113
GetAsString(std::string * out_value) const114 bool Value::GetAsString(std::string* out_value) const {
115 return false;
116 }
117
GetAsString(string16 * out_value) const118 bool Value::GetAsString(string16* out_value) const {
119 return false;
120 }
121
GetAsList(ListValue ** out_value)122 bool Value::GetAsList(ListValue** out_value) {
123 return false;
124 }
125
DeepCopy() const126 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
Equals(const Value * other) const133 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
Equals(const Value * a,const Value * b)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
Value(ValueType type)147 Value::Value(ValueType type) : type_(type) {
148 }
149
150 ///////////////////// FundamentalValue ////////////////////
151
FundamentalValue(bool in_value)152 FundamentalValue::FundamentalValue(bool in_value)
153 : Value(TYPE_BOOLEAN), boolean_value_(in_value) {
154 }
155
FundamentalValue(int in_value)156 FundamentalValue::FundamentalValue(int in_value)
157 : Value(TYPE_INTEGER), integer_value_(in_value) {
158 }
159
FundamentalValue(double in_value)160 FundamentalValue::FundamentalValue(double in_value)
161 : Value(TYPE_DOUBLE), double_value_(in_value) {
162 }
163
~FundamentalValue()164 FundamentalValue::~FundamentalValue() {
165 }
166
GetAsBoolean(bool * out_value) const167 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
GetAsInteger(int * out_value) const173 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
GetAsDouble(double * out_value) const179 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
DeepCopy() const185 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
Equals(const Value * other) const202 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
StringValue(const std::string & in_value)227 StringValue::StringValue(const std::string& in_value)
228 : Value(TYPE_STRING),
229 value_(in_value) {
230 DCHECK(IsStringUTF8(in_value));
231 }
232
StringValue(const string16 & in_value)233 StringValue::StringValue(const string16& in_value)
234 : Value(TYPE_STRING),
235 value_(UTF16ToUTF8(in_value)) {
236 }
237
~StringValue()238 StringValue::~StringValue() {
239 }
240
GetAsString(std::string * out_value) const241 bool StringValue::GetAsString(std::string* out_value) const {
242 if (out_value)
243 *out_value = value_;
244 return true;
245 }
246
GetAsString(string16 * out_value) const247 bool StringValue::GetAsString(string16* out_value) const {
248 if (out_value)
249 *out_value = UTF8ToUTF16(value_);
250 return true;
251 }
252
DeepCopy() const253 StringValue* StringValue::DeepCopy() const {
254 return CreateStringValue(value_);
255 }
256
Equals(const Value * other) const257 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
~BinaryValue()266 BinaryValue::~BinaryValue() {
267 DCHECK(buffer_);
268 if (buffer_)
269 delete[] buffer_;
270 }
271
272 // static
Create(char * buffer,size_t size)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
CreateWithCopiedBuffer(const char * buffer,size_t size)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
DeepCopy() const291 BinaryValue* BinaryValue::DeepCopy() const {
292 return CreateWithCopiedBuffer(buffer_, size_);
293 }
294
Equals(const Value * other) const295 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
BinaryValue(char * buffer,size_t size)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
DictionaryValue()313 DictionaryValue::DictionaryValue()
314 : Value(TYPE_DICTIONARY) {
315 }
316
~DictionaryValue()317 DictionaryValue::~DictionaryValue() {
318 Clear();
319 }
320
HasKey(const std::string & key) const321 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
Clear()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
Set(const std::string & path,Value * in_value)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
SetBoolean(const std::string & path,bool in_value)362 void DictionaryValue::SetBoolean(const std::string& path, bool in_value) {
363 Set(path, CreateBooleanValue(in_value));
364 }
365
SetInteger(const std::string & path,int in_value)366 void DictionaryValue::SetInteger(const std::string& path, int in_value) {
367 Set(path, CreateIntegerValue(in_value));
368 }
369
SetDouble(const std::string & path,double in_value)370 void DictionaryValue::SetDouble(const std::string& path, double in_value) {
371 Set(path, CreateDoubleValue(in_value));
372 }
373
SetString(const std::string & path,const std::string & in_value)374 void DictionaryValue::SetString(const std::string& path,
375 const std::string& in_value) {
376 Set(path, CreateStringValue(in_value));
377 }
378
SetString(const std::string & path,const string16 & in_value)379 void DictionaryValue::SetString(const std::string& path,
380 const string16& in_value) {
381 Set(path, CreateStringValue(in_value));
382 }
383
SetWithoutPathExpansion(const std::string & key,Value * in_value)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
Get(const std::string & path,Value ** out_value) const396 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
GetBoolean(const std::string & path,bool * bool_value) const415 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
GetInteger(const std::string & path,int * out_value) const424 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
GetDouble(const std::string & path,double * out_value) const433 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
GetString(const std::string & path,std::string * out_value) const442 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
GetString(const std::string & path,string16 * out_value) const451 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
GetStringASCII(const std::string & path,std::string * out_value) const460 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
GetBinary(const std::string & path,BinaryValue ** out_value) const475 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
GetDictionary(const std::string & path,DictionaryValue ** out_value) const488 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
GetList(const std::string & path,ListValue ** out_value) const501 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
GetWithoutPathExpansion(const std::string & key,Value ** out_value) const514 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
GetIntegerWithoutPathExpansion(const std::string & key,int * out_value) const527 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
GetDoubleWithoutPathExpansion(const std::string & key,double * out_value) const536 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
GetStringWithoutPathExpansion(const std::string & key,std::string * out_value) const545 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
GetStringWithoutPathExpansion(const std::string & key,string16 * out_value) const555 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
GetDictionaryWithoutPathExpansion(const std::string & key,DictionaryValue ** out_value) const565 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
GetListWithoutPathExpansion(const std::string & key,ListValue ** out_value) const579 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
Remove(const std::string & path,Value ** out_value)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 ¤t_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
RemoveWithoutPathExpansion(const std::string & key,Value ** out_value)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
DeepCopyWithoutEmptyChildren()624 DictionaryValue* DictionaryValue::DeepCopyWithoutEmptyChildren() {
625 Value* copy = CopyWithoutEmptyChildren(this);
626 return copy ? static_cast<DictionaryValue*>(copy) : new DictionaryValue;
627 }
628
MergeDictionary(const DictionaryValue * dictionary)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
DeepCopy() const649 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
Equals(const Value * other) const661 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
ListValue()689 ListValue::ListValue() : Value(TYPE_LIST) {
690 }
691
~ListValue()692 ListValue::~ListValue() {
693 Clear();
694 }
695
Clear()696 void ListValue::Clear() {
697 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i)
698 delete *i;
699 list_.clear();
700 }
701
Set(size_t index,Value * in_value)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
Get(size_t index,Value ** out_value) const719 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
GetBoolean(size_t index,bool * bool_value) const729 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
GetInteger(size_t index,int * out_value) const737 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
GetDouble(size_t index,double * out_value) const745 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
GetString(size_t index,std::string * out_value) const753 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
GetString(size_t index,string16 * out_value) const761 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
GetBinary(size_t index,BinaryValue ** out_value) const769 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
GetDictionary(size_t index,DictionaryValue ** out_value) const781 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
GetList(size_t index,ListValue ** out_value) const793 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
Remove(size_t index,Value ** out_value)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
Remove(const Value & value)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
Append(Value * in_value)835 void ListValue::Append(Value* in_value) {
836 DCHECK(in_value);
837 list_.push_back(in_value);
838 }
839
AppendIfNotPresent(Value * in_value)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
Insert(size_t index,Value * in_value)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
GetAsList(ListValue ** out_value)861 bool ListValue::GetAsList(ListValue** out_value) {
862 if (out_value)
863 *out_value = this;
864 return true;
865 }
866
DeepCopy() const867 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
Equals(const Value * other) const876 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
~ValueSerializer()895 ValueSerializer::~ValueSerializer() {
896 }
897