blob: f214ead4ee41a03bc4aff0ba6ad914bfb9085a89 [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
tony@chromium.orge4948ab2009-12-02 09:20:32 +09005#include "base/values.h"
6
initial.commit3f4a7322008-07-27 06:49:38 +09007#include "base/logging.h"
scherkus@chromium.org2b923e72008-12-11 10:23:17 +09008#include "base/string_util.h"
brettw@chromium.org50c94652009-10-07 11:10:20 +09009#include "base/utf_string_conversions.h"
tony@chromium.orge4948ab2009-12-02 09:20:32 +090010
11namespace {
12
13// Make a deep copy of |node|, but don't include empty lists or dictionaries
14// in the copy. It's possible for this function to return NULL and it
15// expects |node| to always be non-NULL.
16Value* CopyWithoutEmptyChildren(Value* node) {
17 DCHECK(node);
18 switch (node->GetType()) {
19 case Value::TYPE_LIST: {
20 ListValue* list = static_cast<ListValue*>(node);
21 ListValue* copy = new ListValue;
22 for (ListValue::const_iterator it = list->begin(); it != list->end();
23 ++it) {
24 Value* child_copy = CopyWithoutEmptyChildren(*it);
25 if (child_copy)
26 copy->Append(child_copy);
27 }
28 if (!copy->empty())
29 return copy;
30
31 delete copy;
32 return NULL;
33 }
34
35 case Value::TYPE_DICTIONARY: {
36 DictionaryValue* dict = static_cast<DictionaryValue*>(node);
37 DictionaryValue* copy = new DictionaryValue;
38 for (DictionaryValue::key_iterator it = dict->begin_keys();
39 it != dict->end_keys(); ++it) {
40 Value* child = NULL;
41 bool rv = dict->GetWithoutPathExpansion(*it, &child);
42 DCHECK(rv);
43 Value* child_copy = CopyWithoutEmptyChildren(child);
44 if (child_copy)
45 copy->SetWithoutPathExpansion(*it, child_copy);
46 }
47 if (!copy->empty())
48 return copy;
49
50 delete copy;
51 return NULL;
52 }
53
54 default:
55 // For everything else, just make a copy.
56 return node->DeepCopy();
57 }
58}
59
60} // namespace
initial.commit3f4a7322008-07-27 06:49:38 +090061
62///////////////////// Value ////////////////////
63
64Value::~Value() {
65}
66
67// static
68Value* Value::CreateNullValue() {
69 return new Value(TYPE_NULL);
70}
71
72// static
73Value* Value::CreateBooleanValue(bool in_value) {
74 return new FundamentalValue(in_value);
75}
76
77// static
78Value* Value::CreateIntegerValue(int in_value) {
79 return new FundamentalValue(in_value);
80}
81
82// static
83Value* Value::CreateRealValue(double in_value) {
84 return new FundamentalValue(in_value);
85}
86
87// static
scherkus@chromium.org2b923e72008-12-11 10:23:17 +090088Value* Value::CreateStringValue(const std::string& in_value) {
89 return new StringValue(in_value);
90}
91
92// static
scherkus@chromium.org92bc0d42008-12-11 07:18:47 +090093Value* Value::CreateStringValue(const std::wstring& in_value) {
scherkus@chromium.org5ad62762008-12-11 07:30:57 +090094 return new StringValue(in_value);
scherkus@chromium.org92bc0d42008-12-11 07:18:47 +090095}
96
97// static
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +090098Value* Value::CreateStringValueFromUTF16(const string16& in_value) {
99 return new StringValue(in_value);
100}
101
102// static
initial.commit3f4a7322008-07-27 06:49:38 +0900103BinaryValue* Value::CreateBinaryValue(char* buffer, size_t size) {
104 return BinaryValue::Create(buffer, size);
105}
106
107bool Value::GetAsBoolean(bool* in_value) const {
108 return false;
109}
110
111bool Value::GetAsInteger(int* in_value) const {
112 return false;
113}
114
115bool Value::GetAsReal(double* in_value) const {
116 return false;
117}
118
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900119bool Value::GetAsString(std::string* in_value) const {
120 return false;
121}
122
initial.commit3f4a7322008-07-27 06:49:38 +0900123bool Value::GetAsString(std::wstring* in_value) const {
124 return false;
125}
126
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900127bool Value::GetAsUTF16(string16* out_value) const {
128 return false;
129}
130
initial.commit3f4a7322008-07-27 06:49:38 +0900131Value* 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
138bool 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
147FundamentalValue::~FundamentalValue() {
148}
149
150bool 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
156bool 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
162bool 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
168Value* 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
185bool 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
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900210StringValue::StringValue(const std::string& in_value)
211 : Value(TYPE_STRING),
212 value_(in_value) {
213 DCHECK(IsStringUTF8(in_value));
214}
215
216StringValue::StringValue(const std::wstring& in_value)
217 : Value(TYPE_STRING),
218 value_(WideToUTF8(in_value)) {
219}
220
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900221#if !defined(WCHAR_T_IS_UTF16)
222StringValue::StringValue(const string16& in_value)
223 : Value(TYPE_STRING),
224 value_(UTF16ToUTF8(in_value)) {
225}
226#endif
227
initial.commit3f4a7322008-07-27 06:49:38 +0900228StringValue::~StringValue() {
229}
230
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900231bool StringValue::GetAsString(std::string* out_value) const {
232 if (out_value)
233 *out_value = value_;
234 return true;
235}
236
initial.commit3f4a7322008-07-27 06:49:38 +0900237bool StringValue::GetAsString(std::wstring* out_value) const {
238 if (out_value)
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900239 *out_value = UTF8ToWide(value_);
initial.commit3f4a7322008-07-27 06:49:38 +0900240 return true;
241}
242
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900243bool StringValue::GetAsUTF16(string16* out_value) const {
244 if (out_value)
245 *out_value = UTF8ToUTF16(value_);
246 return true;
247}
248
initial.commit3f4a7322008-07-27 06:49:38 +0900249Value* StringValue::DeepCopy() const {
250 return CreateStringValue(value_);
251}
252
253bool StringValue::Equals(const Value* other) const {
254 if (other->GetType() != GetType())
255 return false;
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900256 std::string lhs, rhs;
initial.commit3f4a7322008-07-27 06:49:38 +0900257 return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs;
258}
259
260///////////////////// BinaryValue ////////////////////
261
jcampan@chromium.orgd1105672009-09-15 01:56:12 +0900262// static
initial.commit3f4a7322008-07-27 06:49:38 +0900263BinaryValue* BinaryValue::Create(char* buffer, size_t size) {
264 if (!buffer)
265 return NULL;
266
267 return new BinaryValue(buffer, size);
268}
269
jcampan@chromium.orgd1105672009-09-15 01:56:12 +0900270// static
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900271BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer,
272 size_t size) {
initial.commit3f4a7322008-07-27 06:49:38 +0900273 if (!buffer)
274 return NULL;
275
276 char* buffer_copy = new char[size];
mmentovai@google.com4a5b6272008-08-07 00:46:59 +0900277 memcpy(buffer_copy, buffer, size);
initial.commit3f4a7322008-07-27 06:49:38 +0900278 return new BinaryValue(buffer_copy, size);
279}
280
281
282BinaryValue::BinaryValue(char* buffer, size_t size)
283 : Value(TYPE_BINARY),
284 buffer_(buffer),
285 size_(size) {
286 DCHECK(buffer_);
287}
288
289BinaryValue::~BinaryValue() {
290 DCHECK(buffer_);
291 if (buffer_)
292 delete[] buffer_;
293}
294
295Value* BinaryValue::DeepCopy() const {
296 return CreateWithCopiedBuffer(buffer_, size_);
297}
298
299bool 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
310DictionaryValue::~DictionaryValue() {
311 Clear();
312}
313
tony@chromium.orge4948ab2009-12-02 09:20:32 +0900314Value* 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
326bool 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
351bool 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
evan@chromium.orgd9ab8de2010-02-19 22:32:16 +0900357bool DictionaryValue::HasKeyASCII(const std::string& key) const {
358 return HasKey(ASCIIToWide(key));
359}
360
initial.commit3f4a7322008-07-27 06:49:38 +0900361void DictionaryValue::Clear() {
362 ValueMap::iterator dict_iterator = dictionary_.begin();
363 while (dict_iterator != dictionary_.end()) {
364 delete dict_iterator->second;
365 ++dict_iterator;
366 }
367
368 dictionary_.clear();
369}
370
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900371void DictionaryValue::Set(const std::wstring& path, Value* in_value) {
372 DCHECK(in_value);
373
374 std::wstring current_path(path);
375 DictionaryValue* current_dictionary = this;
376 for (size_t delimiter_position = current_path.find('.');
377 delimiter_position != std::wstring::npos;
378 delimiter_position = current_path.find('.')) {
379 // Assume that we're indexing into a dictionary.
380 std::wstring key(current_path, 0, delimiter_position);
pkasting@chromium.org8535dc22009-11-26 06:02:24 +0900381 DictionaryValue* child_dictionary = NULL;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900382 if (!current_dictionary->GetDictionary(key, &child_dictionary)) {
383 child_dictionary = new DictionaryValue;
384 current_dictionary->SetWithoutPathExpansion(key, child_dictionary);
385 }
386
387 current_dictionary = child_dictionary;
388 current_path.erase(0, delimiter_position + 1);
389 }
390
391 current_dictionary->SetWithoutPathExpansion(current_path, in_value);
392}
393
394void DictionaryValue::SetBoolean(const std::wstring& path, bool in_value) {
395 Set(path, CreateBooleanValue(in_value));
396}
397
398void DictionaryValue::SetInteger(const std::wstring& path, int in_value) {
399 Set(path, CreateIntegerValue(in_value));
400}
401
402void DictionaryValue::SetReal(const std::wstring& path, double in_value) {
403 Set(path, CreateRealValue(in_value));
404}
405
406void DictionaryValue::SetString(const std::wstring& path,
407 const std::string& in_value) {
408 Set(path, CreateStringValue(in_value));
409}
410
411void DictionaryValue::SetString(const std::wstring& path,
412 const std::wstring& in_value) {
413 Set(path, CreateStringValue(in_value));
414}
415
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900416void DictionaryValue::SetStringFromUTF16(const std::wstring& path,
417 const string16& in_value) {
418 Set(path, CreateStringValueFromUTF16(in_value));
419}
420
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900421void DictionaryValue::SetWithoutPathExpansion(const std::wstring& key,
422 Value* in_value) {
initial.commit3f4a7322008-07-27 06:49:38 +0900423 // If there's an existing value here, we need to delete it, because
424 // we own all our children.
425 if (HasKey(key)) {
426 DCHECK(dictionary_[key] != in_value); // This would be bogus
427 delete dictionary_[key];
428 }
429
430 dictionary_[key] = in_value;
431}
432
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900433bool DictionaryValue::Get(const std::wstring& path, Value** out_value) const {
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900434 std::wstring current_path(path);
435 const DictionaryValue* current_dictionary = this;
436 for (size_t delimiter_position = current_path.find('.');
437 delimiter_position != std::wstring::npos;
438 delimiter_position = current_path.find('.')) {
pkasting@chromium.org8535dc22009-11-26 06:02:24 +0900439 DictionaryValue* child_dictionary = NULL;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900440 if (!current_dictionary->GetDictionary(
441 current_path.substr(0, delimiter_position), &child_dictionary))
442 return false;
initial.commit3f4a7322008-07-27 06:49:38 +0900443
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900444 current_dictionary = child_dictionary;
445 current_path.erase(0, delimiter_position + 1);
initial.commit3f4a7322008-07-27 06:49:38 +0900446 }
447
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900448 return current_dictionary->GetWithoutPathExpansion(current_path, out_value);
initial.commit3f4a7322008-07-27 06:49:38 +0900449}
450
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900451bool DictionaryValue::GetBoolean(const std::wstring& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900452 bool* bool_value) const {
453 Value* value;
454 if (!Get(path, &value))
455 return false;
456
457 return value->GetAsBoolean(bool_value);
458}
459
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900460bool DictionaryValue::GetInteger(const std::wstring& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900461 int* out_value) const {
462 Value* value;
463 if (!Get(path, &value))
464 return false;
465
466 return value->GetAsInteger(out_value);
467}
468
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900469bool DictionaryValue::GetReal(const std::wstring& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900470 double* out_value) const {
471 Value* value;
472 if (!Get(path, &value))
473 return false;
474
475 return value->GetAsReal(out_value);
476}
477
evan@chromium.orgd9ab8de2010-02-19 22:32:16 +0900478bool DictionaryValue::GetString(const std::string& path,
479 string16* out_value) const {
480 return GetStringAsUTF16(ASCIIToWide(path), out_value);
481}
482
483bool DictionaryValue::GetStringASCII(const std::string& path,
484 std::string* out_value) const {
485 std::string out;
486 if (!GetString(ASCIIToWide(path), &out))
487 return false;
488
489 if (!IsStringASCII(out)) {
490 NOTREACHED();
491 return false;
492 }
493
494 out_value->assign(out);
495 return true;
496}
497
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900498bool DictionaryValue::GetString(const std::wstring& path,
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900499 std::string* out_value) const {
500 Value* value;
501 if (!Get(path, &value))
502 return false;
503
504 return value->GetAsString(out_value);
505}
506
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900507bool DictionaryValue::GetString(const std::wstring& path,
508 std::wstring* out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900509 Value* value;
510 if (!Get(path, &value))
511 return false;
512
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900513 return value->GetAsString(out_value);
initial.commit3f4a7322008-07-27 06:49:38 +0900514}
515
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900516bool DictionaryValue::GetStringAsUTF16(const std::wstring& path,
517 string16* out_value) const {
518 Value* value;
519 if (!Get(path, &value))
520 return false;
521
522 return value->GetAsUTF16(out_value);
523}
524
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900525bool DictionaryValue::GetBinary(const std::wstring& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900526 BinaryValue** out_value) const {
527 Value* value;
528 bool result = Get(path, &value);
529 if (!result || !value->IsType(TYPE_BINARY))
530 return false;
531
532 if (out_value)
533 *out_value = static_cast<BinaryValue*>(value);
534
535 return true;
536}
537
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900538bool DictionaryValue::GetDictionary(const std::wstring& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900539 DictionaryValue** out_value) const {
540 Value* value;
541 bool result = Get(path, &value);
542 if (!result || !value->IsType(TYPE_DICTIONARY))
543 return false;
544
545 if (out_value)
546 *out_value = static_cast<DictionaryValue*>(value);
547
548 return true;
549}
550
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900551bool DictionaryValue::GetList(const std::wstring& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900552 ListValue** out_value) const {
553 Value* value;
554 bool result = Get(path, &value);
555 if (!result || !value->IsType(TYPE_LIST))
556 return false;
557
558 if (out_value)
559 *out_value = static_cast<ListValue*>(value);
560
561 return true;
562}
563
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900564bool DictionaryValue::GetWithoutPathExpansion(const std::wstring& key,
565 Value** out_value) const {
566 ValueMap::const_iterator entry_iterator = dictionary_.find(key);
567 if (entry_iterator == dictionary_.end())
568 return false;
initial.commit3f4a7322008-07-27 06:49:38 +0900569
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900570 Value* entry = entry_iterator->second;
571 if (out_value)
572 *out_value = entry;
573 return true;
574}
575
576bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::wstring& path,
577 int* out_value) const {
578 Value* value;
579 if (!GetWithoutPathExpansion(path, &value))
580 return false;
581
582 return value->GetAsInteger(out_value);
583}
584
585bool DictionaryValue::GetStringWithoutPathExpansion(
586 const std::wstring& path,
587 std::string* out_value) const {
588 Value* value;
589 if (!GetWithoutPathExpansion(path, &value))
590 return false;
591
592 return value->GetAsString(out_value);
593}
594
595bool DictionaryValue::GetStringWithoutPathExpansion(
596 const std::wstring& path,
597 std::wstring* out_value) const {
598 Value* value;
599 if (!GetWithoutPathExpansion(path, &value))
600 return false;
601
602 return value->GetAsString(out_value);
603}
604
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900605bool DictionaryValue::GetStringAsUTF16WithoutPathExpansion(
606 const std::wstring& path,
607 string16* out_value) const {
608 Value* value;
609 if (!GetWithoutPathExpansion(path, &value))
610 return false;
611
612 return value->GetAsUTF16(out_value);
613}
614
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900615bool DictionaryValue::GetDictionaryWithoutPathExpansion(
616 const std::wstring& path,
617 DictionaryValue** out_value) const {
618 Value* value;
619 bool result = GetWithoutPathExpansion(path, &value);
620 if (!result || !value->IsType(TYPE_DICTIONARY))
621 return false;
622
623 if (out_value)
624 *out_value = static_cast<DictionaryValue*>(value);
625
626 return true;
627}
628
629bool DictionaryValue::GetListWithoutPathExpansion(const std::wstring& path,
630 ListValue** out_value) const {
631 Value* value;
632 bool result = GetWithoutPathExpansion(path, &value);
633 if (!result || !value->IsType(TYPE_LIST))
634 return false;
635
636 if (out_value)
637 *out_value = static_cast<ListValue*>(value);
638
639 return true;
640}
641
642bool DictionaryValue::Remove(const std::wstring& path, Value** out_value) {
643 std::wstring current_path(path);
644 DictionaryValue* current_dictionary = this;
645 size_t delimiter_position = current_path.rfind('.');
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900646 if (delimiter_position != std::wstring::npos) {
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900647 if (!GetDictionary(current_path.substr(0, delimiter_position),
648 &current_dictionary))
649 return false;
650 current_path.erase(0, delimiter_position + 1);
initial.commit3f4a7322008-07-27 06:49:38 +0900651 }
652
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900653 return current_dictionary->RemoveWithoutPathExpansion(current_path,
654 out_value);
655}
656
657bool DictionaryValue::RemoveWithoutPathExpansion(const std::wstring& key,
658 Value** out_value) {
initial.commit3f4a7322008-07-27 06:49:38 +0900659 ValueMap::iterator entry_iterator = dictionary_.find(key);
660 if (entry_iterator == dictionary_.end())
661 return false;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900662
initial.commit3f4a7322008-07-27 06:49:38 +0900663 Value* entry = entry_iterator->second;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900664 if (out_value)
665 *out_value = entry;
666 else
667 delete entry;
668 dictionary_.erase(entry_iterator);
669 return true;
initial.commit3f4a7322008-07-27 06:49:38 +0900670}
671
tony@chromium.orge4948ab2009-12-02 09:20:32 +0900672DictionaryValue* DictionaryValue::DeepCopyWithoutEmptyChildren() {
673 Value* copy = CopyWithoutEmptyChildren(this);
674 return copy ? static_cast<DictionaryValue*>(copy) : new DictionaryValue;
initial.commit3f4a7322008-07-27 06:49:38 +0900675}
676
677///////////////////// ListValue ////////////////////
678
679ListValue::~ListValue() {
680 Clear();
681}
682
683void ListValue::Clear() {
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900684 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i)
685 delete *i;
initial.commit3f4a7322008-07-27 06:49:38 +0900686 list_.clear();
687}
688
689bool ListValue::Set(size_t index, Value* in_value) {
690 if (!in_value)
691 return false;
692
693 if (index >= list_.size()) {
694 // Pad out any intermediate indexes with null settings
695 while (index > list_.size())
696 Append(CreateNullValue());
697 Append(in_value);
698 } else {
699 DCHECK(list_[index] != in_value);
700 delete list_[index];
701 list_[index] = in_value;
702 }
703 return true;
704}
705
706bool ListValue::Get(size_t index, Value** out_value) const {
707 if (index >= list_.size())
708 return false;
709
710 if (out_value)
711 *out_value = list_[index];
712
713 return true;
714}
715
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900716bool ListValue::GetBoolean(size_t index, bool* bool_value) const {
717 Value* value;
718 if (!Get(index, &value))
719 return false;
720
721 return value->GetAsBoolean(bool_value);
722}
723
724bool ListValue::GetInteger(size_t index, int* out_value) const {
725 Value* value;
726 if (!Get(index, &value))
727 return false;
728
729 return value->GetAsInteger(out_value);
730}
731
732bool ListValue::GetReal(size_t index, double* out_value) const {
733 Value* value;
734 if (!Get(index, &value))
735 return false;
736
737 return value->GetAsReal(out_value);
738}
739
740bool ListValue::GetString(size_t index, std::string* out_value) const {
741 Value* value;
742 if (!Get(index, &value))
743 return false;
744
745 return value->GetAsString(out_value);
746}
747
estade@chromium.org8f158c32009-12-18 11:39:16 +0900748bool ListValue::GetString(size_t index, std::wstring* out_value) const {
749 Value* value;
750 if (!Get(index, &value))
751 return false;
752
753 return value->GetAsString(out_value);
754}
755
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900756bool ListValue::GetStringAsUTF16(size_t index, string16* out_value) const {
757 Value* value;
758 if (!Get(index, &value))
759 return false;
760
761 return value->GetAsUTF16(out_value);
762}
763
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900764bool ListValue::GetBinary(size_t index, BinaryValue** out_value) const {
765 Value* value;
766 bool result = Get(index, &value);
767 if (!result || !value->IsType(TYPE_BINARY))
768 return false;
769
770 if (out_value)
771 *out_value = static_cast<BinaryValue*>(value);
772
773 return true;
774}
775
776bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900777 Value* value;
778 bool result = Get(index, &value);
779 if (!result || !value->IsType(TYPE_DICTIONARY))
780 return false;
781
782 if (out_value)
783 *out_value = static_cast<DictionaryValue*>(value);
784
785 return true;
786}
787
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900788bool ListValue::GetList(size_t index, ListValue** out_value) const {
789 Value* value;
790 bool result = Get(index, &value);
791 if (!result || !value->IsType(TYPE_LIST))
792 return false;
793
794 if (out_value)
795 *out_value = static_cast<ListValue*>(value);
796
797 return true;
798}
799
initial.commit3f4a7322008-07-27 06:49:38 +0900800bool ListValue::Remove(size_t index, Value** out_value) {
801 if (index >= list_.size())
802 return false;
803
804 if (out_value)
805 *out_value = list_[index];
806 else
807 delete list_[index];
808
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900809 list_.erase(list_.begin() + index);
initial.commit3f4a7322008-07-27 06:49:38 +0900810 return true;
811}
812
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900813int ListValue::Remove(const Value& value) {
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900814 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) {
815 if ((*i)->Equals(&value)) {
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900816 size_t index = i - list_.begin();
pkasting@chromium.orgdfe6a692009-12-01 04:59:11 +0900817 delete *i;
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900818 list_.erase(i);
robertshield@chromium.org9fb9e372010-03-23 05:12:50 +0900819
820 // TODO(anyone): Returning a signed int type here is just wrong.
821 // Change this interface to return a size_t.
822 DCHECK(index <= INT_MAX);
823 int return_index = static_cast<int>(index);
824 return return_index;
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900825 }
826 }
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900827 return -1;
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900828}
829
initial.commit3f4a7322008-07-27 06:49:38 +0900830void ListValue::Append(Value* in_value) {
831 DCHECK(in_value);
832 list_.push_back(in_value);
833}
834
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900835bool ListValue::Insert(size_t index, Value* in_value) {
836 DCHECK(in_value);
jhawkins@chromium.org33edb6b2009-10-01 06:36:37 +0900837 if (index > list_.size())
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900838 return false;
839
840 list_.insert(list_.begin() + index, in_value);
841 return true;
842}
843
initial.commit3f4a7322008-07-27 06:49:38 +0900844Value* ListValue::DeepCopy() const {
845 ListValue* result = new ListValue;
846
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900847 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i)
848 result->Append((*i)->DeepCopy());
initial.commit3f4a7322008-07-27 06:49:38 +0900849
850 return result;
851}
852
853bool ListValue::Equals(const Value* other) const {
854 if (other->GetType() != GetType())
855 return false;
856
857 const ListValue* other_list =
858 static_cast<const ListValue*>(other);
859 const_iterator lhs_it, rhs_it;
860 for (lhs_it = begin(), rhs_it = other_list->begin();
861 lhs_it != end() && rhs_it != other_list->end();
862 ++lhs_it, ++rhs_it) {
863 if (!(*lhs_it)->Equals(*rhs_it))
864 return false;
865 }
866 if (lhs_it != end() || rhs_it != other_list->end())
867 return false;
868
869 return true;
870}