blob: 8453bb4836d3bbaa06a0503afdb8a7b2c30de577 [file] [log] [blame]
rsesek@chromium.orgc2d2b202012-05-17 00:23:30 +09001// Copyright (c) 2012 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
pastarmovj@chromium.org1602a472011-09-20 00:23:10 +09007#include <algorithm>
kalman@chromium.org829cf752012-09-12 12:39:35 +09008#include <ostream>
pastarmovj@chromium.org1602a472011-09-20 00:23:10 +09009
derat@chromium.orgaf8c8f02011-08-17 17:03:43 +090010#include "base/float_util.h"
kalman@chromium.org829cf752012-09-12 12:39:35 +090011#include "base/json/json_writer.h"
initial.commit3f4a7322008-07-27 06:49:38 +090012#include "base/logging.h"
scherkus@chromium.org2b923e72008-12-11 10:23:17 +090013#include "base/string_util.h"
brettw@chromium.org50c94652009-10-07 11:10:20 +090014#include "base/utf_string_conversions.h"
tony@chromium.orge4948ab2009-12-02 09:20:32 +090015
16namespace {
17
18// Make a deep copy of |node|, but don't include empty lists or dictionaries
19// in the copy. It's possible for this function to return NULL and it
20// expects |node| to always be non-NULL.
21Value* CopyWithoutEmptyChildren(Value* node) {
22 DCHECK(node);
23 switch (node->GetType()) {
24 case Value::TYPE_LIST: {
stevenjb@google.comf4f58272011-08-26 10:54:00 +090025 ListValue* list = static_cast<ListValue*>(node);
tony@chromium.orge4948ab2009-12-02 09:20:32 +090026 ListValue* copy = new ListValue;
27 for (ListValue::const_iterator it = list->begin(); it != list->end();
28 ++it) {
29 Value* child_copy = CopyWithoutEmptyChildren(*it);
30 if (child_copy)
31 copy->Append(child_copy);
32 }
33 if (!copy->empty())
34 return copy;
35
36 delete copy;
37 return NULL;
38 }
39
40 case Value::TYPE_DICTIONARY: {
41 DictionaryValue* dict = static_cast<DictionaryValue*>(node);
42 DictionaryValue* copy = new DictionaryValue;
43 for (DictionaryValue::key_iterator it = dict->begin_keys();
44 it != dict->end_keys(); ++it) {
45 Value* child = NULL;
46 bool rv = dict->GetWithoutPathExpansion(*it, &child);
47 DCHECK(rv);
48 Value* child_copy = CopyWithoutEmptyChildren(child);
49 if (child_copy)
50 copy->SetWithoutPathExpansion(*it, child_copy);
51 }
52 if (!copy->empty())
53 return copy;
54
55 delete copy;
56 return NULL;
57 }
58
59 default:
60 // For everything else, just make a copy.
61 return node->DeepCopy();
62 }
63}
64
pastarmovj@chromium.org1602a472011-09-20 00:23:10 +090065// A small functor for comparing Values for std::find_if and similar.
66class ValueEquals {
67 public:
68 // Pass the value against which all consecutive calls of the () operator will
69 // compare their argument to. This Value object must not be destroyed while
70 // the ValueEquals is in use.
71 ValueEquals(const Value* first) : first_(first) { }
72
73 bool operator ()(const Value* second) const {
74 return first_->Equals(second);
75 }
76
77 private:
78 const Value* first_;
79};
80
tony@chromium.orge4948ab2009-12-02 09:20:32 +090081} // namespace
initial.commit3f4a7322008-07-27 06:49:38 +090082
tfarina@chromium.orgde3ef412011-08-05 08:51:10 +090083namespace base {
84
initial.commit3f4a7322008-07-27 06:49:38 +090085///////////////////// Value ////////////////////
86
87Value::~Value() {
88}
89
90// static
91Value* Value::CreateNullValue() {
92 return new Value(TYPE_NULL);
93}
94
95// static
akalin@chromium.org810f92f2011-01-18 11:16:59 +090096FundamentalValue* Value::CreateBooleanValue(bool in_value) {
initial.commit3f4a7322008-07-27 06:49:38 +090097 return new FundamentalValue(in_value);
98}
99
100// static
akalin@chromium.org810f92f2011-01-18 11:16:59 +0900101FundamentalValue* Value::CreateIntegerValue(int in_value) {
initial.commit3f4a7322008-07-27 06:49:38 +0900102 return new FundamentalValue(in_value);
103}
104
105// static
arv@chromium.org13413eb2011-02-01 10:02:07 +0900106FundamentalValue* Value::CreateDoubleValue(double in_value) {
initial.commit3f4a7322008-07-27 06:49:38 +0900107 return new FundamentalValue(in_value);
108}
109
110// static
akalin@chromium.org810f92f2011-01-18 11:16:59 +0900111StringValue* Value::CreateStringValue(const std::string& in_value) {
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900112 return new StringValue(in_value);
113}
114
115// static
akalin@chromium.org810f92f2011-01-18 11:16:59 +0900116StringValue* Value::CreateStringValue(const string16& in_value) {
scherkus@chromium.org5ad62762008-12-11 07:30:57 +0900117 return new StringValue(in_value);
scherkus@chromium.org92bc0d42008-12-11 07:18:47 +0900118}
119
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900120bool Value::GetAsBoolean(bool* out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900121 return false;
122}
123
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900124bool Value::GetAsInteger(int* out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900125 return false;
126}
127
arv@chromium.org13413eb2011-02-01 10:02:07 +0900128bool Value::GetAsDouble(double* out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900129 return false;
130}
131
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900132bool Value::GetAsString(std::string* out_value) const {
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900133 return false;
134}
135
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900136bool Value::GetAsString(string16* out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900137 return false;
138}
139
scottbyer@google.com673b8762010-12-07 09:35:29 +0900140bool Value::GetAsList(ListValue** out_value) {
141 return false;
142}
143
bauerb@chromium.org6878e502011-07-12 18:04:38 +0900144bool Value::GetAsList(const ListValue** out_value) const {
145 return false;
146}
147
battre@chromium.org29eaa252011-11-26 10:11:44 +0900148bool Value::GetAsDictionary(DictionaryValue** out_value) {
149 return false;
150}
151
152bool Value::GetAsDictionary(const DictionaryValue** out_value) const {
153 return false;
154}
155
initial.commit3f4a7322008-07-27 06:49:38 +0900156Value* Value::DeepCopy() const {
157 // This method should only be getting called for null Values--all subclasses
158 // need to provide their own implementation;.
159 DCHECK(IsType(TYPE_NULL));
160 return CreateNullValue();
161}
162
163bool Value::Equals(const Value* other) const {
164 // This method should only be getting called for null Values--all subclasses
165 // need to provide their own implementation;.
166 DCHECK(IsType(TYPE_NULL));
167 return other->IsType(TYPE_NULL);
168}
169
bauerb@chromium.orgfbd55e12010-12-07 03:13:43 +0900170// static
171bool Value::Equals(const Value* a, const Value* b) {
172 if ((a == NULL) && (b == NULL)) return true;
173 if ((a == NULL) ^ (b == NULL)) return false;
174 return a->Equals(b);
175}
176
sky@chromium.org8d103c72011-08-25 06:17:59 +0900177Value::Value(Type type) : type_(type) {
erg@chromium.org493f5f62010-07-16 06:03:54 +0900178}
179
initial.commit3f4a7322008-07-27 06:49:38 +0900180///////////////////// FundamentalValue ////////////////////
181
erg@chromium.org493f5f62010-07-16 06:03:54 +0900182FundamentalValue::FundamentalValue(bool in_value)
183 : Value(TYPE_BOOLEAN), boolean_value_(in_value) {
184}
185
186FundamentalValue::FundamentalValue(int in_value)
187 : Value(TYPE_INTEGER), integer_value_(in_value) {
188}
189
190FundamentalValue::FundamentalValue(double in_value)
arv@chromium.org13413eb2011-02-01 10:02:07 +0900191 : Value(TYPE_DOUBLE), double_value_(in_value) {
derat@chromium.orga40267d2011-08-23 13:11:22 +0900192 if (!IsFinite(double_value_)) {
193 NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) "
194 << "values cannot be represented in JSON";
195 double_value_ = 0.0;
196 }
erg@chromium.org493f5f62010-07-16 06:03:54 +0900197}
198
initial.commit3f4a7322008-07-27 06:49:38 +0900199FundamentalValue::~FundamentalValue() {
200}
201
202bool FundamentalValue::GetAsBoolean(bool* out_value) const {
203 if (out_value && IsType(TYPE_BOOLEAN))
204 *out_value = boolean_value_;
205 return (IsType(TYPE_BOOLEAN));
206}
207
208bool FundamentalValue::GetAsInteger(int* out_value) const {
209 if (out_value && IsType(TYPE_INTEGER))
210 *out_value = integer_value_;
211 return (IsType(TYPE_INTEGER));
212}
213
arv@chromium.org13413eb2011-02-01 10:02:07 +0900214bool FundamentalValue::GetAsDouble(double* out_value) const {
215 if (out_value && IsType(TYPE_DOUBLE))
216 *out_value = double_value_;
yusukes@google.com0b18b532011-05-02 10:59:21 +0900217 else if (out_value && IsType(TYPE_INTEGER))
218 *out_value = integer_value_;
219 return (IsType(TYPE_DOUBLE) || IsType(TYPE_INTEGER));
initial.commit3f4a7322008-07-27 06:49:38 +0900220}
221
akalin@chromium.org810f92f2011-01-18 11:16:59 +0900222FundamentalValue* FundamentalValue::DeepCopy() const {
initial.commit3f4a7322008-07-27 06:49:38 +0900223 switch (GetType()) {
224 case TYPE_BOOLEAN:
225 return CreateBooleanValue(boolean_value_);
226
227 case TYPE_INTEGER:
228 return CreateIntegerValue(integer_value_);
229
arv@chromium.org13413eb2011-02-01 10:02:07 +0900230 case TYPE_DOUBLE:
231 return CreateDoubleValue(double_value_);
initial.commit3f4a7322008-07-27 06:49:38 +0900232
233 default:
234 NOTREACHED();
235 return NULL;
236 }
237}
238
239bool FundamentalValue::Equals(const Value* other) const {
240 if (other->GetType() != GetType())
241 return false;
242
243 switch (GetType()) {
244 case TYPE_BOOLEAN: {
245 bool lhs, rhs;
246 return GetAsBoolean(&lhs) && other->GetAsBoolean(&rhs) && lhs == rhs;
247 }
248 case TYPE_INTEGER: {
249 int lhs, rhs;
250 return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs;
251 }
arv@chromium.org13413eb2011-02-01 10:02:07 +0900252 case TYPE_DOUBLE: {
initial.commit3f4a7322008-07-27 06:49:38 +0900253 double lhs, rhs;
arv@chromium.org13413eb2011-02-01 10:02:07 +0900254 return GetAsDouble(&lhs) && other->GetAsDouble(&rhs) && lhs == rhs;
initial.commit3f4a7322008-07-27 06:49:38 +0900255 }
256 default:
257 NOTREACHED();
258 return false;
259 }
260}
261
262///////////////////// StringValue ////////////////////
263
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900264StringValue::StringValue(const std::string& in_value)
265 : Value(TYPE_STRING),
266 value_(in_value) {
267 DCHECK(IsStringUTF8(in_value));
268}
269
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900270StringValue::StringValue(const string16& in_value)
271 : Value(TYPE_STRING),
272 value_(UTF16ToUTF8(in_value)) {
273}
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900274
initial.commit3f4a7322008-07-27 06:49:38 +0900275StringValue::~StringValue() {
276}
277
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900278bool StringValue::GetAsString(std::string* out_value) const {
279 if (out_value)
280 *out_value = value_;
281 return true;
282}
283
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900284bool StringValue::GetAsString(string16* out_value) const {
285 if (out_value)
286 *out_value = UTF8ToUTF16(value_);
287 return true;
288}
289
akalin@chromium.org810f92f2011-01-18 11:16:59 +0900290StringValue* StringValue::DeepCopy() const {
initial.commit3f4a7322008-07-27 06:49:38 +0900291 return CreateStringValue(value_);
292}
293
294bool StringValue::Equals(const Value* other) const {
295 if (other->GetType() != GetType())
296 return false;
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900297 std::string lhs, rhs;
initial.commit3f4a7322008-07-27 06:49:38 +0900298 return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs;
299}
300
301///////////////////// BinaryValue ////////////////////
302
mitchellwrosen@chromium.org3897f9b2012-05-20 04:31:16 +0900303BinaryValue::~BinaryValue() {
jhawkins@chromium.org592520e2012-05-20 11:34:57 +0900304 DCHECK(buffer_);
305 if (buffer_)
306 delete[] buffer_;
307}
308
309// static
310BinaryValue* BinaryValue::Create(char* buffer, size_t size) {
311 if (!buffer)
312 return NULL;
313
314 return new BinaryValue(buffer, size);
initial.commit3f4a7322008-07-27 06:49:38 +0900315}
316
jcampan@chromium.orgd1105672009-09-15 01:56:12 +0900317// static
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900318BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer,
319 size_t size) {
jhawkins@chromium.org592520e2012-05-20 11:34:57 +0900320 if (!buffer)
321 return NULL;
322
initial.commit3f4a7322008-07-27 06:49:38 +0900323 char* buffer_copy = new char[size];
mmentovai@google.com4a5b6272008-08-07 00:46:59 +0900324 memcpy(buffer_copy, buffer, size);
jhawkins@chromium.org592520e2012-05-20 11:34:57 +0900325 return new BinaryValue(buffer_copy, size);
initial.commit3f4a7322008-07-27 06:49:38 +0900326}
327
akalin@chromium.org810f92f2011-01-18 11:16:59 +0900328BinaryValue* BinaryValue::DeepCopy() const {
jhawkins@chromium.org592520e2012-05-20 11:34:57 +0900329 return CreateWithCopiedBuffer(buffer_, size_);
initial.commit3f4a7322008-07-27 06:49:38 +0900330}
331
332bool BinaryValue::Equals(const Value* other) const {
333 if (other->GetType() != GetType())
334 return false;
335 const BinaryValue* other_binary = static_cast<const BinaryValue*>(other);
336 if (other_binary->size_ != size_)
337 return false;
jhawkins@chromium.org592520e2012-05-20 11:34:57 +0900338 return !memcmp(buffer_, other_binary->buffer_, size_);
339}
340
341BinaryValue::BinaryValue(char* buffer, size_t size)
342 : Value(TYPE_BINARY),
343 buffer_(buffer),
344 size_(size) {
345 DCHECK(buffer_);
erg@google.com67a25432011-01-08 05:23:43 +0900346}
347
initial.commit3f4a7322008-07-27 06:49:38 +0900348///////////////////// DictionaryValue ////////////////////
349
erg@chromium.org493f5f62010-07-16 06:03:54 +0900350DictionaryValue::DictionaryValue()
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900351 : Value(TYPE_DICTIONARY) {
erg@chromium.org493f5f62010-07-16 06:03:54 +0900352}
353
initial.commit3f4a7322008-07-27 06:49:38 +0900354DictionaryValue::~DictionaryValue() {
355 Clear();
356}
357
battre@chromium.org29eaa252011-11-26 10:11:44 +0900358bool DictionaryValue::GetAsDictionary(DictionaryValue** out_value) {
359 if (out_value)
360 *out_value = this;
361 return true;
362}
363
364bool DictionaryValue::GetAsDictionary(const DictionaryValue** out_value) const {
365 if (out_value)
366 *out_value = this;
367 return true;
368}
369
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900370bool DictionaryValue::HasKey(const std::string& key) const {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900371 DCHECK(IsStringUTF8(key));
tony@chromium.orge4948ab2009-12-02 09:20:32 +0900372 ValueMap::const_iterator current_entry = dictionary_.find(key);
373 DCHECK((current_entry == dictionary_.end()) || current_entry->second);
374 return current_entry != dictionary_.end();
375}
376
initial.commit3f4a7322008-07-27 06:49:38 +0900377void DictionaryValue::Clear() {
378 ValueMap::iterator dict_iterator = dictionary_.begin();
379 while (dict_iterator != dictionary_.end()) {
380 delete dict_iterator->second;
381 ++dict_iterator;
382 }
383
384 dictionary_.clear();
385}
386
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900387void DictionaryValue::Set(const std::string& path, Value* in_value) {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900388 DCHECK(IsStringUTF8(path));
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900389 DCHECK(in_value);
390
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900391 std::string current_path(path);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900392 DictionaryValue* current_dictionary = this;
393 for (size_t delimiter_position = current_path.find('.');
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900394 delimiter_position != std::string::npos;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900395 delimiter_position = current_path.find('.')) {
396 // Assume that we're indexing into a dictionary.
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900397 std::string key(current_path, 0, delimiter_position);
pkasting@chromium.org8535dc22009-11-26 06:02:24 +0900398 DictionaryValue* child_dictionary = NULL;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900399 if (!current_dictionary->GetDictionary(key, &child_dictionary)) {
400 child_dictionary = new DictionaryValue;
401 current_dictionary->SetWithoutPathExpansion(key, child_dictionary);
402 }
403
404 current_dictionary = child_dictionary;
405 current_path.erase(0, delimiter_position + 1);
406 }
407
408 current_dictionary->SetWithoutPathExpansion(current_path, in_value);
409}
410
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900411void DictionaryValue::SetBoolean(const std::string& path, bool in_value) {
412 Set(path, CreateBooleanValue(in_value));
413}
414
415void DictionaryValue::SetInteger(const std::string& path, int in_value) {
416 Set(path, CreateIntegerValue(in_value));
417}
418
arv@chromium.org13413eb2011-02-01 10:02:07 +0900419void DictionaryValue::SetDouble(const std::string& path, double in_value) {
420 Set(path, CreateDoubleValue(in_value));
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900421}
422
423void DictionaryValue::SetString(const std::string& path,
424 const std::string& in_value) {
425 Set(path, CreateStringValue(in_value));
426}
427
viettrungluu@chromium.orgb7b6aa02010-08-05 01:58:12 +0900428void DictionaryValue::SetString(const std::string& path,
429 const string16& in_value) {
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900430 Set(path, CreateStringValue(in_value));
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900431}
432
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900433void DictionaryValue::SetWithoutPathExpansion(const std::string& key,
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900434 Value* in_value) {
initial.commit3f4a7322008-07-27 06:49:38 +0900435 // If there's an existing value here, we need to delete it, because
436 // we own all our children.
grt@chromium.org4c73d402011-10-22 07:58:52 +0900437 std::pair<ValueMap::iterator, bool> ins_res =
438 dictionary_.insert(std::make_pair(key, in_value));
439 if (!ins_res.second) {
440 DCHECK_NE(ins_res.first->second, in_value); // This would be bogus
441 delete ins_res.first->second;
442 ins_res.first->second = in_value;
initial.commit3f4a7322008-07-27 06:49:38 +0900443 }
initial.commit3f4a7322008-07-27 06:49:38 +0900444}
445
kalman@chromium.org5081d8e2012-09-14 11:14:01 +0900446void DictionaryValue::SetBooleanWithoutPathExpansion(
447 const std::string& path, bool in_value) {
448 SetWithoutPathExpansion(path, CreateBooleanValue(in_value));
449}
450
451void DictionaryValue::SetIntegerWithoutPathExpansion(
452 const std::string& path, int in_value) {
453 SetWithoutPathExpansion(path, CreateIntegerValue(in_value));
454}
455
456void DictionaryValue::SetDoubleWithoutPathExpansion(
457 const std::string& path, double in_value) {
458 SetWithoutPathExpansion(path, CreateDoubleValue(in_value));
459}
460
461void DictionaryValue::SetStringWithoutPathExpansion(
462 const std::string& path, const std::string& in_value) {
463 SetWithoutPathExpansion(path, CreateStringValue(in_value));
464}
465
466void DictionaryValue::SetStringWithoutPathExpansion(
467 const std::string& path, const string16& in_value) {
468 SetWithoutPathExpansion(path, CreateStringValue(in_value));
469}
470
vabr@chromium.org74562432012-07-28 07:27:11 +0900471bool DictionaryValue::Get(
472 const std::string& path, const Value** out_value) const {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900473 DCHECK(IsStringUTF8(path));
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900474 std::string current_path(path);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900475 const DictionaryValue* current_dictionary = this;
476 for (size_t delimiter_position = current_path.find('.');
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900477 delimiter_position != std::string::npos;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900478 delimiter_position = current_path.find('.')) {
vabr@chromium.org74562432012-07-28 07:27:11 +0900479 const DictionaryValue* child_dictionary = NULL;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900480 if (!current_dictionary->GetDictionary(
481 current_path.substr(0, delimiter_position), &child_dictionary))
482 return false;
initial.commit3f4a7322008-07-27 06:49:38 +0900483
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900484 current_dictionary = child_dictionary;
485 current_path.erase(0, delimiter_position + 1);
initial.commit3f4a7322008-07-27 06:49:38 +0900486 }
487
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900488 return current_dictionary->GetWithoutPathExpansion(current_path, out_value);
initial.commit3f4a7322008-07-27 06:49:38 +0900489}
490
vabr@chromium.org74562432012-07-28 07:27:11 +0900491bool DictionaryValue::Get(const std::string& path, Value** out_value) {
492 return static_cast<const DictionaryValue&>(*this).Get(
493 path,
494 const_cast<const Value**>(out_value));
495}
496
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900497bool DictionaryValue::GetBoolean(const std::string& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900498 bool* bool_value) const {
vabr@chromium.org74562432012-07-28 07:27:11 +0900499 const Value* value;
initial.commit3f4a7322008-07-27 06:49:38 +0900500 if (!Get(path, &value))
501 return false;
502
503 return value->GetAsBoolean(bool_value);
504}
505
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900506bool DictionaryValue::GetInteger(const std::string& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900507 int* out_value) const {
vabr@chromium.org74562432012-07-28 07:27:11 +0900508 const Value* value;
initial.commit3f4a7322008-07-27 06:49:38 +0900509 if (!Get(path, &value))
510 return false;
511
512 return value->GetAsInteger(out_value);
513}
514
arv@chromium.org13413eb2011-02-01 10:02:07 +0900515bool DictionaryValue::GetDouble(const std::string& path,
516 double* out_value) const {
vabr@chromium.org74562432012-07-28 07:27:11 +0900517 const Value* value;
initial.commit3f4a7322008-07-27 06:49:38 +0900518 if (!Get(path, &value))
519 return false;
520
arv@chromium.org13413eb2011-02-01 10:02:07 +0900521 return value->GetAsDouble(out_value);
initial.commit3f4a7322008-07-27 06:49:38 +0900522}
523
evan@chromium.orgd9ab8de2010-02-19 22:32:16 +0900524bool DictionaryValue::GetString(const std::string& path,
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900525 std::string* out_value) const {
vabr@chromium.org74562432012-07-28 07:27:11 +0900526 const Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900527 if (!Get(path, &value))
528 return false;
529
530 return value->GetAsString(out_value);
531}
532
viettrungluu@chromium.org58767ef2010-08-05 04:35:33 +0900533bool DictionaryValue::GetString(const std::string& path,
534 string16* out_value) const {
vabr@chromium.org74562432012-07-28 07:27:11 +0900535 const Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900536 if (!Get(path, &value))
537 return false;
538
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900539 return value->GetAsString(out_value);
evan@chromium.orgd9ab8de2010-02-19 22:32:16 +0900540}
541
542bool DictionaryValue::GetStringASCII(const std::string& path,
543 std::string* out_value) const {
544 std::string out;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900545 if (!GetString(path, &out))
evan@chromium.orgd9ab8de2010-02-19 22:32:16 +0900546 return false;
547
548 if (!IsStringASCII(out)) {
549 NOTREACHED();
550 return false;
551 }
552
553 out_value->assign(out);
554 return true;
555}
556
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900557bool DictionaryValue::GetBinary(const std::string& path,
vabr@chromium.org74562432012-07-28 07:27:11 +0900558 const BinaryValue** out_value) const {
559 const Value* value;
initial.commit3f4a7322008-07-27 06:49:38 +0900560 bool result = Get(path, &value);
stevenjb@google.comf4f58272011-08-26 10:54:00 +0900561 if (!result || !value->IsType(TYPE_BINARY))
initial.commit3f4a7322008-07-27 06:49:38 +0900562 return false;
563
564 if (out_value)
vabr@chromium.org74562432012-07-28 07:27:11 +0900565 *out_value = static_cast<const BinaryValue*>(value);
initial.commit3f4a7322008-07-27 06:49:38 +0900566
567 return true;
568}
569
vabr@chromium.org74562432012-07-28 07:27:11 +0900570bool DictionaryValue::GetBinary(const std::string& path,
571 BinaryValue** out_value) {
572 return static_cast<const DictionaryValue&>(*this).GetBinary(
573 path,
574 const_cast<const BinaryValue**>(out_value));
575}
576
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900577bool DictionaryValue::GetDictionary(const std::string& path,
vabr@chromium.org74562432012-07-28 07:27:11 +0900578 const DictionaryValue** out_value) const {
579 const Value* value;
initial.commit3f4a7322008-07-27 06:49:38 +0900580 bool result = Get(path, &value);
581 if (!result || !value->IsType(TYPE_DICTIONARY))
582 return false;
583
584 if (out_value)
vabr@chromium.org74562432012-07-28 07:27:11 +0900585 *out_value = static_cast<const DictionaryValue*>(value);
initial.commit3f4a7322008-07-27 06:49:38 +0900586
587 return true;
588}
589
vabr@chromium.org74562432012-07-28 07:27:11 +0900590bool DictionaryValue::GetDictionary(const std::string& path,
591 DictionaryValue** out_value) {
592 return static_cast<const DictionaryValue&>(*this).GetDictionary(
593 path,
594 const_cast<const DictionaryValue**>(out_value));
595}
596
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900597bool DictionaryValue::GetList(const std::string& path,
vabr@chromium.org74562432012-07-28 07:27:11 +0900598 const ListValue** out_value) const {
599 const Value* value;
initial.commit3f4a7322008-07-27 06:49:38 +0900600 bool result = Get(path, &value);
stevenjb@google.comf4f58272011-08-26 10:54:00 +0900601 if (!result || !value->IsType(TYPE_LIST))
initial.commit3f4a7322008-07-27 06:49:38 +0900602 return false;
603
604 if (out_value)
vabr@chromium.org74562432012-07-28 07:27:11 +0900605 *out_value = static_cast<const ListValue*>(value);
initial.commit3f4a7322008-07-27 06:49:38 +0900606
607 return true;
608}
609
vabr@chromium.org74562432012-07-28 07:27:11 +0900610bool DictionaryValue::GetList(const std::string& path, ListValue** out_value) {
611 return static_cast<const DictionaryValue&>(*this).GetList(
612 path,
613 const_cast<const ListValue**>(out_value));
614}
615
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900616bool DictionaryValue::GetWithoutPathExpansion(const std::string& key,
vabr@chromium.org74562432012-07-28 07:27:11 +0900617 const Value** out_value) const {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900618 DCHECK(IsStringUTF8(key));
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900619 ValueMap::const_iterator entry_iterator = dictionary_.find(key);
620 if (entry_iterator == dictionary_.end())
621 return false;
initial.commit3f4a7322008-07-27 06:49:38 +0900622
vabr@chromium.org74562432012-07-28 07:27:11 +0900623 const Value* entry = entry_iterator->second;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900624 if (out_value)
625 *out_value = entry;
626 return true;
627}
628
vabr@chromium.org74562432012-07-28 07:27:11 +0900629bool DictionaryValue::GetWithoutPathExpansion(const std::string& key,
630 Value** out_value) {
631 return static_cast<const DictionaryValue&>(*this).GetWithoutPathExpansion(
632 key,
633 const_cast<const Value**>(out_value));
634}
635
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900636bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::string& key,
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900637 int* out_value) const {
vabr@chromium.org74562432012-07-28 07:27:11 +0900638 const Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900639 if (!GetWithoutPathExpansion(key, &value))
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900640 return false;
641
642 return value->GetAsInteger(out_value);
643}
644
arv@chromium.org13413eb2011-02-01 10:02:07 +0900645bool DictionaryValue::GetDoubleWithoutPathExpansion(const std::string& key,
646 double* out_value) const {
vabr@chromium.org74562432012-07-28 07:27:11 +0900647 const Value* value;
jam@chromium.org5bd53922010-10-01 16:28:25 +0900648 if (!GetWithoutPathExpansion(key, &value))
649 return false;
650
arv@chromium.org13413eb2011-02-01 10:02:07 +0900651 return value->GetAsDouble(out_value);
jam@chromium.org5bd53922010-10-01 16:28:25 +0900652}
653
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900654bool DictionaryValue::GetStringWithoutPathExpansion(
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900655 const std::string& key,
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900656 std::string* out_value) const {
vabr@chromium.org74562432012-07-28 07:27:11 +0900657 const Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900658 if (!GetWithoutPathExpansion(key, &value))
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900659 return false;
660
661 return value->GetAsString(out_value);
662}
663
vabr@chromium.org74562432012-07-28 07:27:11 +0900664bool DictionaryValue::GetStringWithoutPathExpansion(const std::string& key,
665 string16* out_value) const {
666 const Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900667 if (!GetWithoutPathExpansion(key, &value))
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900668 return false;
669
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900670 return value->GetAsString(out_value);
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900671}
672
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900673bool DictionaryValue::GetDictionaryWithoutPathExpansion(
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900674 const std::string& key,
vabr@chromium.org74562432012-07-28 07:27:11 +0900675 const DictionaryValue** out_value) const {
676 const Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900677 bool result = GetWithoutPathExpansion(key, &value);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900678 if (!result || !value->IsType(TYPE_DICTIONARY))
679 return false;
680
681 if (out_value)
vabr@chromium.org74562432012-07-28 07:27:11 +0900682 *out_value = static_cast<const DictionaryValue*>(value);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900683
684 return true;
685}
686
vabr@chromium.org74562432012-07-28 07:27:11 +0900687bool DictionaryValue::GetDictionaryWithoutPathExpansion(
688 const std::string& key,
689 DictionaryValue** out_value) {
690 const DictionaryValue& const_this =
691 static_cast<const DictionaryValue&>(*this);
692 return const_this.GetDictionaryWithoutPathExpansion(
693 key,
694 const_cast<const DictionaryValue**>(out_value));
695}
696
697bool DictionaryValue::GetListWithoutPathExpansion(
698 const std::string& key,
699 const ListValue** out_value) const {
700 const Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900701 bool result = GetWithoutPathExpansion(key, &value);
stevenjb@google.comf4f58272011-08-26 10:54:00 +0900702 if (!result || !value->IsType(TYPE_LIST))
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900703 return false;
704
705 if (out_value)
vabr@chromium.org74562432012-07-28 07:27:11 +0900706 *out_value = static_cast<const ListValue*>(value);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900707
708 return true;
709}
710
vabr@chromium.org74562432012-07-28 07:27:11 +0900711bool DictionaryValue::GetListWithoutPathExpansion(const std::string& key,
712 ListValue** out_value) {
713 return
714 static_cast<const DictionaryValue&>(*this).GetListWithoutPathExpansion(
715 key,
716 const_cast<const ListValue**>(out_value));
717}
718
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900719bool DictionaryValue::Remove(const std::string& path, Value** out_value) {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900720 DCHECK(IsStringUTF8(path));
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900721 std::string current_path(path);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900722 DictionaryValue* current_dictionary = this;
723 size_t delimiter_position = current_path.rfind('.');
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900724 if (delimiter_position != std::string::npos) {
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900725 if (!GetDictionary(current_path.substr(0, delimiter_position),
726 &current_dictionary))
727 return false;
728 current_path.erase(0, delimiter_position + 1);
initial.commit3f4a7322008-07-27 06:49:38 +0900729 }
730
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900731 return current_dictionary->RemoveWithoutPathExpansion(current_path,
732 out_value);
733}
734
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900735bool DictionaryValue::RemoveWithoutPathExpansion(const std::string& key,
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900736 Value** out_value) {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900737 DCHECK(IsStringUTF8(key));
initial.commit3f4a7322008-07-27 06:49:38 +0900738 ValueMap::iterator entry_iterator = dictionary_.find(key);
739 if (entry_iterator == dictionary_.end())
740 return false;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900741
initial.commit3f4a7322008-07-27 06:49:38 +0900742 Value* entry = entry_iterator->second;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900743 if (out_value)
744 *out_value = entry;
745 else
746 delete entry;
747 dictionary_.erase(entry_iterator);
748 return true;
initial.commit3f4a7322008-07-27 06:49:38 +0900749}
750
tony@chromium.orge4948ab2009-12-02 09:20:32 +0900751DictionaryValue* DictionaryValue::DeepCopyWithoutEmptyChildren() {
752 Value* copy = CopyWithoutEmptyChildren(this);
753 return copy ? static_cast<DictionaryValue*>(copy) : new DictionaryValue;
initial.commit3f4a7322008-07-27 06:49:38 +0900754}
755
mnissler@chromium.org17cee0e2010-05-14 22:17:40 +0900756void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) {
757 for (DictionaryValue::key_iterator key(dictionary->begin_keys());
758 key != dictionary->end_keys(); ++key) {
vabr@chromium.org74562432012-07-28 07:27:11 +0900759 const Value* merge_value;
mnissler@chromium.org17cee0e2010-05-14 22:17:40 +0900760 if (dictionary->GetWithoutPathExpansion(*key, &merge_value)) {
761 // Check whether we have to merge dictionaries.
762 if (merge_value->IsType(Value::TYPE_DICTIONARY)) {
763 DictionaryValue* sub_dict;
764 if (GetDictionaryWithoutPathExpansion(*key, &sub_dict)) {
765 sub_dict->MergeDictionary(
766 static_cast<const DictionaryValue*>(merge_value));
767 continue;
768 }
769 }
770 // All other cases: Make a copy and hook it up.
771 SetWithoutPathExpansion(*key, merge_value->DeepCopy());
772 }
773 }
774}
775
rsesek@chromium.orgc2d2b202012-05-17 00:23:30 +0900776void DictionaryValue::Swap(DictionaryValue* other) {
777 dictionary_.swap(other->dictionary_);
778}
779
hans@chromium.orgd5d38e32012-08-10 21:45:35 +0900780DictionaryValue::key_iterator::key_iterator(ValueMap::const_iterator itr) {
781 itr_ = itr;
782}
783
784DictionaryValue::key_iterator::key_iterator(const key_iterator& rhs) {
785 itr_ = rhs.itr_;
786}
787
788DictionaryValue::Iterator::Iterator(const DictionaryValue& target)
789 : target_(target),
790 it_(target.dictionary_.begin()) {}
791
akalin@chromium.org810f92f2011-01-18 11:16:59 +0900792DictionaryValue* DictionaryValue::DeepCopy() const {
erg@google.com67a25432011-01-08 05:23:43 +0900793 DictionaryValue* result = new DictionaryValue;
794
795 for (ValueMap::const_iterator current_entry(dictionary_.begin());
796 current_entry != dictionary_.end(); ++current_entry) {
797 result->SetWithoutPathExpansion(current_entry->first,
798 current_entry->second->DeepCopy());
799 }
800
801 return result;
802}
803
804bool DictionaryValue::Equals(const Value* other) const {
805 if (other->GetType() != GetType())
806 return false;
807
808 const DictionaryValue* other_dict =
809 static_cast<const DictionaryValue*>(other);
810 key_iterator lhs_it(begin_keys());
811 key_iterator rhs_it(other_dict->begin_keys());
812 while (lhs_it != end_keys() && rhs_it != other_dict->end_keys()) {
vabr@chromium.org74562432012-07-28 07:27:11 +0900813 const Value* lhs;
814 const Value* rhs;
erg@google.com67a25432011-01-08 05:23:43 +0900815 if (*lhs_it != *rhs_it ||
816 !GetWithoutPathExpansion(*lhs_it, &lhs) ||
817 !other_dict->GetWithoutPathExpansion(*rhs_it, &rhs) ||
818 !lhs->Equals(rhs)) {
819 return false;
820 }
821 ++lhs_it;
822 ++rhs_it;
823 }
824 if (lhs_it != end_keys() || rhs_it != other_dict->end_keys())
825 return false;
826
827 return true;
828}
829
initial.commit3f4a7322008-07-27 06:49:38 +0900830///////////////////// ListValue ////////////////////
831
erg@chromium.org493f5f62010-07-16 06:03:54 +0900832ListValue::ListValue() : Value(TYPE_LIST) {
833}
834
initial.commit3f4a7322008-07-27 06:49:38 +0900835ListValue::~ListValue() {
836 Clear();
837}
838
839void ListValue::Clear() {
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900840 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i)
841 delete *i;
initial.commit3f4a7322008-07-27 06:49:38 +0900842 list_.clear();
843}
844
845bool ListValue::Set(size_t index, Value* in_value) {
846 if (!in_value)
847 return false;
848
849 if (index >= list_.size()) {
850 // Pad out any intermediate indexes with null settings
851 while (index > list_.size())
852 Append(CreateNullValue());
853 Append(in_value);
854 } else {
855 DCHECK(list_[index] != in_value);
856 delete list_[index];
857 list_[index] = in_value;
858 }
859 return true;
860}
861
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +0900862bool ListValue::Get(size_t index, const Value** out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900863 if (index >= list_.size())
864 return false;
865
866 if (out_value)
867 *out_value = list_[index];
868
869 return true;
870}
871
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +0900872bool ListValue::Get(size_t index, Value** out_value) {
873 return static_cast<const ListValue&>(*this).Get(
874 index,
875 const_cast<const Value**>(out_value));
876}
877
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900878bool ListValue::GetBoolean(size_t index, bool* bool_value) const {
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +0900879 const Value* value;
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900880 if (!Get(index, &value))
881 return false;
882
883 return value->GetAsBoolean(bool_value);
884}
885
886bool ListValue::GetInteger(size_t index, int* out_value) const {
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +0900887 const Value* value;
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900888 if (!Get(index, &value))
889 return false;
890
891 return value->GetAsInteger(out_value);
892}
893
arv@chromium.org13413eb2011-02-01 10:02:07 +0900894bool ListValue::GetDouble(size_t index, double* out_value) const {
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +0900895 const Value* value;
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900896 if (!Get(index, &value))
897 return false;
898
arv@chromium.org13413eb2011-02-01 10:02:07 +0900899 return value->GetAsDouble(out_value);
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900900}
901
902bool ListValue::GetString(size_t index, std::string* out_value) const {
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +0900903 const Value* value;
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900904 if (!Get(index, &value))
905 return false;
906
907 return value->GetAsString(out_value);
908}
909
viettrungluu@chromium.org58767ef2010-08-05 04:35:33 +0900910bool ListValue::GetString(size_t index, string16* out_value) const {
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +0900911 const Value* value;
viettrungluu@chromium.org58767ef2010-08-05 04:35:33 +0900912 if (!Get(index, &value))
913 return false;
914
915 return value->GetAsString(out_value);
916}
917
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +0900918bool ListValue::GetBinary(size_t index, const BinaryValue** out_value) const {
919 const Value* value;
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900920 bool result = Get(index, &value);
921 if (!result || !value->IsType(TYPE_BINARY))
922 return false;
923
924 if (out_value)
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +0900925 *out_value = static_cast<const BinaryValue*>(value);
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900926
927 return true;
928}
929
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +0900930bool ListValue::GetBinary(size_t index, BinaryValue** out_value) {
931 return static_cast<const ListValue&>(*this).GetBinary(
932 index,
933 const_cast<const BinaryValue**>(out_value));
934}
935
936bool ListValue::GetDictionary(size_t index,
937 const DictionaryValue** out_value) const {
938 const Value* value;
initial.commit3f4a7322008-07-27 06:49:38 +0900939 bool result = Get(index, &value);
940 if (!result || !value->IsType(TYPE_DICTIONARY))
941 return false;
942
943 if (out_value)
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +0900944 *out_value = static_cast<const DictionaryValue*>(value);
initial.commit3f4a7322008-07-27 06:49:38 +0900945
946 return true;
947}
948
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +0900949bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) {
950 return static_cast<const ListValue&>(*this).GetDictionary(
951 index,
952 const_cast<const DictionaryValue**>(out_value));
953}
954
955bool ListValue::GetList(size_t index, const ListValue** out_value) const {
956 const Value* value;
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900957 bool result = Get(index, &value);
stevenjb@google.comf4f58272011-08-26 10:54:00 +0900958 if (!result || !value->IsType(TYPE_LIST))
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900959 return false;
960
961 if (out_value)
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +0900962 *out_value = static_cast<const ListValue*>(value);
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900963
964 return true;
965}
966
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +0900967bool ListValue::GetList(size_t index, ListValue** out_value) {
968 return static_cast<const ListValue&>(*this).GetList(
969 index,
970 const_cast<const ListValue**>(out_value));
971}
972
initial.commit3f4a7322008-07-27 06:49:38 +0900973bool ListValue::Remove(size_t index, Value** out_value) {
974 if (index >= list_.size())
975 return false;
976
977 if (out_value)
978 *out_value = list_[index];
979 else
980 delete list_[index];
981
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900982 list_.erase(list_.begin() + index);
initial.commit3f4a7322008-07-27 06:49:38 +0900983 return true;
984}
985
tfarina@chromium.org09cf4342011-08-14 02:34:31 +0900986bool ListValue::Remove(const Value& value, size_t* index) {
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900987 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) {
988 if ((*i)->Equals(&value)) {
tfarina@chromium.org09cf4342011-08-14 02:34:31 +0900989 size_t previous_index = i - list_.begin();
pkasting@chromium.orgdfe6a692009-12-01 04:59:11 +0900990 delete *i;
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900991 list_.erase(i);
robertshield@chromium.org9fb9e372010-03-23 05:12:50 +0900992
tfarina@chromium.org09cf4342011-08-14 02:34:31 +0900993 if (index)
994 *index = previous_index;
995 return true;
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900996 }
997 }
tfarina@chromium.org09cf4342011-08-14 02:34:31 +0900998 return false;
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900999}
1000
estade@chromium.org52852d52012-07-03 11:51:43 +09001001void ListValue::Erase(iterator iter, Value** out_value) {
1002 if (out_value)
1003 *out_value = *iter;
1004 else
1005 delete *iter;
1006
1007 list_.erase(iter);
1008}
1009
initial.commit3f4a7322008-07-27 06:49:38 +09001010void ListValue::Append(Value* in_value) {
1011 DCHECK(in_value);
1012 list_.push_back(in_value);
1013}
1014
kalman@chromium.org5081d8e2012-09-14 11:14:01 +09001015void ListValue::AppendBoolean(bool in_value) {
1016 Append(CreateBooleanValue(in_value));
1017}
1018
1019void ListValue::AppendInteger(int in_value) {
1020 Append(CreateIntegerValue(in_value));
1021}
1022
1023void ListValue::AppendDouble(double in_value) {
1024 Append(CreateDoubleValue(in_value));
1025}
1026
1027void ListValue::AppendString(const std::string& in_value) {
1028 Append(CreateStringValue(in_value));
1029}
1030
1031void ListValue::AppendString(const string16& in_value) {
1032 Append(CreateStringValue(in_value));
1033}
1034
1035void ListValue::AppendStrings(const std::vector<std::string>& in_values) {
1036 for (std::vector<std::string>::const_iterator it = in_values.begin();
1037 it != in_values.end(); ++it) {
1038 AppendString(*it);
1039 }
1040}
1041
1042void ListValue::AppendStrings(const std::vector<string16>& in_values) {
1043 for (std::vector<string16>::const_iterator it = in_values.begin();
1044 it != in_values.end(); ++it) {
1045 AppendString(*it);
1046 }
1047}
1048
zork@chromium.orgb5f742b2010-04-13 06:48:10 +09001049bool ListValue::AppendIfNotPresent(Value* in_value) {
1050 DCHECK(in_value);
ziadh@chromium.org5c7f6312010-07-19 17:00:42 +09001051 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i) {
markusheintz@chromium.org78621872011-03-18 22:56:38 +09001052 if ((*i)->Equals(in_value)) {
1053 delete in_value;
zork@chromium.orgb5f742b2010-04-13 06:48:10 +09001054 return false;
markusheintz@chromium.org78621872011-03-18 22:56:38 +09001055 }
zork@chromium.orgb5f742b2010-04-13 06:48:10 +09001056 }
1057 list_.push_back(in_value);
1058 return true;
1059}
1060
erikkay@chromium.org9034a232009-08-29 05:26:05 +09001061bool ListValue::Insert(size_t index, Value* in_value) {
1062 DCHECK(in_value);
jhawkins@chromium.org33edb6b2009-10-01 06:36:37 +09001063 if (index > list_.size())
erikkay@chromium.org9034a232009-08-29 05:26:05 +09001064 return false;
1065
1066 list_.insert(list_.begin() + index, in_value);
1067 return true;
1068}
1069
pastarmovj@chromium.org1602a472011-09-20 00:23:10 +09001070ListValue::const_iterator ListValue::Find(const Value& value) const {
1071 return std::find_if(list_.begin(), list_.end(), ValueEquals(&value));
1072}
1073
rsesek@chromium.orgc2d2b202012-05-17 00:23:30 +09001074void ListValue::Swap(ListValue* other) {
1075 list_.swap(other->list_);
1076}
1077
scottbyer@google.com673b8762010-12-07 09:35:29 +09001078bool ListValue::GetAsList(ListValue** out_value) {
1079 if (out_value)
1080 *out_value = this;
1081 return true;
1082}
1083
bauerb@chromium.org6878e502011-07-12 18:04:38 +09001084bool ListValue::GetAsList(const ListValue** out_value) const {
1085 if (out_value)
1086 *out_value = this;
1087 return true;
1088}
1089
akalin@chromium.org810f92f2011-01-18 11:16:59 +09001090ListValue* ListValue::DeepCopy() const {
initial.commit3f4a7322008-07-27 06:49:38 +09001091 ListValue* result = new ListValue;
1092
pkasting@chromium.org727139c2009-05-09 09:33:04 +09001093 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i)
1094 result->Append((*i)->DeepCopy());
initial.commit3f4a7322008-07-27 06:49:38 +09001095
1096 return result;
1097}
1098
1099bool ListValue::Equals(const Value* other) const {
1100 if (other->GetType() != GetType())
1101 return false;
1102
1103 const ListValue* other_list =
1104 static_cast<const ListValue*>(other);
1105 const_iterator lhs_it, rhs_it;
1106 for (lhs_it = begin(), rhs_it = other_list->begin();
1107 lhs_it != end() && rhs_it != other_list->end();
1108 ++lhs_it, ++rhs_it) {
1109 if (!(*lhs_it)->Equals(*rhs_it))
1110 return false;
1111 }
1112 if (lhs_it != end() || rhs_it != other_list->end())
1113 return false;
1114
1115 return true;
1116}
erg@chromium.org493f5f62010-07-16 06:03:54 +09001117
1118ValueSerializer::~ValueSerializer() {
1119}
tfarina@chromium.orgde3ef412011-08-05 08:51:10 +09001120
kalman@chromium.org829cf752012-09-12 12:39:35 +09001121std::ostream& operator<<(std::ostream& out, const Value& value) {
1122 std::string json;
1123 JSONWriter::WriteWithOptions(&value,
1124 JSONWriter::OPTIONS_PRETTY_PRINT,
1125 &json);
1126 return out << json;
1127}
1128
tfarina@chromium.orgde3ef412011-08-05 08:51:10 +09001129} // namespace base