blob: d561d68377fa1f8c6d2e4d1fa2f6a3eee9413c9f [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>
8
derat@chromium.orgaf8c8f02011-08-17 17:03:43 +09009#include "base/float_util.h"
initial.commit3f4a7322008-07-27 06:49:38 +090010#include "base/logging.h"
scherkus@chromium.org2b923e72008-12-11 10:23:17 +090011#include "base/string_util.h"
brettw@chromium.org50c94652009-10-07 11:10:20 +090012#include "base/utf_string_conversions.h"
tony@chromium.orge4948ab2009-12-02 09:20:32 +090013
14namespace {
15
16// Make a deep copy of |node|, but don't include empty lists or dictionaries
17// in the copy. It's possible for this function to return NULL and it
18// expects |node| to always be non-NULL.
19Value* CopyWithoutEmptyChildren(Value* node) {
20 DCHECK(node);
21 switch (node->GetType()) {
22 case Value::TYPE_LIST: {
stevenjb@google.comf4f58272011-08-26 10:54:00 +090023 ListValue* list = static_cast<ListValue*>(node);
tony@chromium.orge4948ab2009-12-02 09:20:32 +090024 ListValue* copy = new ListValue;
25 for (ListValue::const_iterator it = list->begin(); it != list->end();
26 ++it) {
27 Value* child_copy = CopyWithoutEmptyChildren(*it);
28 if (child_copy)
29 copy->Append(child_copy);
30 }
31 if (!copy->empty())
32 return copy;
33
34 delete copy;
35 return NULL;
36 }
37
38 case Value::TYPE_DICTIONARY: {
39 DictionaryValue* dict = static_cast<DictionaryValue*>(node);
40 DictionaryValue* copy = new DictionaryValue;
41 for (DictionaryValue::key_iterator it = dict->begin_keys();
42 it != dict->end_keys(); ++it) {
43 Value* child = NULL;
44 bool rv = dict->GetWithoutPathExpansion(*it, &child);
45 DCHECK(rv);
46 Value* child_copy = CopyWithoutEmptyChildren(child);
47 if (child_copy)
48 copy->SetWithoutPathExpansion(*it, child_copy);
49 }
50 if (!copy->empty())
51 return copy;
52
53 delete copy;
54 return NULL;
55 }
56
57 default:
58 // For everything else, just make a copy.
59 return node->DeepCopy();
60 }
61}
62
pastarmovj@chromium.org1602a472011-09-20 00:23:10 +090063// A small functor for comparing Values for std::find_if and similar.
64class ValueEquals {
65 public:
66 // Pass the value against which all consecutive calls of the () operator will
67 // compare their argument to. This Value object must not be destroyed while
68 // the ValueEquals is in use.
69 ValueEquals(const Value* first) : first_(first) { }
70
71 bool operator ()(const Value* second) const {
72 return first_->Equals(second);
73 }
74
75 private:
76 const Value* first_;
77};
78
tony@chromium.orge4948ab2009-12-02 09:20:32 +090079} // namespace
initial.commit3f4a7322008-07-27 06:49:38 +090080
tfarina@chromium.orgde3ef412011-08-05 08:51:10 +090081namespace base {
82
initial.commit3f4a7322008-07-27 06:49:38 +090083///////////////////// Value ////////////////////
84
85Value::~Value() {
86}
87
88// static
89Value* Value::CreateNullValue() {
90 return new Value(TYPE_NULL);
91}
92
93// static
akalin@chromium.org810f92f2011-01-18 11:16:59 +090094FundamentalValue* Value::CreateBooleanValue(bool in_value) {
initial.commit3f4a7322008-07-27 06:49:38 +090095 return new FundamentalValue(in_value);
96}
97
98// static
akalin@chromium.org810f92f2011-01-18 11:16:59 +090099FundamentalValue* Value::CreateIntegerValue(int in_value) {
initial.commit3f4a7322008-07-27 06:49:38 +0900100 return new FundamentalValue(in_value);
101}
102
103// static
arv@chromium.org13413eb2011-02-01 10:02:07 +0900104FundamentalValue* Value::CreateDoubleValue(double in_value) {
initial.commit3f4a7322008-07-27 06:49:38 +0900105 return new FundamentalValue(in_value);
106}
107
108// static
akalin@chromium.org810f92f2011-01-18 11:16:59 +0900109StringValue* Value::CreateStringValue(const std::string& in_value) {
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900110 return new StringValue(in_value);
111}
112
113// static
akalin@chromium.org810f92f2011-01-18 11:16:59 +0900114StringValue* Value::CreateStringValue(const string16& in_value) {
scherkus@chromium.org5ad62762008-12-11 07:30:57 +0900115 return new StringValue(in_value);
scherkus@chromium.org92bc0d42008-12-11 07:18:47 +0900116}
117
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900118bool Value::GetAsBoolean(bool* out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900119 return false;
120}
121
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900122bool Value::GetAsInteger(int* out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900123 return false;
124}
125
arv@chromium.org13413eb2011-02-01 10:02:07 +0900126bool Value::GetAsDouble(double* out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900127 return false;
128}
129
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900130bool Value::GetAsString(std::string* out_value) const {
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900131 return false;
132}
133
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900134bool Value::GetAsString(string16* out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900135 return false;
136}
137
scottbyer@google.com673b8762010-12-07 09:35:29 +0900138bool Value::GetAsList(ListValue** out_value) {
139 return false;
140}
141
bauerb@chromium.org6878e502011-07-12 18:04:38 +0900142bool Value::GetAsList(const ListValue** out_value) const {
143 return false;
144}
145
battre@chromium.org29eaa252011-11-26 10:11:44 +0900146bool Value::GetAsDictionary(DictionaryValue** out_value) {
147 return false;
148}
149
150bool Value::GetAsDictionary(const DictionaryValue** out_value) const {
151 return false;
152}
153
initial.commit3f4a7322008-07-27 06:49:38 +0900154Value* Value::DeepCopy() const {
155 // This method should only be getting called for null Values--all subclasses
156 // need to provide their own implementation;.
157 DCHECK(IsType(TYPE_NULL));
158 return CreateNullValue();
159}
160
161bool Value::Equals(const Value* other) const {
162 // This method should only be getting called for null Values--all subclasses
163 // need to provide their own implementation;.
164 DCHECK(IsType(TYPE_NULL));
165 return other->IsType(TYPE_NULL);
166}
167
bauerb@chromium.orgfbd55e12010-12-07 03:13:43 +0900168// static
169bool Value::Equals(const Value* a, const Value* b) {
170 if ((a == NULL) && (b == NULL)) return true;
171 if ((a == NULL) ^ (b == NULL)) return false;
172 return a->Equals(b);
173}
174
sky@chromium.org8d103c72011-08-25 06:17:59 +0900175Value::Value(Type type) : type_(type) {
erg@chromium.org493f5f62010-07-16 06:03:54 +0900176}
177
initial.commit3f4a7322008-07-27 06:49:38 +0900178///////////////////// FundamentalValue ////////////////////
179
erg@chromium.org493f5f62010-07-16 06:03:54 +0900180FundamentalValue::FundamentalValue(bool in_value)
181 : Value(TYPE_BOOLEAN), boolean_value_(in_value) {
182}
183
184FundamentalValue::FundamentalValue(int in_value)
185 : Value(TYPE_INTEGER), integer_value_(in_value) {
186}
187
188FundamentalValue::FundamentalValue(double in_value)
arv@chromium.org13413eb2011-02-01 10:02:07 +0900189 : Value(TYPE_DOUBLE), double_value_(in_value) {
derat@chromium.orga40267d2011-08-23 13:11:22 +0900190 if (!IsFinite(double_value_)) {
191 NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) "
192 << "values cannot be represented in JSON";
193 double_value_ = 0.0;
194 }
erg@chromium.org493f5f62010-07-16 06:03:54 +0900195}
196
initial.commit3f4a7322008-07-27 06:49:38 +0900197FundamentalValue::~FundamentalValue() {
198}
199
200bool FundamentalValue::GetAsBoolean(bool* out_value) const {
201 if (out_value && IsType(TYPE_BOOLEAN))
202 *out_value = boolean_value_;
203 return (IsType(TYPE_BOOLEAN));
204}
205
206bool FundamentalValue::GetAsInteger(int* out_value) const {
207 if (out_value && IsType(TYPE_INTEGER))
208 *out_value = integer_value_;
209 return (IsType(TYPE_INTEGER));
210}
211
arv@chromium.org13413eb2011-02-01 10:02:07 +0900212bool FundamentalValue::GetAsDouble(double* out_value) const {
213 if (out_value && IsType(TYPE_DOUBLE))
214 *out_value = double_value_;
yusukes@google.com0b18b532011-05-02 10:59:21 +0900215 else if (out_value && IsType(TYPE_INTEGER))
216 *out_value = integer_value_;
217 return (IsType(TYPE_DOUBLE) || IsType(TYPE_INTEGER));
initial.commit3f4a7322008-07-27 06:49:38 +0900218}
219
akalin@chromium.org810f92f2011-01-18 11:16:59 +0900220FundamentalValue* FundamentalValue::DeepCopy() const {
initial.commit3f4a7322008-07-27 06:49:38 +0900221 switch (GetType()) {
222 case TYPE_BOOLEAN:
223 return CreateBooleanValue(boolean_value_);
224
225 case TYPE_INTEGER:
226 return CreateIntegerValue(integer_value_);
227
arv@chromium.org13413eb2011-02-01 10:02:07 +0900228 case TYPE_DOUBLE:
229 return CreateDoubleValue(double_value_);
initial.commit3f4a7322008-07-27 06:49:38 +0900230
231 default:
232 NOTREACHED();
233 return NULL;
234 }
235}
236
237bool FundamentalValue::Equals(const Value* other) const {
238 if (other->GetType() != GetType())
239 return false;
240
241 switch (GetType()) {
242 case TYPE_BOOLEAN: {
243 bool lhs, rhs;
244 return GetAsBoolean(&lhs) && other->GetAsBoolean(&rhs) && lhs == rhs;
245 }
246 case TYPE_INTEGER: {
247 int lhs, rhs;
248 return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs;
249 }
arv@chromium.org13413eb2011-02-01 10:02:07 +0900250 case TYPE_DOUBLE: {
initial.commit3f4a7322008-07-27 06:49:38 +0900251 double lhs, rhs;
arv@chromium.org13413eb2011-02-01 10:02:07 +0900252 return GetAsDouble(&lhs) && other->GetAsDouble(&rhs) && lhs == rhs;
initial.commit3f4a7322008-07-27 06:49:38 +0900253 }
254 default:
255 NOTREACHED();
256 return false;
257 }
258}
259
260///////////////////// StringValue ////////////////////
261
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900262StringValue::StringValue(const std::string& in_value)
263 : Value(TYPE_STRING),
264 value_(in_value) {
265 DCHECK(IsStringUTF8(in_value));
266}
267
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900268StringValue::StringValue(const string16& in_value)
269 : Value(TYPE_STRING),
270 value_(UTF16ToUTF8(in_value)) {
271}
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900272
initial.commit3f4a7322008-07-27 06:49:38 +0900273StringValue::~StringValue() {
274}
275
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900276bool StringValue::GetAsString(std::string* out_value) const {
277 if (out_value)
278 *out_value = value_;
279 return true;
280}
281
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900282bool StringValue::GetAsString(string16* out_value) const {
283 if (out_value)
284 *out_value = UTF8ToUTF16(value_);
285 return true;
286}
287
akalin@chromium.org810f92f2011-01-18 11:16:59 +0900288StringValue* StringValue::DeepCopy() const {
initial.commit3f4a7322008-07-27 06:49:38 +0900289 return CreateStringValue(value_);
290}
291
292bool StringValue::Equals(const Value* other) const {
293 if (other->GetType() != GetType())
294 return false;
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900295 std::string lhs, rhs;
initial.commit3f4a7322008-07-27 06:49:38 +0900296 return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs;
297}
298
299///////////////////// BinaryValue ////////////////////
300
mitchellwrosen@chromium.org3897f9b2012-05-20 04:31:16 +0900301BinaryValue::~BinaryValue() {
jhawkins@chromium.org592520e2012-05-20 11:34:57 +0900302 DCHECK(buffer_);
303 if (buffer_)
304 delete[] buffer_;
305}
306
307// static
308BinaryValue* BinaryValue::Create(char* buffer, size_t size) {
309 if (!buffer)
310 return NULL;
311
312 return new BinaryValue(buffer, size);
initial.commit3f4a7322008-07-27 06:49:38 +0900313}
314
jcampan@chromium.orgd1105672009-09-15 01:56:12 +0900315// static
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900316BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer,
317 size_t size) {
jhawkins@chromium.org592520e2012-05-20 11:34:57 +0900318 if (!buffer)
319 return NULL;
320
initial.commit3f4a7322008-07-27 06:49:38 +0900321 char* buffer_copy = new char[size];
mmentovai@google.com4a5b6272008-08-07 00:46:59 +0900322 memcpy(buffer_copy, buffer, size);
jhawkins@chromium.org592520e2012-05-20 11:34:57 +0900323 return new BinaryValue(buffer_copy, size);
initial.commit3f4a7322008-07-27 06:49:38 +0900324}
325
akalin@chromium.org810f92f2011-01-18 11:16:59 +0900326BinaryValue* BinaryValue::DeepCopy() const {
jhawkins@chromium.org592520e2012-05-20 11:34:57 +0900327 return CreateWithCopiedBuffer(buffer_, size_);
initial.commit3f4a7322008-07-27 06:49:38 +0900328}
329
330bool BinaryValue::Equals(const Value* other) const {
331 if (other->GetType() != GetType())
332 return false;
333 const BinaryValue* other_binary = static_cast<const BinaryValue*>(other);
334 if (other_binary->size_ != size_)
335 return false;
jhawkins@chromium.org592520e2012-05-20 11:34:57 +0900336 return !memcmp(buffer_, other_binary->buffer_, size_);
337}
338
339BinaryValue::BinaryValue(char* buffer, size_t size)
340 : Value(TYPE_BINARY),
341 buffer_(buffer),
342 size_(size) {
343 DCHECK(buffer_);
erg@google.com67a25432011-01-08 05:23:43 +0900344}
345
initial.commit3f4a7322008-07-27 06:49:38 +0900346///////////////////// DictionaryValue ////////////////////
347
erg@chromium.org493f5f62010-07-16 06:03:54 +0900348DictionaryValue::DictionaryValue()
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900349 : Value(TYPE_DICTIONARY) {
erg@chromium.org493f5f62010-07-16 06:03:54 +0900350}
351
initial.commit3f4a7322008-07-27 06:49:38 +0900352DictionaryValue::~DictionaryValue() {
353 Clear();
354}
355
battre@chromium.org29eaa252011-11-26 10:11:44 +0900356bool DictionaryValue::GetAsDictionary(DictionaryValue** out_value) {
357 if (out_value)
358 *out_value = this;
359 return true;
360}
361
362bool DictionaryValue::GetAsDictionary(const DictionaryValue** out_value) const {
363 if (out_value)
364 *out_value = this;
365 return true;
366}
367
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900368bool DictionaryValue::HasKey(const std::string& key) const {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900369 DCHECK(IsStringUTF8(key));
tony@chromium.orge4948ab2009-12-02 09:20:32 +0900370 ValueMap::const_iterator current_entry = dictionary_.find(key);
371 DCHECK((current_entry == dictionary_.end()) || current_entry->second);
372 return current_entry != dictionary_.end();
373}
374
initial.commit3f4a7322008-07-27 06:49:38 +0900375void DictionaryValue::Clear() {
376 ValueMap::iterator dict_iterator = dictionary_.begin();
377 while (dict_iterator != dictionary_.end()) {
378 delete dict_iterator->second;
379 ++dict_iterator;
380 }
381
382 dictionary_.clear();
383}
384
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900385void DictionaryValue::Set(const std::string& path, Value* in_value) {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900386 DCHECK(IsStringUTF8(path));
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900387 DCHECK(in_value);
388
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900389 std::string current_path(path);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900390 DictionaryValue* current_dictionary = this;
391 for (size_t delimiter_position = current_path.find('.');
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900392 delimiter_position != std::string::npos;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900393 delimiter_position = current_path.find('.')) {
394 // Assume that we're indexing into a dictionary.
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900395 std::string key(current_path, 0, delimiter_position);
pkasting@chromium.org8535dc22009-11-26 06:02:24 +0900396 DictionaryValue* child_dictionary = NULL;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900397 if (!current_dictionary->GetDictionary(key, &child_dictionary)) {
398 child_dictionary = new DictionaryValue;
399 current_dictionary->SetWithoutPathExpansion(key, child_dictionary);
400 }
401
402 current_dictionary = child_dictionary;
403 current_path.erase(0, delimiter_position + 1);
404 }
405
406 current_dictionary->SetWithoutPathExpansion(current_path, in_value);
407}
408
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900409void DictionaryValue::SetBoolean(const std::string& path, bool in_value) {
410 Set(path, CreateBooleanValue(in_value));
411}
412
413void DictionaryValue::SetInteger(const std::string& path, int in_value) {
414 Set(path, CreateIntegerValue(in_value));
415}
416
arv@chromium.org13413eb2011-02-01 10:02:07 +0900417void DictionaryValue::SetDouble(const std::string& path, double in_value) {
418 Set(path, CreateDoubleValue(in_value));
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900419}
420
421void DictionaryValue::SetString(const std::string& path,
422 const std::string& in_value) {
423 Set(path, CreateStringValue(in_value));
424}
425
viettrungluu@chromium.orgb7b6aa02010-08-05 01:58:12 +0900426void DictionaryValue::SetString(const std::string& path,
427 const string16& in_value) {
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900428 Set(path, CreateStringValue(in_value));
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900429}
430
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900431void DictionaryValue::SetWithoutPathExpansion(const std::string& key,
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900432 Value* in_value) {
initial.commit3f4a7322008-07-27 06:49:38 +0900433 // If there's an existing value here, we need to delete it, because
434 // we own all our children.
grt@chromium.org4c73d402011-10-22 07:58:52 +0900435 std::pair<ValueMap::iterator, bool> ins_res =
436 dictionary_.insert(std::make_pair(key, in_value));
437 if (!ins_res.second) {
438 DCHECK_NE(ins_res.first->second, in_value); // This would be bogus
439 delete ins_res.first->second;
440 ins_res.first->second = in_value;
initial.commit3f4a7322008-07-27 06:49:38 +0900441 }
initial.commit3f4a7322008-07-27 06:49:38 +0900442}
443
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900444bool DictionaryValue::Get(const std::string& path, Value** out_value) const {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900445 DCHECK(IsStringUTF8(path));
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900446 std::string current_path(path);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900447 const DictionaryValue* current_dictionary = this;
448 for (size_t delimiter_position = current_path.find('.');
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900449 delimiter_position != std::string::npos;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900450 delimiter_position = current_path.find('.')) {
pkasting@chromium.org8535dc22009-11-26 06:02:24 +0900451 DictionaryValue* child_dictionary = NULL;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900452 if (!current_dictionary->GetDictionary(
453 current_path.substr(0, delimiter_position), &child_dictionary))
454 return false;
initial.commit3f4a7322008-07-27 06:49:38 +0900455
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900456 current_dictionary = child_dictionary;
457 current_path.erase(0, delimiter_position + 1);
initial.commit3f4a7322008-07-27 06:49:38 +0900458 }
459
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900460 return current_dictionary->GetWithoutPathExpansion(current_path, out_value);
initial.commit3f4a7322008-07-27 06:49:38 +0900461}
462
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900463bool DictionaryValue::GetBoolean(const std::string& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900464 bool* bool_value) const {
465 Value* value;
466 if (!Get(path, &value))
467 return false;
468
469 return value->GetAsBoolean(bool_value);
470}
471
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900472bool DictionaryValue::GetInteger(const std::string& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900473 int* out_value) const {
474 Value* value;
475 if (!Get(path, &value))
476 return false;
477
478 return value->GetAsInteger(out_value);
479}
480
arv@chromium.org13413eb2011-02-01 10:02:07 +0900481bool DictionaryValue::GetDouble(const std::string& path,
482 double* out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900483 Value* value;
484 if (!Get(path, &value))
485 return false;
486
arv@chromium.org13413eb2011-02-01 10:02:07 +0900487 return value->GetAsDouble(out_value);
initial.commit3f4a7322008-07-27 06:49:38 +0900488}
489
evan@chromium.orgd9ab8de2010-02-19 22:32:16 +0900490bool DictionaryValue::GetString(const std::string& path,
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900491 std::string* out_value) const {
492 Value* value;
493 if (!Get(path, &value))
494 return false;
495
496 return value->GetAsString(out_value);
497}
498
viettrungluu@chromium.org58767ef2010-08-05 04:35:33 +0900499bool DictionaryValue::GetString(const std::string& path,
500 string16* out_value) const {
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900501 Value* value;
502 if (!Get(path, &value))
503 return false;
504
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900505 return value->GetAsString(out_value);
evan@chromium.orgd9ab8de2010-02-19 22:32:16 +0900506}
507
508bool DictionaryValue::GetStringASCII(const std::string& path,
509 std::string* out_value) const {
510 std::string out;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900511 if (!GetString(path, &out))
evan@chromium.orgd9ab8de2010-02-19 22:32:16 +0900512 return false;
513
514 if (!IsStringASCII(out)) {
515 NOTREACHED();
516 return false;
517 }
518
519 out_value->assign(out);
520 return true;
521}
522
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900523bool DictionaryValue::GetBinary(const std::string& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900524 BinaryValue** out_value) const {
525 Value* value;
526 bool result = Get(path, &value);
stevenjb@google.comf4f58272011-08-26 10:54:00 +0900527 if (!result || !value->IsType(TYPE_BINARY))
initial.commit3f4a7322008-07-27 06:49:38 +0900528 return false;
529
530 if (out_value)
stevenjb@google.comf4f58272011-08-26 10:54:00 +0900531 *out_value = static_cast<BinaryValue*>(value);
initial.commit3f4a7322008-07-27 06:49:38 +0900532
533 return true;
534}
535
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900536bool DictionaryValue::GetDictionary(const std::string& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900537 DictionaryValue** out_value) const {
538 Value* value;
539 bool result = Get(path, &value);
540 if (!result || !value->IsType(TYPE_DICTIONARY))
541 return false;
542
543 if (out_value)
544 *out_value = static_cast<DictionaryValue*>(value);
545
546 return true;
547}
548
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900549bool DictionaryValue::GetList(const std::string& path,
initial.commit3f4a7322008-07-27 06:49:38 +0900550 ListValue** out_value) const {
551 Value* value;
552 bool result = Get(path, &value);
stevenjb@google.comf4f58272011-08-26 10:54:00 +0900553 if (!result || !value->IsType(TYPE_LIST))
initial.commit3f4a7322008-07-27 06:49:38 +0900554 return false;
555
556 if (out_value)
stevenjb@google.comf4f58272011-08-26 10:54:00 +0900557 *out_value = static_cast<ListValue*>(value);
initial.commit3f4a7322008-07-27 06:49:38 +0900558
559 return true;
560}
561
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900562bool DictionaryValue::GetWithoutPathExpansion(const std::string& key,
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900563 Value** out_value) const {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900564 DCHECK(IsStringUTF8(key));
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900565 ValueMap::const_iterator entry_iterator = dictionary_.find(key);
566 if (entry_iterator == dictionary_.end())
567 return false;
initial.commit3f4a7322008-07-27 06:49:38 +0900568
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900569 Value* entry = entry_iterator->second;
570 if (out_value)
571 *out_value = entry;
572 return true;
573}
574
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900575bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::string& key,
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900576 int* out_value) const {
577 Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900578 if (!GetWithoutPathExpansion(key, &value))
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900579 return false;
580
581 return value->GetAsInteger(out_value);
582}
583
arv@chromium.org13413eb2011-02-01 10:02:07 +0900584bool DictionaryValue::GetDoubleWithoutPathExpansion(const std::string& key,
585 double* out_value) const {
jam@chromium.org5bd53922010-10-01 16:28:25 +0900586 Value* value;
587 if (!GetWithoutPathExpansion(key, &value))
588 return false;
589
arv@chromium.org13413eb2011-02-01 10:02:07 +0900590 return value->GetAsDouble(out_value);
jam@chromium.org5bd53922010-10-01 16:28:25 +0900591}
592
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900593bool DictionaryValue::GetStringWithoutPathExpansion(
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900594 const std::string& key,
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900595 std::string* out_value) const {
596 Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900597 if (!GetWithoutPathExpansion(key, &value))
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900598 return false;
599
600 return value->GetAsString(out_value);
601}
602
viettrungluu@chromium.org58767ef2010-08-05 04:35:33 +0900603bool DictionaryValue::GetStringWithoutPathExpansion(
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900604 const std::string& key,
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900605 string16* out_value) const {
606 Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900607 if (!GetWithoutPathExpansion(key, &value))
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900608 return false;
609
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900610 return value->GetAsString(out_value);
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900611}
612
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900613bool DictionaryValue::GetDictionaryWithoutPathExpansion(
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900614 const std::string& key,
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900615 DictionaryValue** out_value) const {
616 Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900617 bool result = GetWithoutPathExpansion(key, &value);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900618 if (!result || !value->IsType(TYPE_DICTIONARY))
619 return false;
620
621 if (out_value)
622 *out_value = static_cast<DictionaryValue*>(value);
623
624 return true;
625}
626
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900627bool DictionaryValue::GetListWithoutPathExpansion(const std::string& key,
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900628 ListValue** out_value) const {
629 Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900630 bool result = GetWithoutPathExpansion(key, &value);
stevenjb@google.comf4f58272011-08-26 10:54:00 +0900631 if (!result || !value->IsType(TYPE_LIST))
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900632 return false;
633
634 if (out_value)
stevenjb@google.comf4f58272011-08-26 10:54:00 +0900635 *out_value = static_cast<ListValue*>(value);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900636
637 return true;
638}
639
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900640bool DictionaryValue::Remove(const std::string& path, Value** out_value) {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900641 DCHECK(IsStringUTF8(path));
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900642 std::string current_path(path);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900643 DictionaryValue* current_dictionary = this;
644 size_t delimiter_position = current_path.rfind('.');
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900645 if (delimiter_position != std::string::npos) {
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900646 if (!GetDictionary(current_path.substr(0, delimiter_position),
647 &current_dictionary))
648 return false;
649 current_path.erase(0, delimiter_position + 1);
initial.commit3f4a7322008-07-27 06:49:38 +0900650 }
651
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900652 return current_dictionary->RemoveWithoutPathExpansion(current_path,
653 out_value);
654}
655
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900656bool DictionaryValue::RemoveWithoutPathExpansion(const std::string& key,
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900657 Value** out_value) {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900658 DCHECK(IsStringUTF8(key));
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
mnissler@chromium.org17cee0e2010-05-14 22:17:40 +0900677void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) {
678 for (DictionaryValue::key_iterator key(dictionary->begin_keys());
679 key != dictionary->end_keys(); ++key) {
680 Value* merge_value;
681 if (dictionary->GetWithoutPathExpansion(*key, &merge_value)) {
682 // Check whether we have to merge dictionaries.
683 if (merge_value->IsType(Value::TYPE_DICTIONARY)) {
684 DictionaryValue* sub_dict;
685 if (GetDictionaryWithoutPathExpansion(*key, &sub_dict)) {
686 sub_dict->MergeDictionary(
687 static_cast<const DictionaryValue*>(merge_value));
688 continue;
689 }
690 }
691 // All other cases: Make a copy and hook it up.
692 SetWithoutPathExpansion(*key, merge_value->DeepCopy());
693 }
694 }
695}
696
rsesek@chromium.orgc2d2b202012-05-17 00:23:30 +0900697void DictionaryValue::Swap(DictionaryValue* other) {
698 dictionary_.swap(other->dictionary_);
699}
700
akalin@chromium.org810f92f2011-01-18 11:16:59 +0900701DictionaryValue* DictionaryValue::DeepCopy() const {
erg@google.com67a25432011-01-08 05:23:43 +0900702 DictionaryValue* result = new DictionaryValue;
703
704 for (ValueMap::const_iterator current_entry(dictionary_.begin());
705 current_entry != dictionary_.end(); ++current_entry) {
706 result->SetWithoutPathExpansion(current_entry->first,
707 current_entry->second->DeepCopy());
708 }
709
710 return result;
711}
712
713bool DictionaryValue::Equals(const Value* other) const {
714 if (other->GetType() != GetType())
715 return false;
716
717 const DictionaryValue* other_dict =
718 static_cast<const DictionaryValue*>(other);
719 key_iterator lhs_it(begin_keys());
720 key_iterator rhs_it(other_dict->begin_keys());
721 while (lhs_it != end_keys() && rhs_it != other_dict->end_keys()) {
722 Value* lhs;
723 Value* rhs;
724 if (*lhs_it != *rhs_it ||
725 !GetWithoutPathExpansion(*lhs_it, &lhs) ||
726 !other_dict->GetWithoutPathExpansion(*rhs_it, &rhs) ||
727 !lhs->Equals(rhs)) {
728 return false;
729 }
730 ++lhs_it;
731 ++rhs_it;
732 }
733 if (lhs_it != end_keys() || rhs_it != other_dict->end_keys())
734 return false;
735
736 return true;
737}
738
initial.commit3f4a7322008-07-27 06:49:38 +0900739///////////////////// ListValue ////////////////////
740
erg@chromium.org493f5f62010-07-16 06:03:54 +0900741ListValue::ListValue() : Value(TYPE_LIST) {
742}
743
initial.commit3f4a7322008-07-27 06:49:38 +0900744ListValue::~ListValue() {
745 Clear();
746}
747
748void ListValue::Clear() {
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900749 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i)
750 delete *i;
initial.commit3f4a7322008-07-27 06:49:38 +0900751 list_.clear();
752}
753
754bool ListValue::Set(size_t index, Value* in_value) {
755 if (!in_value)
756 return false;
757
758 if (index >= list_.size()) {
759 // Pad out any intermediate indexes with null settings
760 while (index > list_.size())
761 Append(CreateNullValue());
762 Append(in_value);
763 } else {
764 DCHECK(list_[index] != in_value);
765 delete list_[index];
766 list_[index] = in_value;
767 }
768 return true;
769}
770
771bool ListValue::Get(size_t index, Value** out_value) const {
772 if (index >= list_.size())
773 return false;
774
775 if (out_value)
776 *out_value = list_[index];
777
778 return true;
779}
780
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900781bool ListValue::GetBoolean(size_t index, bool* bool_value) const {
782 Value* value;
783 if (!Get(index, &value))
784 return false;
785
786 return value->GetAsBoolean(bool_value);
787}
788
789bool ListValue::GetInteger(size_t index, int* out_value) const {
790 Value* value;
791 if (!Get(index, &value))
792 return false;
793
794 return value->GetAsInteger(out_value);
795}
796
arv@chromium.org13413eb2011-02-01 10:02:07 +0900797bool ListValue::GetDouble(size_t index, double* out_value) const {
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900798 Value* value;
799 if (!Get(index, &value))
800 return false;
801
arv@chromium.org13413eb2011-02-01 10:02:07 +0900802 return value->GetAsDouble(out_value);
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900803}
804
805bool ListValue::GetString(size_t index, std::string* out_value) const {
806 Value* value;
807 if (!Get(index, &value))
808 return false;
809
810 return value->GetAsString(out_value);
811}
812
viettrungluu@chromium.org58767ef2010-08-05 04:35:33 +0900813bool ListValue::GetString(size_t index, string16* out_value) const {
814 Value* value;
815 if (!Get(index, &value))
816 return false;
817
818 return value->GetAsString(out_value);
819}
820
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900821bool ListValue::GetBinary(size_t index, BinaryValue** out_value) const {
822 Value* value;
823 bool result = Get(index, &value);
824 if (!result || !value->IsType(TYPE_BINARY))
825 return false;
826
827 if (out_value)
828 *out_value = static_cast<BinaryValue*>(value);
829
830 return true;
831}
832
833bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) const {
initial.commit3f4a7322008-07-27 06:49:38 +0900834 Value* value;
835 bool result = Get(index, &value);
836 if (!result || !value->IsType(TYPE_DICTIONARY))
837 return false;
838
839 if (out_value)
840 *out_value = static_cast<DictionaryValue*>(value);
841
842 return true;
843}
844
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900845bool ListValue::GetList(size_t index, ListValue** out_value) const {
846 Value* value;
847 bool result = Get(index, &value);
stevenjb@google.comf4f58272011-08-26 10:54:00 +0900848 if (!result || !value->IsType(TYPE_LIST))
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900849 return false;
850
851 if (out_value)
stevenjb@google.comf4f58272011-08-26 10:54:00 +0900852 *out_value = static_cast<ListValue*>(value);
aa@chromium.orgc93b02f2009-01-21 06:05:32 +0900853
854 return true;
855}
856
initial.commit3f4a7322008-07-27 06:49:38 +0900857bool ListValue::Remove(size_t index, Value** out_value) {
858 if (index >= list_.size())
859 return false;
860
861 if (out_value)
862 *out_value = list_[index];
863 else
864 delete list_[index];
865
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900866 list_.erase(list_.begin() + index);
initial.commit3f4a7322008-07-27 06:49:38 +0900867 return true;
868}
869
tfarina@chromium.org09cf4342011-08-14 02:34:31 +0900870bool ListValue::Remove(const Value& value, size_t* index) {
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900871 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) {
872 if ((*i)->Equals(&value)) {
tfarina@chromium.org09cf4342011-08-14 02:34:31 +0900873 size_t previous_index = i - list_.begin();
pkasting@chromium.orgdfe6a692009-12-01 04:59:11 +0900874 delete *i;
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900875 list_.erase(i);
robertshield@chromium.org9fb9e372010-03-23 05:12:50 +0900876
tfarina@chromium.org09cf4342011-08-14 02:34:31 +0900877 if (index)
878 *index = previous_index;
879 return true;
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900880 }
881 }
tfarina@chromium.org09cf4342011-08-14 02:34:31 +0900882 return false;
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900883}
884
initial.commit3f4a7322008-07-27 06:49:38 +0900885void ListValue::Append(Value* in_value) {
886 DCHECK(in_value);
887 list_.push_back(in_value);
888}
889
zork@chromium.orgb5f742b2010-04-13 06:48:10 +0900890bool ListValue::AppendIfNotPresent(Value* in_value) {
891 DCHECK(in_value);
ziadh@chromium.org5c7f6312010-07-19 17:00:42 +0900892 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i) {
markusheintz@chromium.org78621872011-03-18 22:56:38 +0900893 if ((*i)->Equals(in_value)) {
894 delete in_value;
zork@chromium.orgb5f742b2010-04-13 06:48:10 +0900895 return false;
markusheintz@chromium.org78621872011-03-18 22:56:38 +0900896 }
zork@chromium.orgb5f742b2010-04-13 06:48:10 +0900897 }
898 list_.push_back(in_value);
899 return true;
900}
901
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900902bool ListValue::Insert(size_t index, Value* in_value) {
903 DCHECK(in_value);
jhawkins@chromium.org33edb6b2009-10-01 06:36:37 +0900904 if (index > list_.size())
erikkay@chromium.org9034a232009-08-29 05:26:05 +0900905 return false;
906
907 list_.insert(list_.begin() + index, in_value);
908 return true;
909}
910
pastarmovj@chromium.org1602a472011-09-20 00:23:10 +0900911ListValue::const_iterator ListValue::Find(const Value& value) const {
912 return std::find_if(list_.begin(), list_.end(), ValueEquals(&value));
913}
914
rsesek@chromium.orgc2d2b202012-05-17 00:23:30 +0900915void ListValue::Swap(ListValue* other) {
916 list_.swap(other->list_);
917}
918
scottbyer@google.com673b8762010-12-07 09:35:29 +0900919bool ListValue::GetAsList(ListValue** out_value) {
920 if (out_value)
921 *out_value = this;
922 return true;
923}
924
bauerb@chromium.org6878e502011-07-12 18:04:38 +0900925bool ListValue::GetAsList(const ListValue** out_value) const {
926 if (out_value)
927 *out_value = this;
928 return true;
929}
930
akalin@chromium.org810f92f2011-01-18 11:16:59 +0900931ListValue* ListValue::DeepCopy() const {
initial.commit3f4a7322008-07-27 06:49:38 +0900932 ListValue* result = new ListValue;
933
pkasting@chromium.org727139c2009-05-09 09:33:04 +0900934 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i)
935 result->Append((*i)->DeepCopy());
initial.commit3f4a7322008-07-27 06:49:38 +0900936
937 return result;
938}
939
940bool ListValue::Equals(const Value* other) const {
941 if (other->GetType() != GetType())
942 return false;
943
944 const ListValue* other_list =
945 static_cast<const ListValue*>(other);
946 const_iterator lhs_it, rhs_it;
947 for (lhs_it = begin(), rhs_it = other_list->begin();
948 lhs_it != end() && rhs_it != other_list->end();
949 ++lhs_it, ++rhs_it) {
950 if (!(*lhs_it)->Equals(*rhs_it))
951 return false;
952 }
953 if (lhs_it != end() || rhs_it != other_list->end())
954 return false;
955
956 return true;
957}
erg@chromium.org493f5f62010-07-16 06:03:54 +0900958
959ValueSerializer::~ValueSerializer() {
960}
tfarina@chromium.orgde3ef412011-08-05 08:51:10 +0900961
962} // namespace base