blob: 6728e55519a77e42ab73c587a0d5b2ff8bd83e95 [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
mostynb@opera.comf29dd612013-09-04 08:29:12 +09007#include <string.h>
8
pastarmovj@chromium.org1602a472011-09-20 00:23:10 +09009#include <algorithm>
mateuszs8b1a88a2015-04-24 22:20:23 +090010#include <cmath>
kalman@chromium.org829cf752012-09-12 12:39:35 +090011#include <ostream>
danakj800d2ea2015-11-25 14:29:58 +090012#include <utility>
pastarmovj@chromium.org1602a472011-09-20 00:23:10 +090013
kalman@chromium.org829cf752012-09-12 12:39:35 +090014#include "base/json/json_writer.h"
initial.commit3f4a7322008-07-27 06:49:38 +090015#include "base/logging.h"
dchengcc8e4d82016-04-05 06:25:51 +090016#include "base/memory/ptr_util.h"
avi@chromium.org68a745c2013-06-11 05:11:14 +090017#include "base/strings/string_util.h"
avi@chromium.org17f60622013-06-08 03:37:07 +090018#include "base/strings/utf_string_conversions.h"
tony@chromium.orge4948ab2009-12-02 09:20:32 +090019
brettw@chromium.org88aa6552013-06-15 02:56:08 +090020namespace base {
21
tony@chromium.orge4948ab2009-12-02 09:20:32 +090022namespace {
23
thestige44b9322016-07-19 09:39:30 +090024const char* const kTypeNames[] = {"null", "boolean", "integer", "double",
25 "string", "binary", "dictionary", "list"};
jdoerrie89ee31a2016-12-08 00:43:28 +090026static_assert(arraysize(kTypeNames) ==
27 static_cast<size_t>(Value::Type::LIST) + 1,
thestige44b9322016-07-19 09:39:30 +090028 "kTypeNames Has Wrong Size");
29
dchengcc8e4d82016-04-05 06:25:51 +090030std::unique_ptr<Value> CopyWithoutEmptyChildren(const Value& node);
estade51a57ab2015-05-23 11:42:09 +090031
tony@chromium.orge4948ab2009-12-02 09:20:32 +090032// Make a deep copy of |node|, but don't include empty lists or dictionaries
33// in the copy. It's possible for this function to return NULL and it
34// expects |node| to always be non-NULL.
dchengcc8e4d82016-04-05 06:25:51 +090035std::unique_ptr<ListValue> CopyListWithoutEmptyChildren(const ListValue& list) {
36 std::unique_ptr<ListValue> copy;
dcheng1fa44fb2016-05-26 03:30:47 +090037 for (const auto& entry : list) {
38 std::unique_ptr<Value> child_copy = CopyWithoutEmptyChildren(*entry);
estade51a57ab2015-05-23 11:42:09 +090039 if (child_copy) {
40 if (!copy)
41 copy.reset(new ListValue);
danakj800d2ea2015-11-25 14:29:58 +090042 copy->Append(std::move(child_copy));
tony@chromium.orge4948ab2009-12-02 09:20:32 +090043 }
estade51a57ab2015-05-23 11:42:09 +090044 }
45 return copy;
46}
tony@chromium.orge4948ab2009-12-02 09:20:32 +090047
dchengcc8e4d82016-04-05 06:25:51 +090048std::unique_ptr<DictionaryValue> CopyDictionaryWithoutEmptyChildren(
estade51a57ab2015-05-23 11:42:09 +090049 const DictionaryValue& dict) {
dchengcc8e4d82016-04-05 06:25:51 +090050 std::unique_ptr<DictionaryValue> copy;
estade51a57ab2015-05-23 11:42:09 +090051 for (DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
dchengcc8e4d82016-04-05 06:25:51 +090052 std::unique_ptr<Value> child_copy = CopyWithoutEmptyChildren(it.value());
estade51a57ab2015-05-23 11:42:09 +090053 if (child_copy) {
54 if (!copy)
55 copy.reset(new DictionaryValue);
danakj800d2ea2015-11-25 14:29:58 +090056 copy->SetWithoutPathExpansion(it.key(), std::move(child_copy));
tony@chromium.orge4948ab2009-12-02 09:20:32 +090057 }
estade51a57ab2015-05-23 11:42:09 +090058 }
59 return copy;
60}
61
dchengcc8e4d82016-04-05 06:25:51 +090062std::unique_ptr<Value> CopyWithoutEmptyChildren(const Value& node) {
estade51a57ab2015-05-23 11:42:09 +090063 switch (node.GetType()) {
jdoerrie89ee31a2016-12-08 00:43:28 +090064 case Value::Type::LIST:
estade51a57ab2015-05-23 11:42:09 +090065 return CopyListWithoutEmptyChildren(static_cast<const ListValue&>(node));
66
jdoerrie89ee31a2016-12-08 00:43:28 +090067 case Value::Type::DICTIONARY:
estade51a57ab2015-05-23 11:42:09 +090068 return CopyDictionaryWithoutEmptyChildren(
69 static_cast<const DictionaryValue&>(node));
tony@chromium.orge4948ab2009-12-02 09:20:32 +090070
71 default:
estade51a57ab2015-05-23 11:42:09 +090072 return node.CreateDeepCopy();
tony@chromium.orge4948ab2009-12-02 09:20:32 +090073 }
74}
75
jdoerrie93a0cf32017-02-01 19:36:56 +090076} // namespace
77
initial.commit3f4a7322008-07-27 06:49:38 +090078// static
dchengcc8e4d82016-04-05 06:25:51 +090079std::unique_ptr<Value> Value::CreateNullValue() {
jdoerrie89ee31a2016-12-08 00:43:28 +090080 return WrapUnique(new Value(Type::NONE));
initial.commit3f4a7322008-07-27 06:49:38 +090081}
82
jdoerrie58325a42017-02-15 17:42:14 +090083// static
84std::unique_ptr<BinaryValue> BinaryValue::CreateWithCopiedBuffer(
85 const char* buffer,
86 size_t size) {
87 return MakeUnique<BinaryValue>(std::vector<char>(buffer, buffer + size));
88}
89
jdoerrie93a0cf32017-02-01 19:36:56 +090090Value::Value(const Value& that) {
jdoerrie31299132017-02-01 23:38:32 +090091 InternalCopyConstructFrom(that);
jdoerrie93a0cf32017-02-01 19:36:56 +090092}
93
94Value::Value(Value&& that) {
jdoerrie31299132017-02-01 23:38:32 +090095 InternalMoveConstructFrom(std::move(that));
jdoerrie93a0cf32017-02-01 19:36:56 +090096}
97
98Value::Value() : type_(Type::NONE) {}
99
100Value::Value(Type type) : type_(type) {
101 // Initialize with the default value.
102 switch (type_) {
103 case Type::NONE:
104 return;
105
106 case Type::BOOLEAN:
107 bool_value_ = false;
108 return;
109 case Type::INTEGER:
110 int_value_ = 0;
111 return;
112 case Type::DOUBLE:
113 double_value_ = 0.0;
114 return;
jdoerrie31299132017-02-01 23:38:32 +0900115 case Type::STRING:
116 string_value_.Init();
117 return;
jdoerrie58325a42017-02-15 17:42:14 +0900118 case Type::BINARY:
119 binary_value_.Init();
120 return;
jdoerrie93a0cf32017-02-01 19:36:56 +0900121 case Type::DICTIONARY:
jdoerrie1d5b3482017-02-17 22:54:49 +0900122 dict_ptr_.Init(MakeUnique<DictStorage>());
123 return;
124 case Type::LIST:
125 list_.Init();
jdoerrie93a0cf32017-02-01 19:36:56 +0900126 return;
127 }
128}
129
130Value::Value(bool in_bool) : type_(Type::BOOLEAN), bool_value_(in_bool) {}
131
132Value::Value(int in_int) : type_(Type::INTEGER), int_value_(in_int) {}
133
134Value::Value(double in_double) : type_(Type::DOUBLE), double_value_(in_double) {
135 if (!std::isfinite(double_value_)) {
136 NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) "
137 << "values cannot be represented in JSON";
138 double_value_ = 0.0;
139 }
140}
141
jdoerrie31299132017-02-01 23:38:32 +0900142Value::Value(const char* in_string) : type_(Type::STRING) {
143 string_value_.Init(in_string);
144 DCHECK(IsStringUTF8(*string_value_));
145}
146
147Value::Value(const std::string& in_string) : type_(Type::STRING) {
148 string_value_.Init(in_string);
149 DCHECK(IsStringUTF8(*string_value_));
150}
151
152Value::Value(std::string&& in_string) : type_(Type::STRING) {
153 string_value_.Init(std::move(in_string));
154 DCHECK(IsStringUTF8(*string_value_));
155}
156
157Value::Value(const char16* in_string) : type_(Type::STRING) {
158 string_value_.Init(UTF16ToUTF8(in_string));
159}
160
161Value::Value(const string16& in_string) : type_(Type::STRING) {
162 string_value_.Init(UTF16ToUTF8(in_string));
163}
164
165Value::Value(StringPiece in_string) : Value(in_string.as_string()) {}
166
jdoerrie58325a42017-02-15 17:42:14 +0900167Value::Value(const std::vector<char>& in_blob) : type_(Type::BINARY) {
168 binary_value_.Init(in_blob);
169}
170
171Value::Value(std::vector<char>&& in_blob) : type_(Type::BINARY) {
172 binary_value_.Init(std::move(in_blob));
173}
174
jdoerrie93a0cf32017-02-01 19:36:56 +0900175Value& Value::operator=(const Value& that) {
dyaroshev798c5ef2017-03-21 02:04:27 +0900176 if (type_ == that.type_) {
177 InternalCopyAssignFromSameType(that);
178 } else {
179 // This is not a self assignment because the type_ doesn't match.
180 InternalCleanup();
181 InternalCopyConstructFrom(that);
jdoerrie93a0cf32017-02-01 19:36:56 +0900182 }
183
184 return *this;
185}
186
187Value& Value::operator=(Value&& that) {
dyaroshev798c5ef2017-03-21 02:04:27 +0900188 DCHECK(this != &that) << "attempt to self move assign.";
189 InternalCleanup();
190 InternalMoveConstructFrom(std::move(that));
jdoerrie93a0cf32017-02-01 19:36:56 +0900191
192 return *this;
193}
194
jdoerrie31299132017-02-01 23:38:32 +0900195Value::~Value() {
196 InternalCleanup();
vabr3f090ed2017-03-15 05:06:11 +0900197 alive_ = false;
jdoerrie31299132017-02-01 23:38:32 +0900198}
jdoerrie93a0cf32017-02-01 19:36:56 +0900199
thestige44b9322016-07-19 09:39:30 +0900200// static
201const char* Value::GetTypeName(Value::Type type) {
jdoerrie89ee31a2016-12-08 00:43:28 +0900202 DCHECK_GE(static_cast<int>(type), 0);
thestige44b9322016-07-19 09:39:30 +0900203 DCHECK_LT(static_cast<size_t>(type), arraysize(kTypeNames));
jdoerrie89ee31a2016-12-08 00:43:28 +0900204 return kTypeNames[static_cast<size_t>(type)];
thestige44b9322016-07-19 09:39:30 +0900205}
206
jdoerrie93a0cf32017-02-01 19:36:56 +0900207bool Value::GetBool() const {
208 CHECK(is_bool());
209 return bool_value_;
210}
211
212int Value::GetInt() const {
213 CHECK(is_int());
214 return int_value_;
215}
216
217double Value::GetDouble() const {
218 if (is_double())
219 return double_value_;
220 if (is_int())
221 return int_value_;
222 CHECK(false);
223 return 0.0;
pneubeckb57f3f52015-01-20 20:26:36 +0900224}
225
jdoerrie31299132017-02-01 23:38:32 +0900226const std::string& Value::GetString() const {
227 CHECK(is_string());
228 return *string_value_;
229}
230
jdoerrie58325a42017-02-15 17:42:14 +0900231const std::vector<char>& Value::GetBlob() const {
232 CHECK(is_blob());
233 return *binary_value_;
234}
235
236size_t Value::GetSize() const {
237 return GetBlob().size();
238}
239
240const char* Value::GetBuffer() const {
241 return GetBlob().data();
242}
243
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900244bool Value::GetAsBoolean(bool* out_value) const {
jdoerrie93a0cf32017-02-01 19:36:56 +0900245 if (out_value && is_bool()) {
246 *out_value = bool_value_;
247 return true;
248 }
249 return is_bool();
initial.commit3f4a7322008-07-27 06:49:38 +0900250}
251
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900252bool Value::GetAsInteger(int* out_value) const {
jdoerrie93a0cf32017-02-01 19:36:56 +0900253 if (out_value && is_int()) {
254 *out_value = int_value_;
255 return true;
256 }
257 return is_int();
initial.commit3f4a7322008-07-27 06:49:38 +0900258}
259
arv@chromium.org13413eb2011-02-01 10:02:07 +0900260bool Value::GetAsDouble(double* out_value) const {
jdoerrie93a0cf32017-02-01 19:36:56 +0900261 if (out_value && is_double()) {
262 *out_value = double_value_;
263 return true;
264 } else if (out_value && is_int()) {
265 // Allow promotion from int to double.
266 *out_value = int_value_;
267 return true;
268 }
269 return is_double() || is_int();
initial.commit3f4a7322008-07-27 06:49:38 +0900270}
271
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900272bool Value::GetAsString(std::string* out_value) const {
jdoerrie31299132017-02-01 23:38:32 +0900273 if (out_value && is_string()) {
274 *out_value = *string_value_;
275 return true;
276 }
277 return is_string();
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900278}
279
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900280bool Value::GetAsString(string16* out_value) const {
jdoerrie31299132017-02-01 23:38:32 +0900281 if (out_value && is_string()) {
282 *out_value = UTF8ToUTF16(*string_value_);
283 return true;
284 }
285 return is_string();
initial.commit3f4a7322008-07-27 06:49:38 +0900286}
287
jdoerrie0d1295b2017-03-06 20:12:04 +0900288bool Value::GetAsString(const Value** out_value) const {
jdoerrie31299132017-02-01 23:38:32 +0900289 if (out_value && is_string()) {
jdoerrie0d1295b2017-03-06 20:12:04 +0900290 *out_value = static_cast<const Value*>(this);
jdoerrie31299132017-02-01 23:38:32 +0900291 return true;
292 }
293 return is_string();
estade@chromium.org0fd309d2014-02-06 05:42:06 +0900294}
295
sammc94ef7962016-12-21 17:55:41 +0900296bool Value::GetAsString(StringPiece* out_value) const {
jdoerrie31299132017-02-01 23:38:32 +0900297 if (out_value && is_string()) {
298 *out_value = *string_value_;
299 return true;
300 }
301 return is_string();
sammc94ef7962016-12-21 17:55:41 +0900302}
303
jdoerrie93a0cf32017-02-01 19:36:56 +0900304bool Value::GetAsBinary(const BinaryValue** out_value) const {
jdoerrie58325a42017-02-15 17:42:14 +0900305 if (out_value && is_blob()) {
306 *out_value = this;
307 return true;
308 }
309 return is_blob();
jdoerrie93a0cf32017-02-01 19:36:56 +0900310}
311
scottbyer@google.com673b8762010-12-07 09:35:29 +0900312bool Value::GetAsList(ListValue** out_value) {
jdoerrie1d5b3482017-02-17 22:54:49 +0900313 if (out_value && is_list()) {
314 *out_value = static_cast<ListValue*>(this);
315 return true;
316 }
317 return is_list();
scottbyer@google.com673b8762010-12-07 09:35:29 +0900318}
319
bauerb@chromium.org6878e502011-07-12 18:04:38 +0900320bool Value::GetAsList(const ListValue** out_value) const {
jdoerrie1d5b3482017-02-17 22:54:49 +0900321 if (out_value && is_list()) {
322 *out_value = static_cast<const ListValue*>(this);
323 return true;
324 }
325 return is_list();
bauerb@chromium.org6878e502011-07-12 18:04:38 +0900326}
327
battre@chromium.org29eaa252011-11-26 10:11:44 +0900328bool Value::GetAsDictionary(DictionaryValue** out_value) {
jdoerrie1d5b3482017-02-17 22:54:49 +0900329 if (out_value && is_dict()) {
330 *out_value = static_cast<DictionaryValue*>(this);
331 return true;
332 }
333 return is_dict();
battre@chromium.org29eaa252011-11-26 10:11:44 +0900334}
335
336bool Value::GetAsDictionary(const DictionaryValue** out_value) const {
jdoerrie1d5b3482017-02-17 22:54:49 +0900337 if (out_value && is_dict()) {
338 *out_value = static_cast<const DictionaryValue*>(this);
339 return true;
340 }
341 return is_dict();
battre@chromium.org29eaa252011-11-26 10:11:44 +0900342}
343
initial.commit3f4a7322008-07-27 06:49:38 +0900344Value* Value::DeepCopy() const {
345 // This method should only be getting called for null Values--all subclasses
346 // need to provide their own implementation;.
jdoerrie93a0cf32017-02-01 19:36:56 +0900347 switch (type()) {
348 case Type::NONE:
349 return CreateNullValue().release();
350
jdoerrie93a0cf32017-02-01 19:36:56 +0900351 case Type::BOOLEAN:
jdoerriebfe825e2017-03-02 21:09:19 +0900352 return new Value(bool_value_);
jdoerrie93a0cf32017-02-01 19:36:56 +0900353 case Type::INTEGER:
jdoerriebfe825e2017-03-02 21:09:19 +0900354 return new Value(int_value_);
jdoerrie93a0cf32017-02-01 19:36:56 +0900355 case Type::DOUBLE:
jdoerriebfe825e2017-03-02 21:09:19 +0900356 return new Value(double_value_);
jdoerrie31299132017-02-01 23:38:32 +0900357 case Type::STRING:
jdoerrie0d1295b2017-03-06 20:12:04 +0900358 return new Value(*string_value_);
jdoerrie58325a42017-02-15 17:42:14 +0900359 // For now, make BinaryValues for backward-compatibility. Convert to
360 // Value when that code is deleted.
361 case Type::BINARY:
jdoerrie0d1295b2017-03-06 20:12:04 +0900362 return new Value(*binary_value_);
jdoerrie93a0cf32017-02-01 19:36:56 +0900363
jdoerrie1d5b3482017-02-17 22:54:49 +0900364 // TODO(crbug.com/646113): Clean this up when DictionaryValue and ListValue
365 // are completely inlined.
366 case Type::DICTIONARY: {
367 DictionaryValue* result = new DictionaryValue;
368
369 for (const auto& current_entry : **dict_ptr_) {
370 result->SetWithoutPathExpansion(current_entry.first,
371 current_entry.second->CreateDeepCopy());
372 }
373
374 return result;
375 }
376
377 case Type::LIST: {
378 ListValue* result = new ListValue;
379
380 for (const auto& entry : *list_)
381 result->Append(entry->CreateDeepCopy());
382
383 return result;
384 }
385
jdoerrie93a0cf32017-02-01 19:36:56 +0900386 default:
jdoerrie93a0cf32017-02-01 19:36:56 +0900387 NOTREACHED();
388 return nullptr;
389 }
initial.commit3f4a7322008-07-27 06:49:38 +0900390}
391
dchengcc8e4d82016-04-05 06:25:51 +0900392std::unique_ptr<Value> Value::CreateDeepCopy() const {
393 return WrapUnique(DeepCopy());
estade77a018f2015-05-07 10:53:08 +0900394}
395
initial.commit3f4a7322008-07-27 06:49:38 +0900396bool Value::Equals(const Value* other) const {
jdoerrie93a0cf32017-02-01 19:36:56 +0900397 if (other->type() != type())
398 return false;
399
400 switch (type()) {
401 case Type::NONE:
402 return true;
403 case Type::BOOLEAN:
404 return bool_value_ == other->bool_value_;
405 case Type::INTEGER:
406 return int_value_ == other->int_value_;
407 case Type::DOUBLE:
408 return double_value_ == other->double_value_;
jdoerrie34ee9f62017-02-02 19:56:03 +0900409 case Type::STRING:
410 return *string_value_ == *(other->string_value_);
jdoerrie58325a42017-02-15 17:42:14 +0900411 case Type::BINARY:
412 return *binary_value_ == *(other->binary_value_);
jdoerrie1d5b3482017-02-17 22:54:49 +0900413 // TODO(crbug.com/646113): Clean this up when DictionaryValue and ListValue
414 // are completely inlined.
415 case Type::DICTIONARY: {
416 if ((*dict_ptr_)->size() != (*other->dict_ptr_)->size())
417 return false;
418
419 return std::equal(std::begin(**dict_ptr_), std::end(**dict_ptr_),
420 std::begin(**(other->dict_ptr_)),
421 [](const DictStorage::value_type& lhs,
422 const DictStorage::value_type& rhs) {
423 if (lhs.first != rhs.first)
424 return false;
425
426 return lhs.second->Equals(rhs.second.get());
427 });
428 }
429 case Type::LIST: {
430 if (list_->size() != other->list_->size())
431 return false;
432
433 return std::equal(std::begin(*list_), std::end(*list_),
434 std::begin(*(other->list_)),
435 [](const ListStorage::value_type& lhs,
436 const ListStorage::value_type& rhs) {
437 return lhs->Equals(rhs.get());
438 });
439 }
jdoerrie93a0cf32017-02-01 19:36:56 +0900440 }
jdoerrie1d5b3482017-02-17 22:54:49 +0900441
442 NOTREACHED();
443 return false;
initial.commit3f4a7322008-07-27 06:49:38 +0900444}
445
bauerb@chromium.orgfbd55e12010-12-07 03:13:43 +0900446// static
447bool Value::Equals(const Value* a, const Value* b) {
448 if ((a == NULL) && (b == NULL)) return true;
449 if ((a == NULL) ^ (b == NULL)) return false;
450 return a->Equals(b);
451}
452
jdoerrie31299132017-02-01 23:38:32 +0900453void Value::InternalCopyFundamentalValue(const Value& that) {
jdoerrie93a0cf32017-02-01 19:36:56 +0900454 switch (type_) {
455 case Type::NONE:
456 // Nothing to do.
457 return;
erg@chromium.org493f5f62010-07-16 06:03:54 +0900458
jdoerrie89ee31a2016-12-08 00:43:28 +0900459 case Type::BOOLEAN:
jdoerrie93a0cf32017-02-01 19:36:56 +0900460 bool_value_ = that.bool_value_;
461 return;
jdoerrie89ee31a2016-12-08 00:43:28 +0900462 case Type::INTEGER:
jdoerrie93a0cf32017-02-01 19:36:56 +0900463 int_value_ = that.int_value_;
464 return;
jdoerrie89ee31a2016-12-08 00:43:28 +0900465 case Type::DOUBLE:
jdoerrie93a0cf32017-02-01 19:36:56 +0900466 double_value_ = that.double_value_;
467 return;
initial.commit3f4a7322008-07-27 06:49:38 +0900468
jdoerrie31299132017-02-01 23:38:32 +0900469 default:
470 NOTREACHED();
471 }
472}
473
474void Value::InternalCopyConstructFrom(const Value& that) {
475 type_ = that.type_;
476
477 switch (type_) {
478 case Type::NONE:
479 case Type::BOOLEAN:
480 case Type::INTEGER:
481 case Type::DOUBLE:
482 InternalCopyFundamentalValue(that);
483 return;
484
485 case Type::STRING:
486 string_value_.Init(*that.string_value_);
487 return;
jdoerrie58325a42017-02-15 17:42:14 +0900488 case Type::BINARY:
489 binary_value_.Init(*that.binary_value_);
490 return;
jdoerrie1d5b3482017-02-17 22:54:49 +0900491 // DictStorage and ListStorage are move-only types due to the presence of
492 // unique_ptrs. This is why the call to |CreateDeepCopy| is necessary here.
493 // TODO(crbug.com/646113): Clean this up when DictStorage and ListStorage
494 // can be copied directly.
jdoerrie93a0cf32017-02-01 19:36:56 +0900495 case Type::DICTIONARY:
jdoerrie1d5b3482017-02-17 22:54:49 +0900496 dict_ptr_.Init(std::move(*that.CreateDeepCopy()->dict_ptr_));
497 return;
498 case Type::LIST:
499 list_.Init(std::move(*that.CreateDeepCopy()->list_));
jdoerrie93a0cf32017-02-01 19:36:56 +0900500 return;
initial.commit3f4a7322008-07-27 06:49:38 +0900501 }
502}
503
jdoerrie31299132017-02-01 23:38:32 +0900504void Value::InternalMoveConstructFrom(Value&& that) {
505 type_ = that.type_;
initial.commit3f4a7322008-07-27 06:49:38 +0900506
jdoerrie31299132017-02-01 23:38:32 +0900507 switch (type_) {
508 case Type::NONE:
509 case Type::BOOLEAN:
510 case Type::INTEGER:
511 case Type::DOUBLE:
512 InternalCopyFundamentalValue(that);
513 return;
514
515 case Type::STRING:
516 string_value_.InitFromMove(std::move(that.string_value_));
517 return;
jdoerrie58325a42017-02-15 17:42:14 +0900518 case Type::BINARY:
519 binary_value_.InitFromMove(std::move(that.binary_value_));
520 return;
jdoerrie31299132017-02-01 23:38:32 +0900521 case Type::DICTIONARY:
jdoerrie1d5b3482017-02-17 22:54:49 +0900522 dict_ptr_.InitFromMove(std::move(that.dict_ptr_));
523 return;
524 case Type::LIST:
525 list_.InitFromMove(std::move(that.list_));
jdoerrie31299132017-02-01 23:38:32 +0900526 return;
527 }
scherkus@chromium.org2b923e72008-12-11 10:23:17 +0900528}
529
vabr7eac8352017-03-08 08:34:30 +0900530void Value::InternalCopyAssignFromSameType(const Value& that) {
dyaroshev798c5ef2017-03-21 02:04:27 +0900531 // TODO(crbug.com/646113): make this a DCHECK once base::Value does not have
532 // subclasses.
vabr7eac8352017-03-08 08:34:30 +0900533 CHECK_EQ(type_, that.type_);
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900534
jdoerrie31299132017-02-01 23:38:32 +0900535 switch (type_) {
536 case Type::NONE:
537 case Type::BOOLEAN:
538 case Type::INTEGER:
539 case Type::DOUBLE:
540 InternalCopyFundamentalValue(that);
541 return;
542
543 case Type::STRING:
544 *string_value_ = *that.string_value_;
545 return;
jdoerrie58325a42017-02-15 17:42:14 +0900546 case Type::BINARY:
547 *binary_value_ = *that.binary_value_;
548 return;
jdoerrie1d5b3482017-02-17 22:54:49 +0900549 // DictStorage and ListStorage are move-only types due to the presence of
550 // unique_ptrs. This is why the call to |CreateDeepCopy| is necessary here.
551 // TODO(crbug.com/646113): Clean this up when DictStorage and ListStorage
552 // can be copied directly.
jdoerrie31299132017-02-01 23:38:32 +0900553 case Type::DICTIONARY:
jdoerrie1d5b3482017-02-17 22:54:49 +0900554 *dict_ptr_ = std::move(*that.CreateDeepCopy()->dict_ptr_);
555 return;
556 case Type::LIST:
557 *list_ = std::move(*that.CreateDeepCopy()->list_);
jdoerrie31299132017-02-01 23:38:32 +0900558 return;
559 }
initial.commit3f4a7322008-07-27 06:49:38 +0900560}
561
jdoerrie31299132017-02-01 23:38:32 +0900562void Value::InternalCleanup() {
vabr3f090ed2017-03-15 05:06:11 +0900563 CHECK(alive_);
564
jdoerrie31299132017-02-01 23:38:32 +0900565 switch (type_) {
566 case Type::NONE:
567 case Type::BOOLEAN:
568 case Type::INTEGER:
569 case Type::DOUBLE:
570 // Nothing to do
571 return;
estade@chromium.org0fd309d2014-02-06 05:42:06 +0900572
jdoerrie31299132017-02-01 23:38:32 +0900573 case Type::STRING:
574 string_value_.Destroy();
575 return;
jdoerrie58325a42017-02-15 17:42:14 +0900576 case Type::BINARY:
577 binary_value_.Destroy();
578 return;
jdoerrie31299132017-02-01 23:38:32 +0900579 case Type::DICTIONARY:
jdoerrie1d5b3482017-02-17 22:54:49 +0900580 dict_ptr_.Destroy();
581 return;
582 case Type::LIST:
583 list_.Destroy();
jdoerrie31299132017-02-01 23:38:32 +0900584 return;
585 }
initial.commit3f4a7322008-07-27 06:49:38 +0900586}
587
initial.commit3f4a7322008-07-27 06:49:38 +0900588///////////////////// DictionaryValue ////////////////////
589
reillygd39049b2015-09-11 09:25:54 +0900590// static
dchengcc8e4d82016-04-05 06:25:51 +0900591std::unique_ptr<DictionaryValue> DictionaryValue::From(
592 std::unique_ptr<Value> value) {
reillygd39049b2015-09-11 09:25:54 +0900593 DictionaryValue* out;
594 if (value && value->GetAsDictionary(&out)) {
595 ignore_result(value.release());
dchengcc8e4d82016-04-05 06:25:51 +0900596 return WrapUnique(out);
reillygd39049b2015-09-11 09:25:54 +0900597 }
598 return nullptr;
599}
600
jdoerrie89ee31a2016-12-08 00:43:28 +0900601DictionaryValue::DictionaryValue() : Value(Type::DICTIONARY) {}
erg@chromium.org493f5f62010-07-16 06:03:54 +0900602
dchengae1c2d62016-08-26 01:07:11 +0900603bool DictionaryValue::HasKey(StringPiece key) const {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900604 DCHECK(IsStringUTF8(key));
jdoerrie1d5b3482017-02-17 22:54:49 +0900605 auto current_entry = (*dict_ptr_)->find(key.as_string());
606 DCHECK((current_entry == (*dict_ptr_)->end()) || current_entry->second);
607 return current_entry != (*dict_ptr_)->end();
tony@chromium.orge4948ab2009-12-02 09:20:32 +0900608}
609
initial.commit3f4a7322008-07-27 06:49:38 +0900610void DictionaryValue::Clear() {
jdoerrie1d5b3482017-02-17 22:54:49 +0900611 (*dict_ptr_)->clear();
initial.commit3f4a7322008-07-27 06:49:38 +0900612}
613
dchengae1c2d62016-08-26 01:07:11 +0900614void DictionaryValue::Set(StringPiece path, std::unique_ptr<Value> in_value) {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900615 DCHECK(IsStringUTF8(path));
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900616 DCHECK(in_value);
617
lazyboya6030462016-10-04 09:18:57 +0900618 StringPiece current_path(path);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900619 DictionaryValue* current_dictionary = this;
620 for (size_t delimiter_position = current_path.find('.');
lazyboya6030462016-10-04 09:18:57 +0900621 delimiter_position != StringPiece::npos;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900622 delimiter_position = current_path.find('.')) {
623 // Assume that we're indexing into a dictionary.
lazyboya6030462016-10-04 09:18:57 +0900624 StringPiece key = current_path.substr(0, delimiter_position);
corona1050a617b2016-10-07 21:53:36 +0900625 DictionaryValue* child_dictionary = nullptr;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900626 if (!current_dictionary->GetDictionary(key, &child_dictionary)) {
627 child_dictionary = new DictionaryValue;
corona1050a617b2016-10-07 21:53:36 +0900628 current_dictionary->SetWithoutPathExpansion(
629 key, base::WrapUnique(child_dictionary));
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900630 }
631
632 current_dictionary = child_dictionary;
lazyboya6030462016-10-04 09:18:57 +0900633 current_path = current_path.substr(delimiter_position + 1);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900634 }
635
danakj800d2ea2015-11-25 14:29:58 +0900636 current_dictionary->SetWithoutPathExpansion(current_path,
637 std::move(in_value));
estade948395d2015-01-07 05:06:50 +0900638}
639
dchengae1c2d62016-08-26 01:07:11 +0900640void DictionaryValue::Set(StringPiece path, Value* in_value) {
dchengcc8e4d82016-04-05 06:25:51 +0900641 Set(path, WrapUnique(in_value));
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900642}
643
dchengae1c2d62016-08-26 01:07:11 +0900644void DictionaryValue::SetBoolean(StringPiece path, bool in_value) {
jdoerriebfe825e2017-03-02 21:09:19 +0900645 Set(path, new Value(in_value));
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900646}
647
dchengae1c2d62016-08-26 01:07:11 +0900648void DictionaryValue::SetInteger(StringPiece path, int in_value) {
jdoerriebfe825e2017-03-02 21:09:19 +0900649 Set(path, new Value(in_value));
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900650}
651
dchengae1c2d62016-08-26 01:07:11 +0900652void DictionaryValue::SetDouble(StringPiece path, double in_value) {
jdoerriebfe825e2017-03-02 21:09:19 +0900653 Set(path, new Value(in_value));
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900654}
655
dchengae1c2d62016-08-26 01:07:11 +0900656void DictionaryValue::SetString(StringPiece path, StringPiece in_value) {
jdoerrie0d1295b2017-03-06 20:12:04 +0900657 Set(path, new Value(in_value));
dchengae1c2d62016-08-26 01:07:11 +0900658}
659
660void DictionaryValue::SetString(StringPiece path, const string16& in_value) {
jdoerrie0d1295b2017-03-06 20:12:04 +0900661 Set(path, new Value(in_value));
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900662}
663
dchengae1c2d62016-08-26 01:07:11 +0900664void DictionaryValue::SetWithoutPathExpansion(StringPiece key,
dchengcc8e4d82016-04-05 06:25:51 +0900665 std::unique_ptr<Value> in_value) {
jdoerrie1d5b3482017-02-17 22:54:49 +0900666 (**dict_ptr_)[key.as_string()] = std::move(in_value);
initial.commit3f4a7322008-07-27 06:49:38 +0900667}
668
dchengae1c2d62016-08-26 01:07:11 +0900669void DictionaryValue::SetWithoutPathExpansion(StringPiece key,
estade948395d2015-01-07 05:06:50 +0900670 Value* in_value) {
dchengcc8e4d82016-04-05 06:25:51 +0900671 SetWithoutPathExpansion(key, WrapUnique(in_value));
estade948395d2015-01-07 05:06:50 +0900672}
673
dchengae1c2d62016-08-26 01:07:11 +0900674void DictionaryValue::SetBooleanWithoutPathExpansion(StringPiece path,
675 bool in_value) {
jdoerriebfe825e2017-03-02 21:09:19 +0900676 SetWithoutPathExpansion(path, base::MakeUnique<base::Value>(in_value));
kalman@chromium.org5081d8e2012-09-14 11:14:01 +0900677}
678
dchengae1c2d62016-08-26 01:07:11 +0900679void DictionaryValue::SetIntegerWithoutPathExpansion(StringPiece path,
680 int in_value) {
jdoerriebfe825e2017-03-02 21:09:19 +0900681 SetWithoutPathExpansion(path, base::MakeUnique<base::Value>(in_value));
kalman@chromium.org5081d8e2012-09-14 11:14:01 +0900682}
683
dchengae1c2d62016-08-26 01:07:11 +0900684void DictionaryValue::SetDoubleWithoutPathExpansion(StringPiece path,
685 double in_value) {
jdoerriebfe825e2017-03-02 21:09:19 +0900686 SetWithoutPathExpansion(path, base::MakeUnique<base::Value>(in_value));
kalman@chromium.org5081d8e2012-09-14 11:14:01 +0900687}
688
dchengae1c2d62016-08-26 01:07:11 +0900689void DictionaryValue::SetStringWithoutPathExpansion(StringPiece path,
690 StringPiece in_value) {
jdoerrie0d1295b2017-03-06 20:12:04 +0900691 SetWithoutPathExpansion(path, base::MakeUnique<base::Value>(in_value));
kalman@chromium.org5081d8e2012-09-14 11:14:01 +0900692}
693
dchengae1c2d62016-08-26 01:07:11 +0900694void DictionaryValue::SetStringWithoutPathExpansion(StringPiece path,
695 const string16& in_value) {
jdoerrie0d1295b2017-03-06 20:12:04 +0900696 SetWithoutPathExpansion(path, base::MakeUnique<base::Value>(in_value));
kalman@chromium.org5081d8e2012-09-14 11:14:01 +0900697}
698
asvitkine22632bf2015-06-24 03:22:52 +0900699bool DictionaryValue::Get(StringPiece path,
gab@chromium.org903d5c92013-11-27 10:38:24 +0900700 const Value** out_value) const {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900701 DCHECK(IsStringUTF8(path));
asvitkine22632bf2015-06-24 03:22:52 +0900702 StringPiece current_path(path);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900703 const DictionaryValue* current_dictionary = this;
704 for (size_t delimiter_position = current_path.find('.');
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900705 delimiter_position != std::string::npos;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900706 delimiter_position = current_path.find('.')) {
vabr@chromium.org74562432012-07-28 07:27:11 +0900707 const DictionaryValue* child_dictionary = NULL;
asvitkinec568efe2015-07-15 12:10:12 +0900708 if (!current_dictionary->GetDictionaryWithoutPathExpansion(
lazyboya6030462016-10-04 09:18:57 +0900709 current_path.substr(0, delimiter_position), &child_dictionary)) {
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900710 return false;
asvitkine22632bf2015-06-24 03:22:52 +0900711 }
initial.commit3f4a7322008-07-27 06:49:38 +0900712
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900713 current_dictionary = child_dictionary;
asvitkine22632bf2015-06-24 03:22:52 +0900714 current_path = current_path.substr(delimiter_position + 1);
initial.commit3f4a7322008-07-27 06:49:38 +0900715 }
716
lazyboya6030462016-10-04 09:18:57 +0900717 return current_dictionary->GetWithoutPathExpansion(current_path, out_value);
initial.commit3f4a7322008-07-27 06:49:38 +0900718}
719
asvitkine22632bf2015-06-24 03:22:52 +0900720bool DictionaryValue::Get(StringPiece path, Value** out_value) {
vabr@chromium.org74562432012-07-28 07:27:11 +0900721 return static_cast<const DictionaryValue&>(*this).Get(
722 path,
723 const_cast<const Value**>(out_value));
724}
725
dchengae1c2d62016-08-26 01:07:11 +0900726bool DictionaryValue::GetBoolean(StringPiece path, bool* bool_value) const {
vabr@chromium.org74562432012-07-28 07:27:11 +0900727 const Value* value;
initial.commit3f4a7322008-07-27 06:49:38 +0900728 if (!Get(path, &value))
729 return false;
730
731 return value->GetAsBoolean(bool_value);
732}
733
dchengae1c2d62016-08-26 01:07:11 +0900734bool DictionaryValue::GetInteger(StringPiece path, int* out_value) const {
vabr@chromium.org74562432012-07-28 07:27:11 +0900735 const Value* value;
initial.commit3f4a7322008-07-27 06:49:38 +0900736 if (!Get(path, &value))
737 return false;
738
739 return value->GetAsInteger(out_value);
740}
741
dchengae1c2d62016-08-26 01:07:11 +0900742bool DictionaryValue::GetDouble(StringPiece path, double* out_value) const {
vabr@chromium.org74562432012-07-28 07:27:11 +0900743 const Value* value;
initial.commit3f4a7322008-07-27 06:49:38 +0900744 if (!Get(path, &value))
745 return false;
746
arv@chromium.org13413eb2011-02-01 10:02:07 +0900747 return value->GetAsDouble(out_value);
initial.commit3f4a7322008-07-27 06:49:38 +0900748}
749
dchengae1c2d62016-08-26 01:07:11 +0900750bool DictionaryValue::GetString(StringPiece path,
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900751 std::string* out_value) const {
vabr@chromium.org74562432012-07-28 07:27:11 +0900752 const Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900753 if (!Get(path, &value))
754 return false;
755
756 return value->GetAsString(out_value);
757}
758
dchengae1c2d62016-08-26 01:07:11 +0900759bool DictionaryValue::GetString(StringPiece path, string16* out_value) const {
vabr@chromium.org74562432012-07-28 07:27:11 +0900760 const Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900761 if (!Get(path, &value))
762 return false;
763
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900764 return value->GetAsString(out_value);
evan@chromium.orgd9ab8de2010-02-19 22:32:16 +0900765}
766
dchengae1c2d62016-08-26 01:07:11 +0900767bool DictionaryValue::GetStringASCII(StringPiece path,
evan@chromium.orgd9ab8de2010-02-19 22:32:16 +0900768 std::string* out_value) const {
769 std::string out;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900770 if (!GetString(path, &out))
evan@chromium.orgd9ab8de2010-02-19 22:32:16 +0900771 return false;
772
773 if (!IsStringASCII(out)) {
774 NOTREACHED();
775 return false;
776 }
777
778 out_value->assign(out);
779 return true;
780}
781
dchengae1c2d62016-08-26 01:07:11 +0900782bool DictionaryValue::GetBinary(StringPiece path,
vabr@chromium.org74562432012-07-28 07:27:11 +0900783 const BinaryValue** out_value) const {
784 const Value* value;
initial.commit3f4a7322008-07-27 06:49:38 +0900785 bool result = Get(path, &value);
jdoerrie89ee31a2016-12-08 00:43:28 +0900786 if (!result || !value->IsType(Type::BINARY))
initial.commit3f4a7322008-07-27 06:49:38 +0900787 return false;
788
789 if (out_value)
jdoerrie58325a42017-02-15 17:42:14 +0900790 *out_value = value;
initial.commit3f4a7322008-07-27 06:49:38 +0900791
792 return true;
793}
794
dchengae1c2d62016-08-26 01:07:11 +0900795bool DictionaryValue::GetBinary(StringPiece path, BinaryValue** out_value) {
vabr@chromium.org74562432012-07-28 07:27:11 +0900796 return static_cast<const DictionaryValue&>(*this).GetBinary(
797 path,
798 const_cast<const BinaryValue**>(out_value));
799}
800
asvitkine22632bf2015-06-24 03:22:52 +0900801bool DictionaryValue::GetDictionary(StringPiece path,
vabr@chromium.org74562432012-07-28 07:27:11 +0900802 const DictionaryValue** out_value) const {
803 const Value* value;
initial.commit3f4a7322008-07-27 06:49:38 +0900804 bool result = Get(path, &value);
jdoerrie89ee31a2016-12-08 00:43:28 +0900805 if (!result || !value->IsType(Type::DICTIONARY))
initial.commit3f4a7322008-07-27 06:49:38 +0900806 return false;
807
808 if (out_value)
vabr@chromium.org74562432012-07-28 07:27:11 +0900809 *out_value = static_cast<const DictionaryValue*>(value);
initial.commit3f4a7322008-07-27 06:49:38 +0900810
811 return true;
812}
813
asvitkine22632bf2015-06-24 03:22:52 +0900814bool DictionaryValue::GetDictionary(StringPiece path,
vabr@chromium.org74562432012-07-28 07:27:11 +0900815 DictionaryValue** out_value) {
816 return static_cast<const DictionaryValue&>(*this).GetDictionary(
817 path,
818 const_cast<const DictionaryValue**>(out_value));
819}
820
dchengae1c2d62016-08-26 01:07:11 +0900821bool DictionaryValue::GetList(StringPiece path,
vabr@chromium.org74562432012-07-28 07:27:11 +0900822 const ListValue** out_value) const {
823 const Value* value;
initial.commit3f4a7322008-07-27 06:49:38 +0900824 bool result = Get(path, &value);
jdoerrie89ee31a2016-12-08 00:43:28 +0900825 if (!result || !value->IsType(Type::LIST))
initial.commit3f4a7322008-07-27 06:49:38 +0900826 return false;
827
828 if (out_value)
vabr@chromium.org74562432012-07-28 07:27:11 +0900829 *out_value = static_cast<const ListValue*>(value);
initial.commit3f4a7322008-07-27 06:49:38 +0900830
831 return true;
832}
833
dchengae1c2d62016-08-26 01:07:11 +0900834bool DictionaryValue::GetList(StringPiece path, ListValue** out_value) {
vabr@chromium.org74562432012-07-28 07:27:11 +0900835 return static_cast<const DictionaryValue&>(*this).GetList(
836 path,
837 const_cast<const ListValue**>(out_value));
838}
839
dchengae1c2d62016-08-26 01:07:11 +0900840bool DictionaryValue::GetWithoutPathExpansion(StringPiece key,
vabr@chromium.org74562432012-07-28 07:27:11 +0900841 const Value** out_value) const {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900842 DCHECK(IsStringUTF8(key));
jdoerrie1d5b3482017-02-17 22:54:49 +0900843 auto entry_iterator = (*dict_ptr_)->find(key.as_string());
844 if (entry_iterator == (*dict_ptr_)->end())
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900845 return false;
initial.commit3f4a7322008-07-27 06:49:38 +0900846
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900847 if (out_value)
dcheng1fa44fb2016-05-26 03:30:47 +0900848 *out_value = entry_iterator->second.get();
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900849 return true;
850}
851
dchengae1c2d62016-08-26 01:07:11 +0900852bool DictionaryValue::GetWithoutPathExpansion(StringPiece key,
vabr@chromium.org74562432012-07-28 07:27:11 +0900853 Value** out_value) {
854 return static_cast<const DictionaryValue&>(*this).GetWithoutPathExpansion(
855 key,
856 const_cast<const Value**>(out_value));
857}
858
dchengae1c2d62016-08-26 01:07:11 +0900859bool DictionaryValue::GetBooleanWithoutPathExpansion(StringPiece key,
pneubeck@chromium.org3b600542012-11-07 01:46:55 +0900860 bool* out_value) const {
861 const Value* value;
862 if (!GetWithoutPathExpansion(key, &value))
863 return false;
864
865 return value->GetAsBoolean(out_value);
866}
867
dchengae1c2d62016-08-26 01:07:11 +0900868bool DictionaryValue::GetIntegerWithoutPathExpansion(StringPiece key,
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900869 int* out_value) const {
vabr@chromium.org74562432012-07-28 07:27:11 +0900870 const Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900871 if (!GetWithoutPathExpansion(key, &value))
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900872 return false;
873
874 return value->GetAsInteger(out_value);
875}
876
dchengae1c2d62016-08-26 01:07:11 +0900877bool DictionaryValue::GetDoubleWithoutPathExpansion(StringPiece key,
arv@chromium.org13413eb2011-02-01 10:02:07 +0900878 double* out_value) const {
vabr@chromium.org74562432012-07-28 07:27:11 +0900879 const Value* value;
jam@chromium.org5bd53922010-10-01 16:28:25 +0900880 if (!GetWithoutPathExpansion(key, &value))
881 return false;
882
arv@chromium.org13413eb2011-02-01 10:02:07 +0900883 return value->GetAsDouble(out_value);
jam@chromium.org5bd53922010-10-01 16:28:25 +0900884}
885
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900886bool DictionaryValue::GetStringWithoutPathExpansion(
dchengae1c2d62016-08-26 01:07:11 +0900887 StringPiece key,
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900888 std::string* out_value) const {
vabr@chromium.org74562432012-07-28 07:27:11 +0900889 const Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900890 if (!GetWithoutPathExpansion(key, &value))
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900891 return false;
892
893 return value->GetAsString(out_value);
894}
895
dchengae1c2d62016-08-26 01:07:11 +0900896bool DictionaryValue::GetStringWithoutPathExpansion(StringPiece key,
vabr@chromium.org74562432012-07-28 07:27:11 +0900897 string16* out_value) const {
898 const Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900899 if (!GetWithoutPathExpansion(key, &value))
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900900 return false;
901
viettrungluu@chromium.org31b80ba2010-08-04 00:42:58 +0900902 return value->GetAsString(out_value);
munjal@chromium.org3b2d3a42010-01-16 05:09:03 +0900903}
904
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900905bool DictionaryValue::GetDictionaryWithoutPathExpansion(
dchengae1c2d62016-08-26 01:07:11 +0900906 StringPiece key,
vabr@chromium.org74562432012-07-28 07:27:11 +0900907 const DictionaryValue** out_value) const {
908 const Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900909 bool result = GetWithoutPathExpansion(key, &value);
jdoerrie89ee31a2016-12-08 00:43:28 +0900910 if (!result || !value->IsType(Type::DICTIONARY))
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900911 return false;
912
913 if (out_value)
vabr@chromium.org74562432012-07-28 07:27:11 +0900914 *out_value = static_cast<const DictionaryValue*>(value);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900915
916 return true;
917}
918
vabr@chromium.org74562432012-07-28 07:27:11 +0900919bool DictionaryValue::GetDictionaryWithoutPathExpansion(
dchengae1c2d62016-08-26 01:07:11 +0900920 StringPiece key,
vabr@chromium.org74562432012-07-28 07:27:11 +0900921 DictionaryValue** out_value) {
922 const DictionaryValue& const_this =
923 static_cast<const DictionaryValue&>(*this);
924 return const_this.GetDictionaryWithoutPathExpansion(
925 key,
926 const_cast<const DictionaryValue**>(out_value));
927}
928
929bool DictionaryValue::GetListWithoutPathExpansion(
dchengae1c2d62016-08-26 01:07:11 +0900930 StringPiece key,
vabr@chromium.org74562432012-07-28 07:27:11 +0900931 const ListValue** out_value) const {
932 const Value* value;
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900933 bool result = GetWithoutPathExpansion(key, &value);
jdoerrie89ee31a2016-12-08 00:43:28 +0900934 if (!result || !value->IsType(Type::LIST))
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900935 return false;
936
937 if (out_value)
vabr@chromium.org74562432012-07-28 07:27:11 +0900938 *out_value = static_cast<const ListValue*>(value);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900939
940 return true;
941}
942
dchengae1c2d62016-08-26 01:07:11 +0900943bool DictionaryValue::GetListWithoutPathExpansion(StringPiece key,
vabr@chromium.org74562432012-07-28 07:27:11 +0900944 ListValue** out_value) {
945 return
946 static_cast<const DictionaryValue&>(*this).GetListWithoutPathExpansion(
947 key,
948 const_cast<const ListValue**>(out_value));
949}
950
dchengae1c2d62016-08-26 01:07:11 +0900951bool DictionaryValue::Remove(StringPiece path,
dchengcc8e4d82016-04-05 06:25:51 +0900952 std::unique_ptr<Value>* out_value) {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900953 DCHECK(IsStringUTF8(path));
lazyboya6030462016-10-04 09:18:57 +0900954 StringPiece current_path(path);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900955 DictionaryValue* current_dictionary = this;
956 size_t delimiter_position = current_path.rfind('.');
lazyboya6030462016-10-04 09:18:57 +0900957 if (delimiter_position != StringPiece::npos) {
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900958 if (!GetDictionary(current_path.substr(0, delimiter_position),
959 &current_dictionary))
960 return false;
lazyboya6030462016-10-04 09:18:57 +0900961 current_path = current_path.substr(delimiter_position + 1);
initial.commit3f4a7322008-07-27 06:49:38 +0900962 }
963
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900964 return current_dictionary->RemoveWithoutPathExpansion(current_path,
965 out_value);
966}
967
dchengcc8e4d82016-04-05 06:25:51 +0900968bool DictionaryValue::RemoveWithoutPathExpansion(
dchengae1c2d62016-08-26 01:07:11 +0900969 StringPiece key,
dchengcc8e4d82016-04-05 06:25:51 +0900970 std::unique_ptr<Value>* out_value) {
viettrungluu@chromium.org4c86b852010-08-06 15:03:25 +0900971 DCHECK(IsStringUTF8(key));
jdoerrie1d5b3482017-02-17 22:54:49 +0900972 auto entry_iterator = (*dict_ptr_)->find(key.as_string());
973 if (entry_iterator == (*dict_ptr_)->end())
initial.commit3f4a7322008-07-27 06:49:38 +0900974 return false;
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900975
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900976 if (out_value)
dcheng1fa44fb2016-05-26 03:30:47 +0900977 *out_value = std::move(entry_iterator->second);
jdoerrie1d5b3482017-02-17 22:54:49 +0900978 (*dict_ptr_)->erase(entry_iterator);
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900979 return true;
initial.commit3f4a7322008-07-27 06:49:38 +0900980}
981
dchengae1c2d62016-08-26 01:07:11 +0900982bool DictionaryValue::RemovePath(StringPiece path,
dchengcc8e4d82016-04-05 06:25:51 +0900983 std::unique_ptr<Value>* out_value) {
gab@chromium.org903d5c92013-11-27 10:38:24 +0900984 bool result = false;
985 size_t delimiter_position = path.find('.');
986
987 if (delimiter_position == std::string::npos)
988 return RemoveWithoutPathExpansion(path, out_value);
989
dchengae1c2d62016-08-26 01:07:11 +0900990 StringPiece subdict_path = path.substr(0, delimiter_position);
gab@chromium.org903d5c92013-11-27 10:38:24 +0900991 DictionaryValue* subdict = NULL;
992 if (!GetDictionary(subdict_path, &subdict))
993 return false;
994 result = subdict->RemovePath(path.substr(delimiter_position + 1),
995 out_value);
996 if (result && subdict->empty())
997 RemoveWithoutPathExpansion(subdict_path, NULL);
998
999 return result;
1000}
1001
dchengcc8e4d82016-04-05 06:25:51 +09001002std::unique_ptr<DictionaryValue> DictionaryValue::DeepCopyWithoutEmptyChildren()
estade51a57ab2015-05-23 11:42:09 +09001003 const {
dchengcc8e4d82016-04-05 06:25:51 +09001004 std::unique_ptr<DictionaryValue> copy =
1005 CopyDictionaryWithoutEmptyChildren(*this);
estade51a57ab2015-05-23 11:42:09 +09001006 if (!copy)
1007 copy.reset(new DictionaryValue);
1008 return copy;
initial.commit3f4a7322008-07-27 06:49:38 +09001009}
1010
mnissler@chromium.org17cee0e2010-05-14 22:17:40 +09001011void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) {
vabr7eac8352017-03-08 08:34:30 +09001012 CHECK(dictionary->is_dict());
pneubeck@chromium.org03ed8622013-03-10 20:32:49 +09001013 for (DictionaryValue::Iterator it(*dictionary); !it.IsAtEnd(); it.Advance()) {
1014 const Value* merge_value = &it.value();
1015 // Check whether we have to merge dictionaries.
jdoerrie89ee31a2016-12-08 00:43:28 +09001016 if (merge_value->IsType(Value::Type::DICTIONARY)) {
pneubeck@chromium.org03ed8622013-03-10 20:32:49 +09001017 DictionaryValue* sub_dict;
1018 if (GetDictionaryWithoutPathExpansion(it.key(), &sub_dict)) {
1019 sub_dict->MergeDictionary(
1020 static_cast<const DictionaryValue*>(merge_value));
1021 continue;
mnissler@chromium.org17cee0e2010-05-14 22:17:40 +09001022 }
mnissler@chromium.org17cee0e2010-05-14 22:17:40 +09001023 }
pneubeck@chromium.org03ed8622013-03-10 20:32:49 +09001024 // All other cases: Make a copy and hook it up.
corona1050a617b2016-10-07 21:53:36 +09001025 SetWithoutPathExpansion(it.key(),
1026 base::WrapUnique(merge_value->DeepCopy()));
mnissler@chromium.org17cee0e2010-05-14 22:17:40 +09001027 }
1028}
1029
rsesek@chromium.orgc2d2b202012-05-17 00:23:30 +09001030void DictionaryValue::Swap(DictionaryValue* other) {
vabr7eac8352017-03-08 08:34:30 +09001031 CHECK(other->is_dict());
jdoerrie1d5b3482017-02-17 22:54:49 +09001032 dict_ptr_->swap(*(other->dict_ptr_));
rsesek@chromium.orgc2d2b202012-05-17 00:23:30 +09001033}
1034
hans@chromium.orgd5d38e32012-08-10 21:45:35 +09001035DictionaryValue::Iterator::Iterator(const DictionaryValue& target)
jdoerrie1d5b3482017-02-17 22:54:49 +09001036 : target_(target), it_((*target.dict_ptr_)->begin()) {}
hans@chromium.orgd5d38e32012-08-10 21:45:35 +09001037
vmpstrc8651bf2016-02-25 09:50:31 +09001038DictionaryValue::Iterator::Iterator(const Iterator& other) = default;
1039
phajdan.jr@chromium.org8e2b2082013-12-11 03:52:22 +09001040DictionaryValue::Iterator::~Iterator() {}
1041
akalin@chromium.org810f92f2011-01-18 11:16:59 +09001042DictionaryValue* DictionaryValue::DeepCopy() const {
jdoerrie1d5b3482017-02-17 22:54:49 +09001043 return static_cast<DictionaryValue*>(Value::DeepCopy());
erg@google.com67a25432011-01-08 05:23:43 +09001044}
1045
dchengcc8e4d82016-04-05 06:25:51 +09001046std::unique_ptr<DictionaryValue> DictionaryValue::CreateDeepCopy() const {
1047 return WrapUnique(DeepCopy());
estade77a018f2015-05-07 10:53:08 +09001048}
1049
initial.commit3f4a7322008-07-27 06:49:38 +09001050///////////////////// ListValue ////////////////////
1051
reillygd39049b2015-09-11 09:25:54 +09001052// static
dchengcc8e4d82016-04-05 06:25:51 +09001053std::unique_ptr<ListValue> ListValue::From(std::unique_ptr<Value> value) {
reillygd39049b2015-09-11 09:25:54 +09001054 ListValue* out;
1055 if (value && value->GetAsList(&out)) {
1056 ignore_result(value.release());
dchengcc8e4d82016-04-05 06:25:51 +09001057 return WrapUnique(out);
reillygd39049b2015-09-11 09:25:54 +09001058 }
1059 return nullptr;
1060}
1061
jdoerrie89ee31a2016-12-08 00:43:28 +09001062ListValue::ListValue() : Value(Type::LIST) {}
erg@chromium.org493f5f62010-07-16 06:03:54 +09001063
initial.commit3f4a7322008-07-27 06:49:38 +09001064void ListValue::Clear() {
jdoerrie1d5b3482017-02-17 22:54:49 +09001065 list_->clear();
initial.commit3f4a7322008-07-27 06:49:38 +09001066}
1067
1068bool ListValue::Set(size_t index, Value* in_value) {
dcheng1fa44fb2016-05-26 03:30:47 +09001069 return Set(index, WrapUnique(in_value));
1070}
1071
1072bool ListValue::Set(size_t index, std::unique_ptr<Value> in_value) {
initial.commit3f4a7322008-07-27 06:49:38 +09001073 if (!in_value)
1074 return false;
1075
jdoerrie1d5b3482017-02-17 22:54:49 +09001076 if (index >= list_->size()) {
initial.commit3f4a7322008-07-27 06:49:38 +09001077 // Pad out any intermediate indexes with null settings
jdoerrie1d5b3482017-02-17 22:54:49 +09001078 while (index > list_->size())
initial.commit3f4a7322008-07-27 06:49:38 +09001079 Append(CreateNullValue());
dcheng1fa44fb2016-05-26 03:30:47 +09001080 Append(std::move(in_value));
initial.commit3f4a7322008-07-27 06:49:38 +09001081 } else {
dcheng1fa44fb2016-05-26 03:30:47 +09001082 // TODO(dcheng): remove this DCHECK once the raw pointer version is removed?
jdoerrie1d5b3482017-02-17 22:54:49 +09001083 DCHECK((*list_)[index] != in_value);
1084 (*list_)[index] = std::move(in_value);
initial.commit3f4a7322008-07-27 06:49:38 +09001085 }
1086 return true;
1087}
1088
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +09001089bool ListValue::Get(size_t index, const Value** out_value) const {
jdoerrie1d5b3482017-02-17 22:54:49 +09001090 if (index >= list_->size())
initial.commit3f4a7322008-07-27 06:49:38 +09001091 return false;
1092
1093 if (out_value)
jdoerrie1d5b3482017-02-17 22:54:49 +09001094 *out_value = (*list_)[index].get();
initial.commit3f4a7322008-07-27 06:49:38 +09001095
1096 return true;
1097}
1098
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +09001099bool ListValue::Get(size_t index, Value** out_value) {
1100 return static_cast<const ListValue&>(*this).Get(
1101 index,
1102 const_cast<const Value**>(out_value));
1103}
1104
aa@chromium.orgc93b02f2009-01-21 06:05:32 +09001105bool ListValue::GetBoolean(size_t index, bool* bool_value) const {
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +09001106 const Value* value;
aa@chromium.orgc93b02f2009-01-21 06:05:32 +09001107 if (!Get(index, &value))
1108 return false;
1109
1110 return value->GetAsBoolean(bool_value);
1111}
1112
1113bool ListValue::GetInteger(size_t index, int* out_value) const {
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +09001114 const Value* value;
aa@chromium.orgc93b02f2009-01-21 06:05:32 +09001115 if (!Get(index, &value))
1116 return false;
1117
1118 return value->GetAsInteger(out_value);
1119}
1120
arv@chromium.org13413eb2011-02-01 10:02:07 +09001121bool ListValue::GetDouble(size_t index, double* out_value) const {
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +09001122 const Value* value;
aa@chromium.orgc93b02f2009-01-21 06:05:32 +09001123 if (!Get(index, &value))
1124 return false;
1125
arv@chromium.org13413eb2011-02-01 10:02:07 +09001126 return value->GetAsDouble(out_value);
aa@chromium.orgc93b02f2009-01-21 06:05:32 +09001127}
1128
1129bool ListValue::GetString(size_t index, std::string* out_value) const {
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +09001130 const Value* value;
aa@chromium.orgc93b02f2009-01-21 06:05:32 +09001131 if (!Get(index, &value))
1132 return false;
1133
1134 return value->GetAsString(out_value);
1135}
1136
viettrungluu@chromium.org58767ef2010-08-05 04:35:33 +09001137bool ListValue::GetString(size_t index, string16* out_value) const {
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +09001138 const Value* value;
viettrungluu@chromium.org58767ef2010-08-05 04:35:33 +09001139 if (!Get(index, &value))
1140 return false;
1141
1142 return value->GetAsString(out_value);
1143}
1144
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +09001145bool ListValue::GetBinary(size_t index, const BinaryValue** out_value) const {
1146 const Value* value;
aa@chromium.orgc93b02f2009-01-21 06:05:32 +09001147 bool result = Get(index, &value);
jdoerrie89ee31a2016-12-08 00:43:28 +09001148 if (!result || !value->IsType(Type::BINARY))
aa@chromium.orgc93b02f2009-01-21 06:05:32 +09001149 return false;
1150
1151 if (out_value)
jdoerrie58325a42017-02-15 17:42:14 +09001152 *out_value = value;
aa@chromium.orgc93b02f2009-01-21 06:05:32 +09001153
1154 return true;
1155}
1156
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +09001157bool ListValue::GetBinary(size_t index, BinaryValue** out_value) {
1158 return static_cast<const ListValue&>(*this).GetBinary(
1159 index,
1160 const_cast<const BinaryValue**>(out_value));
1161}
1162
1163bool ListValue::GetDictionary(size_t index,
1164 const DictionaryValue** out_value) const {
1165 const Value* value;
initial.commit3f4a7322008-07-27 06:49:38 +09001166 bool result = Get(index, &value);
jdoerrie89ee31a2016-12-08 00:43:28 +09001167 if (!result || !value->IsType(Type::DICTIONARY))
initial.commit3f4a7322008-07-27 06:49:38 +09001168 return false;
1169
1170 if (out_value)
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +09001171 *out_value = static_cast<const DictionaryValue*>(value);
initial.commit3f4a7322008-07-27 06:49:38 +09001172
1173 return true;
1174}
1175
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +09001176bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) {
1177 return static_cast<const ListValue&>(*this).GetDictionary(
1178 index,
1179 const_cast<const DictionaryValue**>(out_value));
1180}
1181
1182bool ListValue::GetList(size_t index, const ListValue** out_value) const {
1183 const Value* value;
aa@chromium.orgc93b02f2009-01-21 06:05:32 +09001184 bool result = Get(index, &value);
jdoerrie89ee31a2016-12-08 00:43:28 +09001185 if (!result || !value->IsType(Type::LIST))
aa@chromium.orgc93b02f2009-01-21 06:05:32 +09001186 return false;
1187
1188 if (out_value)
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +09001189 *out_value = static_cast<const ListValue*>(value);
aa@chromium.orgc93b02f2009-01-21 06:05:32 +09001190
1191 return true;
1192}
1193
vabr@chromium.orga8ca4fd2012-08-03 17:43:37 +09001194bool ListValue::GetList(size_t index, ListValue** out_value) {
1195 return static_cast<const ListValue&>(*this).GetList(
1196 index,
1197 const_cast<const ListValue**>(out_value));
1198}
1199
dchengcc8e4d82016-04-05 06:25:51 +09001200bool ListValue::Remove(size_t index, std::unique_ptr<Value>* out_value) {
jdoerrie1d5b3482017-02-17 22:54:49 +09001201 if (index >= list_->size())
initial.commit3f4a7322008-07-27 06:49:38 +09001202 return false;
1203
1204 if (out_value)
jdoerrie1d5b3482017-02-17 22:54:49 +09001205 *out_value = std::move((*list_)[index]);
initial.commit3f4a7322008-07-27 06:49:38 +09001206
jdoerrie1d5b3482017-02-17 22:54:49 +09001207 list_->erase(list_->begin() + index);
initial.commit3f4a7322008-07-27 06:49:38 +09001208 return true;
1209}
1210
tfarina@chromium.org09cf4342011-08-14 02:34:31 +09001211bool ListValue::Remove(const Value& value, size_t* index) {
jdoerrie1d5b3482017-02-17 22:54:49 +09001212 for (auto it = list_->begin(); it != list_->end(); ++it) {
dcheng1fa44fb2016-05-26 03:30:47 +09001213 if ((*it)->Equals(&value)) {
jdoerrie1d5b3482017-02-17 22:54:49 +09001214 size_t previous_index = it - list_->begin();
1215 list_->erase(it);
robertshield@chromium.org9fb9e372010-03-23 05:12:50 +09001216
tfarina@chromium.org09cf4342011-08-14 02:34:31 +09001217 if (index)
1218 *index = previous_index;
1219 return true;
pkasting@chromium.org727139c2009-05-09 09:33:04 +09001220 }
1221 }
tfarina@chromium.org09cf4342011-08-14 02:34:31 +09001222 return false;
pkasting@chromium.org727139c2009-05-09 09:33:04 +09001223}
1224
bauerb@chromium.orgae43e0a2013-08-06 22:33:04 +09001225ListValue::iterator ListValue::Erase(iterator iter,
dchengcc8e4d82016-04-05 06:25:51 +09001226 std::unique_ptr<Value>* out_value) {
estade@chromium.org52852d52012-07-03 11:51:43 +09001227 if (out_value)
jdoerrie1d5b3482017-02-17 22:54:49 +09001228 *out_value = std::move(*ListStorage::iterator(iter));
estade@chromium.org52852d52012-07-03 11:51:43 +09001229
jdoerrie1d5b3482017-02-17 22:54:49 +09001230 return list_->erase(iter);
estade@chromium.org52852d52012-07-03 11:51:43 +09001231}
1232
dchengcc8e4d82016-04-05 06:25:51 +09001233void ListValue::Append(std::unique_ptr<Value> in_value) {
jdoerrie1d5b3482017-02-17 22:54:49 +09001234 list_->push_back(std::move(in_value));
estade77a018f2015-05-07 10:53:08 +09001235}
1236
dchengd66aba82016-10-17 11:19:00 +09001237#if !defined(OS_LINUX)
initial.commit3f4a7322008-07-27 06:49:38 +09001238void ListValue::Append(Value* in_value) {
1239 DCHECK(in_value);
dcheng1fa44fb2016-05-26 03:30:47 +09001240 Append(WrapUnique(in_value));
initial.commit3f4a7322008-07-27 06:49:38 +09001241}
dcheng17f21de2016-09-17 10:30:15 +09001242#endif
initial.commit3f4a7322008-07-27 06:49:38 +09001243
kalman@chromium.org5081d8e2012-09-14 11:14:01 +09001244void ListValue::AppendBoolean(bool in_value) {
jdoerriebfe825e2017-03-02 21:09:19 +09001245 Append(MakeUnique<Value>(in_value));
kalman@chromium.org5081d8e2012-09-14 11:14:01 +09001246}
1247
1248void ListValue::AppendInteger(int in_value) {
jdoerriebfe825e2017-03-02 21:09:19 +09001249 Append(MakeUnique<Value>(in_value));
kalman@chromium.org5081d8e2012-09-14 11:14:01 +09001250}
1251
1252void ListValue::AppendDouble(double in_value) {
jdoerriebfe825e2017-03-02 21:09:19 +09001253 Append(MakeUnique<Value>(in_value));
kalman@chromium.org5081d8e2012-09-14 11:14:01 +09001254}
1255
dchengae1c2d62016-08-26 01:07:11 +09001256void ListValue::AppendString(StringPiece in_value) {
jdoerrie0d1295b2017-03-06 20:12:04 +09001257 Append(MakeUnique<Value>(in_value));
kalman@chromium.org5081d8e2012-09-14 11:14:01 +09001258}
1259
1260void ListValue::AppendString(const string16& in_value) {
jdoerrie0d1295b2017-03-06 20:12:04 +09001261 Append(MakeUnique<Value>(in_value));
kalman@chromium.org5081d8e2012-09-14 11:14:01 +09001262}
1263
1264void ListValue::AppendStrings(const std::vector<std::string>& in_values) {
1265 for (std::vector<std::string>::const_iterator it = in_values.begin();
1266 it != in_values.end(); ++it) {
1267 AppendString(*it);
1268 }
1269}
1270
1271void ListValue::AppendStrings(const std::vector<string16>& in_values) {
1272 for (std::vector<string16>::const_iterator it = in_values.begin();
1273 it != in_values.end(); ++it) {
1274 AppendString(*it);
1275 }
1276}
1277
dcheng46cc6ec2016-09-14 14:49:58 +09001278bool ListValue::AppendIfNotPresent(std::unique_ptr<Value> in_value) {
zork@chromium.orgb5f742b2010-04-13 06:48:10 +09001279 DCHECK(in_value);
jdoerrie1d5b3482017-02-17 22:54:49 +09001280 for (const auto& entry : *list_) {
dcheng46cc6ec2016-09-14 14:49:58 +09001281 if (entry->Equals(in_value.get())) {
zork@chromium.orgb5f742b2010-04-13 06:48:10 +09001282 return false;
markusheintz@chromium.org78621872011-03-18 22:56:38 +09001283 }
zork@chromium.orgb5f742b2010-04-13 06:48:10 +09001284 }
jdoerrie1d5b3482017-02-17 22:54:49 +09001285 list_->push_back(std::move(in_value));
zork@chromium.orgb5f742b2010-04-13 06:48:10 +09001286 return true;
1287}
1288
dcheng46cc6ec2016-09-14 14:49:58 +09001289bool ListValue::Insert(size_t index, std::unique_ptr<Value> in_value) {
erikkay@chromium.org9034a232009-08-29 05:26:05 +09001290 DCHECK(in_value);
jdoerrie1d5b3482017-02-17 22:54:49 +09001291 if (index > list_->size())
erikkay@chromium.org9034a232009-08-29 05:26:05 +09001292 return false;
1293
jdoerrie1d5b3482017-02-17 22:54:49 +09001294 list_->insert(list_->begin() + index, std::move(in_value));
erikkay@chromium.org9034a232009-08-29 05:26:05 +09001295 return true;
1296}
1297
pastarmovj@chromium.org1602a472011-09-20 00:23:10 +09001298ListValue::const_iterator ListValue::Find(const Value& value) const {
jdoerrie1d5b3482017-02-17 22:54:49 +09001299 return std::find_if(list_->begin(), list_->end(),
dcheng1fa44fb2016-05-26 03:30:47 +09001300 [&value](const std::unique_ptr<Value>& entry) {
1301 return entry->Equals(&value);
1302 });
pastarmovj@chromium.org1602a472011-09-20 00:23:10 +09001303}
1304
rsesek@chromium.orgc2d2b202012-05-17 00:23:30 +09001305void ListValue::Swap(ListValue* other) {
vabr7eac8352017-03-08 08:34:30 +09001306 CHECK(other->is_list());
jdoerrie1d5b3482017-02-17 22:54:49 +09001307 list_->swap(*(other->list_));
bauerb@chromium.org6878e502011-07-12 18:04:38 +09001308}
1309
akalin@chromium.org810f92f2011-01-18 11:16:59 +09001310ListValue* ListValue::DeepCopy() const {
jdoerrie1d5b3482017-02-17 22:54:49 +09001311 return static_cast<ListValue*>(Value::DeepCopy());
initial.commit3f4a7322008-07-27 06:49:38 +09001312}
1313
dchengcc8e4d82016-04-05 06:25:51 +09001314std::unique_ptr<ListValue> ListValue::CreateDeepCopy() const {
1315 return WrapUnique(DeepCopy());
estade033e61e2015-05-13 03:11:50 +09001316}
1317
erg@chromium.org493f5f62010-07-16 06:03:54 +09001318ValueSerializer::~ValueSerializer() {
1319}
tfarina@chromium.orgde3ef412011-08-05 08:51:10 +09001320
prashhir58322f42015-03-05 18:30:57 +09001321ValueDeserializer::~ValueDeserializer() {
1322}
1323
kalman@chromium.org829cf752012-09-12 12:39:35 +09001324std::ostream& operator<<(std::ostream& out, const Value& value) {
1325 std::string json;
estadeb5f30dd2015-05-16 10:02:34 +09001326 JSONWriter::WriteWithOptions(value, JSONWriter::OPTIONS_PRETTY_PRINT, &json);
kalman@chromium.org829cf752012-09-12 12:39:35 +09001327 return out << json;
1328}
1329
jdoerrie89ee31a2016-12-08 00:43:28 +09001330std::ostream& operator<<(std::ostream& out, const Value::Type& type) {
1331 if (static_cast<int>(type) < 0 ||
1332 static_cast<size_t>(type) >= arraysize(kTypeNames))
1333 return out << "Invalid Type (index = " << static_cast<int>(type) << ")";
1334 return out << Value::GetTypeName(type);
1335}
1336
tfarina@chromium.orgde3ef412011-08-05 08:51:10 +09001337} // namespace base