blob: 8404d3efc5c1c37b89925fb398fd2b947f5038b6 [file] [log] [blame]
brettw@chromium.org50c94652009-10-07 11:10:20 +09001// Copyright (c) 2009 The Chromium Authors. All rights reserved.
license.botf003cfe2008-08-24 09:55:55 +09002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit3f4a7322008-07-27 06:49:38 +09004
5#include "base/logging.h"
scherkus@chromium.org2b923e72008-12-11 10:23:17 +09006#include "base/string_util.h"
brettw@chromium.org50c94652009-10-07 11:10:20 +09007#include "base/utf_string_conversions.h"
initial.commit3f4a7322008-07-27 06:49:38 +09008#include "base/values.h"
9
10///////////////////// Value ////////////////////
11
12Value::~Value() {
13}
14
15// static
16Value* Value::CreateNullValue() {
17 return new Value(TYPE_NULL);
18}
19
20// static
21Value* Value::CreateBooleanValue(bool in_value) {
22 return new FundamentalValue(in_value);
23}
24
25// static
26Value* Value::CreateIntegerValue(int in_value) {
27 return new FundamentalValue(in_value);
28}
29
30// static
31Value* Value::CreateRealValue(double in_value) {
32 return new FundamentalValue(in_value);
33}
34
35// static
scherkus@chromium.org2b923e72008-12-11 10:23:17 +090036Value* Value::CreateStringValue(const std::string& in_value) {
37 return new StringValue(in_value);
38}
39
40// static
scherkus@chromium.org92bc0d42008-12-11 07:18:47 +090041Value* Value::CreateStringValue(const std::wstring& in_value) {
scherkus@chromium.org5ad62762008-12-11 07:30:57 +090042 return new StringValue(in_value);
scherkus@chromium.org92bc0d42008-12-11 07:18:47 +090043}
44
45// static
initial.commit3f4a7322008-07-27 06:49:38 +090046BinaryValue* Value::CreateBinaryValue(char* buffer, size_t size) {
47 return BinaryValue::Create(buffer, size);
48}
49
50bool Value::GetAsBoolean(bool* in_value) const {
51 return false;
52}
53
54bool Value::GetAsInteger(int* in_value) const {
55 return false;
56}
57
58bool Value::GetAsReal(double* in_value) const {
59 return false;
60}
61
scherkus@chromium.org2b923e72008-12-11 10:23:17 +090062bool Value::GetAsString(std::string* in_value) const {
63 return false;
64}
65
initial.commit3f4a7322008-07-27 06:49:38 +090066bool Value::GetAsString(std::wstring* in_value) const {
67 return false;
68}
69
70Value* Value::DeepCopy() const {
71 // This method should only be getting called for null Values--all subclasses
72 // need to provide their own implementation;.
73 DCHECK(IsType(TYPE_NULL));
74 return CreateNullValue();
75}
76
77bool Value::Equals(const Value* other) const {
78 // This method should only be getting called for null Values--all subclasses
79 // need to provide their own implementation;.
80 DCHECK(IsType(TYPE_NULL));
81 return other->IsType(TYPE_NULL);
82}
83
84///////////////////// FundamentalValue ////////////////////
85
86FundamentalValue::~FundamentalValue() {
87}
88
89bool FundamentalValue::GetAsBoolean(bool* out_value) const {
90 if (out_value && IsType(TYPE_BOOLEAN))
91 *out_value = boolean_value_;
92 return (IsType(TYPE_BOOLEAN));
93}
94
95bool FundamentalValue::GetAsInteger(int* out_value) const {
96 if (out_value && IsType(TYPE_INTEGER))
97 *out_value = integer_value_;
98 return (IsType(TYPE_INTEGER));
99}
100
101bool FundamentalValue::GetAsReal(double* out_value) const {
102 if (out_value && IsType(TYPE_REAL))
103 *out_value = real_value_;
104 return (IsType(TYPE_REAL));
105}
106
107Value* FundamentalValue::DeepCopy() const {
108 switch (GetType()) {
109 case TYPE_BOOLEAN:
110 return CreateBooleanValue(boolean_value_);
111
112 case TYPE_INTEGER:
113 return CreateIntegerValue(integer_value_);
114
115 case TYPE_REAL:
116 return CreateRealValue(real_value_);
117
118 default:
119 NOTREACHED();
120 return NULL;
121 }
122}
123
124bool FundamentalValue::Equals(const Value* other) const {
125 if (other->GetType() != GetType())
126 return false;
127
128 switch (GetType()) {
129 case TYPE_BOOLEAN: {
130 bool lhs, rhs;
131 return GetAsBoolean(&lhs) && other->GetAsBoolean(&rhs) && lhs == rhs;
132 }
133 case TYPE_INTEGER: {
134 int lhs, rhs;
135 return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs;
136 }
137 case TYPE_REAL: {
138 double lhs, rhs;
139 return GetAsReal(&lhs) && other->GetAsReal(&rhs) && lhs == rhs;
140 }
141 default:
142 NOTREACHED();
143 return false;
144 }
145}
146
147///////////////////// StringValue ////////////////////
148
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900149StringValue::StringValue(const std::string& in_value)
150 : Value(TYPE_STRING),
151 value_(in_value) {
152 DCHECK(IsStringUTF8(in_value));
153}
154
155StringValue::StringValue(const std::wstring& in_value)
156 : Value(TYPE_STRING),
157 value_(WideToUTF8(in_value)) {
158}
159
initial.commit3f4a7322008-07-27 06:49:38 +0900160StringValue::~StringValue() {
161}
162
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900163bool StringValue::GetAsString(std::string* out_value) const {
164 if (out_value)
165 *out_value = value_;
166 return true;
167}
168
initial.commit3f4a7322008-07-27 06:49:38 +0900169bool StringValue::GetAsString(std::wstring* out_value) const {
170 if (out_value)
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900171 *out_value = UTF8ToWide(value_);
initial.commit3f4a7322008-07-27 06:49:38 +0900172 return true;
173}
174
175Value* StringValue::DeepCopy() const {
176 return CreateStringValue(value_);
177}
178
179bool StringValue::Equals(const Value* other) const {
180 if (other->GetType() != GetType())
181 return false;
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900182 std::string lhs, rhs;
initial.commit3f4a7322008-07-27 06:49:38 +0900183 return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs;
184}
185
186///////////////////// BinaryValue ////////////////////
187
jcampan@chromium.orgd1105672009-09-15 01:56:12 +0900188// static
initial.commit3f4a7322008-07-27 06:49:38 +0900189BinaryValue* BinaryValue::Create(char* buffer, size_t size) {
190 if (!buffer)
191 return NULL;
192
193 return new BinaryValue(buffer, size);
194}
195
jcampan@chromium.orgd1105672009-09-15 01:56:12 +0900196// static
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900197BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer,
198 size_t size) {
initial.commit3f4a7322008-07-27 06:49:38 +0900199 if (!buffer)
200 return NULL;
201
202 char* buffer_copy = new char[size];
mmentovai@google.com4a5b6272008-08-07 00:46:59 +0900203 memcpy(buffer_copy, buffer, size);
initial.commit3f4a7322008-07-27 06:49:38 +0900204 return new BinaryValue(buffer_copy, size);
205}
206
207
208BinaryValue::BinaryValue(char* buffer, size_t size)
209 : Value(TYPE_BINARY),
210 buffer_(buffer),
211 size_(size) {
212 DCHECK(buffer_);
213}
214
215BinaryValue::~BinaryValue() {
216 DCHECK(buffer_);
217 if (buffer_)
218 delete[] buffer_;
219}
220
221Value* BinaryValue::DeepCopy() const {
222 return CreateWithCopiedBuffer(buffer_, size_);
223}
224
225bool BinaryValue::Equals(const Value* other) const {
226 if (other->GetType() != GetType())
227 return false;
228 const BinaryValue* other_binary = static_cast<const BinaryValue*>(other);
229 if (other_binary->size_ != size_)
230 return false;
231 return !memcmp(buffer_, other_binary->buffer_, size_);
232}
233
234///////////////////// DictionaryValue ////////////////////
235
236DictionaryValue::~DictionaryValue() {
237 Clear();
238}
239
240void DictionaryValue::Clear() {
241 ValueMap::iterator dict_iterator = dictionary_.begin();
242 while (dict_iterator != dictionary_.end()) {
243 delete dict_iterator->second;
244 ++dict_iterator;
245 }
246
247 dictionary_.clear();
248}
249
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900250bool DictionaryValue::HasKey(const std::wstring& key) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900251 ValueMap::const_iterator current_entry = dictionary_.find(key);
252 DCHECK((current_entry == dictionary_.end()) || current_entry->second);
253 return current_entry != dictionary_.end();
254}
255
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900256void DictionaryValue::Set(const std::wstring& path, Value* in_value) {
257 DCHECK(in_value);
258
259 std::wstring current_path(path);
260 DictionaryValue* current_dictionary = this;
261 for (size_t delimiter_position = current_path.find('.');
262 delimiter_position != std::wstring::npos;
263 delimiter_position = current_path.find('.')) {
264 // Assume that we're indexing into a dictionary.
265 std::wstring key(current_path, 0, delimiter_position);
pkasting@chromium.org8535dc22009-11-26 06:02:24 +0900266 DictionaryValue* child_dictionary = NULL;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900267 if (!current_dictionary->GetDictionary(key, &child_dictionary)) {
268 child_dictionary = new DictionaryValue;
269 current_dictionary->SetWithoutPathExpansion(key, child_dictionary);
270 }
271
272 current_dictionary = child_dictionary;
273 current_path.erase(0, delimiter_position + 1);
274 }
275
276 current_dictionary->SetWithoutPathExpansion(current_path, in_value);
277}
278
279void DictionaryValue::SetBoolean(const std::wstring& path, bool in_value) {
280 Set(path, CreateBooleanValue(in_value));
281}
282
283void DictionaryValue::SetInteger(const std::wstring& path, int in_value) {
284 Set(path, CreateIntegerValue(in_value));
285}
286
287void DictionaryValue::SetReal(const std::wstring& path, double in_value) {
288 Set(path, CreateRealValue(in_value));
289}
290
291void DictionaryValue::SetString(const std::wstring& path,
292 const std::string& in_value) {
293 Set(path, CreateStringValue(in_value));
294}
295
296void DictionaryValue::SetString(const std::wstring& path,
297 const std::wstring& in_value) {
298 Set(path, CreateStringValue(in_value));
299}
300
301void DictionaryValue::SetWithoutPathExpansion(const std::wstring& key,
302 Value* in_value) {
initial.commit3f4a7322008-07-27 06:49:38 +0900303 // If there's an existing value here, we need to delete it, because
304 // we own all our children.
305 if (HasKey(key)) {
306 DCHECK(dictionary_[key] != in_value); // This would be bogus
307 delete dictionary_[key];
308 }
309
310 dictionary_[key] = in_value;
311}
312
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900313bool DictionaryValue::Get(const std::wstring& path, Value** out_value) const {
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900314 std::wstring current_path(path);
315 const DictionaryValue* current_dictionary = this;
316 for (size_t delimiter_position = current_path.find('.');
317 delimiter_position != std::wstring::npos;
318 delimiter_position = current_path.find('.')) {
pkasting@chromium.org8535dc22009-11-26 06:02:24 +0900319 DictionaryValue* child_dictionary = NULL;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900320 if (!current_dictionary->GetDictionary(
321 current_path.substr(0, delimiter_position), &child_dictionary))
322 return false;
initial.commit3f4a7322008-07-27 06:49:38 +0900323
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900324 current_dictionary = child_dictionary;
325 current_path.erase(0, delimiter_position + 1);
initial.commit3f4a7322008-07-27 06:49:38 +0900326 }
327
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900328 return current_dictionary->GetWithoutPathExpansion(current_path, out_value);
initial.commit3f4a7322008-07-27 06:49:38 +0900329}
330
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900331bool DictionaryValue::GetBoolean(const std::wstring& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900332 bool* bool_value) const {
333 Value* value;
334 if (!Get(path, &value))
335 return false;
336
337 return value->GetAsBoolean(bool_value);
338}
339
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900340bool DictionaryValue::GetInteger(const std::wstring& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900341 int* out_value) const {
342 Value* value;
343 if (!Get(path, &value))
344 return false;
345
346 return value->GetAsInteger(out_value);
347}
348
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900349bool DictionaryValue::GetReal(const std::wstring& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900350 double* out_value) const {
351 Value* value;
352 if (!Get(path, &value))
353 return false;
354
355 return value->GetAsReal(out_value);
356}
357
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900358bool DictionaryValue::GetString(const std::wstring& path,
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900359 std::string* out_value) const {
360 Value* value;
361 if (!Get(path, &value))
362 return false;
363
364 return value->GetAsString(out_value);
365}
366
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900367bool DictionaryValue::GetString(const std::wstring& path,
368 std::wstring* out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900369 Value* value;
370 if (!Get(path, &value))
371 return false;
372
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900373 return value->GetAsString(out_value);
initial.commit3f4a7322008-07-27 06:49:38 +0900374}
375
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900376bool DictionaryValue::GetBinary(const std::wstring& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900377 BinaryValue** out_value) const {
378 Value* value;
379 bool result = Get(path, &value);
380 if (!result || !value->IsType(TYPE_BINARY))
381 return false;
382
383 if (out_value)
384 *out_value = static_cast<BinaryValue*>(value);
385
386 return true;
387}
388
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900389bool DictionaryValue::GetDictionary(const std::wstring& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900390 DictionaryValue** out_value) const {
391 Value* value;
392 bool result = Get(path, &value);
393 if (!result || !value->IsType(TYPE_DICTIONARY))
394 return false;
395
396 if (out_value)
397 *out_value = static_cast<DictionaryValue*>(value);
398
399 return true;
400}
401
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900402bool DictionaryValue::GetList(const std::wstring& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900403 ListValue** out_value) const {
404 Value* value;
405 bool result = Get(path, &value);
406 if (!result || !value->IsType(TYPE_LIST))
407 return false;
408
409 if (out_value)
410 *out_value = static_cast<ListValue*>(value);
411
412 return true;
413}
414
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900415bool DictionaryValue::GetWithoutPathExpansion(const std::wstring& key,
416 Value** out_value) const {
417 ValueMap::const_iterator entry_iterator = dictionary_.find(key);
418 if (entry_iterator == dictionary_.end())
419 return false;
initial.commit3f4a7322008-07-27 06:49:38 +0900420
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900421 Value* entry = entry_iterator->second;
422 if (out_value)
423 *out_value = entry;
424 return true;
425}
426
427bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::wstring& path,
428 int* out_value) const {
429 Value* value;
430 if (!GetWithoutPathExpansion(path, &value))
431 return false;
432
433 return value->GetAsInteger(out_value);
434}
435
436bool DictionaryValue::GetStringWithoutPathExpansion(
437 const std::wstring& path,
438 std::string* out_value) const {
439 Value* value;
440 if (!GetWithoutPathExpansion(path, &value))
441 return false;
442
443 return value->GetAsString(out_value);
444}
445
446bool DictionaryValue::GetStringWithoutPathExpansion(
447 const std::wstring& path,
448 std::wstring* out_value) const {
449 Value* value;
450 if (!GetWithoutPathExpansion(path, &value))
451 return false;
452
453 return value->GetAsString(out_value);
454}
455
456bool DictionaryValue::GetDictionaryWithoutPathExpansion(
457 const std::wstring& path,
458 DictionaryValue** out_value) const {
459 Value* value;
460 bool result = GetWithoutPathExpansion(path, &value);
461 if (!result || !value->IsType(TYPE_DICTIONARY))
462 return false;
463
464 if (out_value)
465 *out_value = static_cast<DictionaryValue*>(value);
466
467 return true;
468}
469
470bool DictionaryValue::GetListWithoutPathExpansion(const std::wstring& path,
471 ListValue** out_value) const {
472 Value* value;
473 bool result = GetWithoutPathExpansion(path, &value);
474 if (!result || !value->IsType(TYPE_LIST))
475 return false;
476
477 if (out_value)
478 *out_value = static_cast<ListValue*>(value);
479
480 return true;
481}
482
483bool DictionaryValue::Remove(const std::wstring& path, Value** out_value) {
484 std::wstring current_path(path);
485 DictionaryValue* current_dictionary = this;
486 size_t delimiter_position = current_path.rfind('.');
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900487 if (delimiter_position != std::wstring::npos) {
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900488 if (!GetDictionary(current_path.substr(0, delimiter_position),
489 &current_dictionary))
490 return false;
491 current_path.erase(0, delimiter_position + 1);
initial.commit3f4a7322008-07-27 06:49:38 +0900492 }
493
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900494 return current_dictionary->RemoveWithoutPathExpansion(current_path,
495 out_value);
496}
497
498bool DictionaryValue::RemoveWithoutPathExpansion(const std::wstring& key,
499 Value** out_value) {
initial.commit3f4a7322008-07-27 06:49:38 +0900500 ValueMap::iterator entry_iterator = dictionary_.find(key);
501 if (entry_iterator == dictionary_.end())
502 return false;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900503
initial.commit3f4a7322008-07-27 06:49:38 +0900504 Value* entry = entry_iterator->second;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900505 if (out_value)
506 *out_value = entry;
507 else
508 delete entry;
509 dictionary_.erase(entry_iterator);
510 return true;
initial.commit3f4a7322008-07-27 06:49:38 +0900511}
512
513Value* DictionaryValue::DeepCopy() const {
514 DictionaryValue* result = new DictionaryValue;
515
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900516 for (ValueMap::const_iterator current_entry(dictionary_.begin());
517 current_entry != dictionary_.end(); ++current_entry) {
518 result->SetWithoutPathExpansion(current_entry->first,
519 current_entry->second->DeepCopy());
initial.commit3f4a7322008-07-27 06:49:38 +0900520 }
521
522 return result;
523}
524
525bool DictionaryValue::Equals(const Value* other) const {
526 if (other->GetType() != GetType())
527 return false;
528
529 const DictionaryValue* other_dict =
530 static_cast<const DictionaryValue*>(other);
531 key_iterator lhs_it(begin_keys());
532 key_iterator rhs_it(other_dict->begin_keys());
533 while (lhs_it != end_keys() && rhs_it != other_dict->end_keys()) {
534 Value* lhs;
535 Value* rhs;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900536 if (!GetWithoutPathExpansion(*lhs_it, &lhs) ||
537 !other_dict->GetWithoutPathExpansion(*rhs_it, &rhs) ||
initial.commit3f4a7322008-07-27 06:49:38 +0900538 !lhs->Equals(rhs)) {
539 return false;
540 }
541 ++lhs_it;
542 ++rhs_it;
543 }
544 if (lhs_it != end_keys() || rhs_it != other_dict->end_keys())
545 return false;
546
547 return true;
548}
549
550///////////////////// ListValue ////////////////////
551
552ListValue::~ListValue() {
553 Clear();
554}
555
556void ListValue::Clear() {
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900557 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i)
558 delete *i;
initial.commit3f4a7322008-07-27 06:49:38 +0900559 list_.clear();
560}
561
562bool ListValue::Set(size_t index, Value* in_value) {
563 if (!in_value)
564 return false;
565
566 if (index >= list_.size()) {
567 // Pad out any intermediate indexes with null settings
568 while (index > list_.size())
569 Append(CreateNullValue());
570 Append(in_value);
571 } else {
572 DCHECK(list_[index] != in_value);
573 delete list_[index];
574 list_[index] = in_value;
575 }
576 return true;
577}
578
579bool ListValue::Get(size_t index, Value** out_value) const {
580 if (index >= list_.size())
581 return false;
582
583 if (out_value)
584 *out_value = list_[index];
585
586 return true;
587}
588
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900589bool ListValue::GetBoolean(size_t index, bool* bool_value) const {
590 Value* value;
591 if (!Get(index, &value))
592 return false;
593
594 return value->GetAsBoolean(bool_value);
595}
596
597bool ListValue::GetInteger(size_t index, int* out_value) const {
598 Value* value;
599 if (!Get(index, &value))
600 return false;
601
602 return value->GetAsInteger(out_value);
603}
604
605bool ListValue::GetReal(size_t index, double* out_value) const {
606 Value* value;
607 if (!Get(index, &value))
608 return false;
609
610 return value->GetAsReal(out_value);
611}
612
613bool ListValue::GetString(size_t index, std::string* out_value) const {
614 Value* value;
615 if (!Get(index, &value))
616 return false;
617
618 return value->GetAsString(out_value);
619}
620
621bool ListValue::GetBinary(size_t index, BinaryValue** out_value) const {
622 Value* value;
623 bool result = Get(index, &value);
624 if (!result || !value->IsType(TYPE_BINARY))
625 return false;
626
627 if (out_value)
628 *out_value = static_cast<BinaryValue*>(value);
629
630 return true;
631}
632
633bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900634 Value* value;
635 bool result = Get(index, &value);
636 if (!result || !value->IsType(TYPE_DICTIONARY))
637 return false;
638
639 if (out_value)
640 *out_value = static_cast<DictionaryValue*>(value);
641
642 return true;
643}
644
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900645bool ListValue::GetList(size_t index, ListValue** out_value) const {
646 Value* value;
647 bool result = Get(index, &value);
648 if (!result || !value->IsType(TYPE_LIST))
649 return false;
650
651 if (out_value)
652 *out_value = static_cast<ListValue*>(value);
653
654 return true;
655}
656
initial.commit3f4a7322008-07-27 06:49:38 +0900657bool ListValue::Remove(size_t index, Value** out_value) {
658 if (index >= list_.size())
659 return false;
660
661 if (out_value)
662 *out_value = list_[index];
663 else
664 delete list_[index];
665
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900666 list_.erase(list_.begin() + index);
initial.commit3f4a7322008-07-27 06:49:38 +0900667 return true;
668}
669
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900670int ListValue::Remove(const Value& value) {
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900671 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) {
672 if ((*i)->Equals(&value)) {
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900673 size_t index = i - list_.begin();
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900674 list_.erase(i);
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900675 return index;
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900676 }
677 }
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900678 return -1;
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900679}
680
initial.commit3f4a7322008-07-27 06:49:38 +0900681void ListValue::Append(Value* in_value) {
682 DCHECK(in_value);
683 list_.push_back(in_value);
684}
685
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900686bool ListValue::Insert(size_t index, Value* in_value) {
687 DCHECK(in_value);
jhawkins@chromium.org33edb6b2009-10-01 06:36:37 +0900688 if (index > list_.size())
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900689 return false;
690
691 list_.insert(list_.begin() + index, in_value);
692 return true;
693}
694
initial.commit3f4a7322008-07-27 06:49:38 +0900695Value* ListValue::DeepCopy() const {
696 ListValue* result = new ListValue;
697
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900698 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i)
699 result->Append((*i)->DeepCopy());
initial.commit3f4a7322008-07-27 06:49:38 +0900700
701 return result;
702}
703
704bool ListValue::Equals(const Value* other) const {
705 if (other->GetType() != GetType())
706 return false;
707
708 const ListValue* other_list =
709 static_cast<const ListValue*>(other);
710 const_iterator lhs_it, rhs_it;
711 for (lhs_it = begin(), rhs_it = other_list->begin();
712 lhs_it != end() && rhs_it != other_list->end();
713 ++lhs_it, ++rhs_it) {
714 if (!(*lhs_it)->Equals(*rhs_it))
715 return false;
716 }
717 if (lhs_it != end() || rhs_it != other_list->end())
718 return false;
719
720 return true;
721}