1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/values.h"
6
7 #include <string.h>
8
9 #include <algorithm>
10 #include <cmath>
11 #include <new>
12 #include <ostream>
13 #include <utility>
14
15 #include "base/json/json_writer.h"
16 #include "base/logging.h"
17 #include "base/memory/ptr_util.h"
18 #include "base/stl_util.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/utf_string_conversions.h"
21 // Unsupported in libchrome
22 // #include "base/trace_event/memory_usage_estimator.h"
23
24 namespace base {
25
26 namespace {
27
28 const char* const kTypeNames[] = {"null", "boolean", "integer", "double",
29 "string", "binary", "dictionary", "list"};
30 static_assert(arraysize(kTypeNames) ==
31 static_cast<size_t>(Value::Type::LIST) + 1,
32 "kTypeNames Has Wrong Size");
33
34 std::unique_ptr<Value> CopyWithoutEmptyChildren(const Value& node);
35
36 // Make a deep copy of |node|, but don't include empty lists or dictionaries
37 // in the copy. It's possible for this function to return NULL and it
38 // expects |node| to always be non-NULL.
CopyListWithoutEmptyChildren(const Value & list)39 std::unique_ptr<Value> CopyListWithoutEmptyChildren(const Value& list) {
40 Value copy(Value::Type::LIST);
41 for (const auto& entry : list.GetList()) {
42 std::unique_ptr<Value> child_copy = CopyWithoutEmptyChildren(entry);
43 if (child_copy)
44 copy.GetList().push_back(std::move(*child_copy));
45 }
46 return copy.GetList().empty() ? nullptr
47 : std::make_unique<Value>(std::move(copy));
48 }
49
CopyDictionaryWithoutEmptyChildren(const DictionaryValue & dict)50 std::unique_ptr<DictionaryValue> CopyDictionaryWithoutEmptyChildren(
51 const DictionaryValue& dict) {
52 std::unique_ptr<DictionaryValue> copy;
53 for (DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
54 std::unique_ptr<Value> child_copy = CopyWithoutEmptyChildren(it.value());
55 if (child_copy) {
56 if (!copy)
57 copy = std::make_unique<DictionaryValue>();
58 copy->SetWithoutPathExpansion(it.key(), std::move(child_copy));
59 }
60 }
61 return copy;
62 }
63
CopyWithoutEmptyChildren(const Value & node)64 std::unique_ptr<Value> CopyWithoutEmptyChildren(const Value& node) {
65 switch (node.type()) {
66 case Value::Type::LIST:
67 return CopyListWithoutEmptyChildren(static_cast<const ListValue&>(node));
68
69 case Value::Type::DICTIONARY:
70 return CopyDictionaryWithoutEmptyChildren(
71 static_cast<const DictionaryValue&>(node));
72
73 default:
74 return std::make_unique<Value>(node.Clone());
75 }
76 }
77
78 } // namespace
79
80 // static
CreateWithCopiedBuffer(const char * buffer,size_t size)81 std::unique_ptr<Value> Value::CreateWithCopiedBuffer(const char* buffer,
82 size_t size) {
83 return std::make_unique<Value>(BlobStorage(buffer, buffer + size));
84 }
85
86 // static
FromUniquePtrValue(std::unique_ptr<Value> val)87 Value Value::FromUniquePtrValue(std::unique_ptr<Value> val) {
88 return std::move(*val);
89 }
90
91 // static
ToUniquePtrValue(Value val)92 std::unique_ptr<Value> Value::ToUniquePtrValue(Value val) {
93 return std::make_unique<Value>(std::move(val));
94 }
95
Value(Value && that)96 Value::Value(Value&& that) noexcept {
97 InternalMoveConstructFrom(std::move(that));
98 }
99
Value()100 Value::Value() noexcept : type_(Type::NONE) {}
101
Value(Type type)102 Value::Value(Type type) : type_(type) {
103 // Initialize with the default value.
104 switch (type_) {
105 case Type::NONE:
106 return;
107
108 case Type::BOOLEAN:
109 bool_value_ = false;
110 return;
111 case Type::INTEGER:
112 int_value_ = 0;
113 return;
114 case Type::DOUBLE:
115 double_value_ = 0.0;
116 return;
117 case Type::STRING:
118 new (&string_value_) std::string();
119 return;
120 case Type::BINARY:
121 new (&binary_value_) BlobStorage();
122 return;
123 case Type::DICTIONARY:
124 new (&dict_) DictStorage();
125 return;
126 case Type::LIST:
127 new (&list_) ListStorage();
128 return;
129 }
130 }
131
Value(bool in_bool)132 Value::Value(bool in_bool) : type_(Type::BOOLEAN), bool_value_(in_bool) {}
133
Value(int in_int)134 Value::Value(int in_int) : type_(Type::INTEGER), int_value_(in_int) {}
135
Value(double in_double)136 Value::Value(double in_double) : type_(Type::DOUBLE), double_value_(in_double) {
137 if (!std::isfinite(double_value_)) {
138 NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) "
139 << "values cannot be represented in JSON";
140 double_value_ = 0.0;
141 }
142 }
143
Value(const char * in_string)144 Value::Value(const char* in_string) : Value(std::string(in_string)) {}
145
Value(StringPiece in_string)146 Value::Value(StringPiece in_string) : Value(std::string(in_string)) {}
147
Value(std::string && in_string)148 Value::Value(std::string&& in_string) noexcept
149 : type_(Type::STRING), string_value_(std::move(in_string)) {
150 DCHECK(IsStringUTF8(string_value_));
151 }
152
Value(const char16 * in_string16)153 Value::Value(const char16* in_string16) : Value(StringPiece16(in_string16)) {}
154
Value(StringPiece16 in_string16)155 Value::Value(StringPiece16 in_string16) : Value(UTF16ToUTF8(in_string16)) {}
156
Value(const BlobStorage & in_blob)157 Value::Value(const BlobStorage& in_blob)
158 : type_(Type::BINARY), binary_value_(in_blob) {}
159
Value(BlobStorage && in_blob)160 Value::Value(BlobStorage&& in_blob) noexcept
161 : type_(Type::BINARY), binary_value_(std::move(in_blob)) {}
162
Value(const DictStorage & in_dict)163 Value::Value(const DictStorage& in_dict) : type_(Type::DICTIONARY), dict_() {
164 dict_.reserve(in_dict.size());
165 for (const auto& it : in_dict) {
166 dict_.try_emplace(dict_.end(), it.first,
167 std::make_unique<Value>(it.second->Clone()));
168 }
169 }
170
Value(DictStorage && in_dict)171 Value::Value(DictStorage&& in_dict) noexcept
172 : type_(Type::DICTIONARY), dict_(std::move(in_dict)) {}
173
Value(const ListStorage & in_list)174 Value::Value(const ListStorage& in_list) : type_(Type::LIST), list_() {
175 list_.reserve(in_list.size());
176 for (const auto& val : in_list)
177 list_.emplace_back(val.Clone());
178 }
179
Value(ListStorage && in_list)180 Value::Value(ListStorage&& in_list) noexcept
181 : type_(Type::LIST), list_(std::move(in_list)) {}
182
operator =(Value && that)183 Value& Value::operator=(Value&& that) noexcept {
184 InternalCleanup();
185 InternalMoveConstructFrom(std::move(that));
186
187 return *this;
188 }
189
Clone() const190 Value Value::Clone() const {
191 switch (type_) {
192 case Type::NONE:
193 return Value();
194 case Type::BOOLEAN:
195 return Value(bool_value_);
196 case Type::INTEGER:
197 return Value(int_value_);
198 case Type::DOUBLE:
199 return Value(double_value_);
200 case Type::STRING:
201 return Value(string_value_);
202 case Type::BINARY:
203 return Value(binary_value_);
204 case Type::DICTIONARY:
205 return Value(dict_);
206 case Type::LIST:
207 return Value(list_);
208 }
209
210 NOTREACHED();
211 return Value();
212 }
213
~Value()214 Value::~Value() {
215 InternalCleanup();
216 }
217
218 // static
GetTypeName(Value::Type type)219 const char* Value::GetTypeName(Value::Type type) {
220 DCHECK_GE(static_cast<int>(type), 0);
221 DCHECK_LT(static_cast<size_t>(type), arraysize(kTypeNames));
222 return kTypeNames[static_cast<size_t>(type)];
223 }
224
GetBool() const225 bool Value::GetBool() const {
226 CHECK(is_bool());
227 return bool_value_;
228 }
229
GetInt() const230 int Value::GetInt() const {
231 CHECK(is_int());
232 return int_value_;
233 }
234
GetDouble() const235 double Value::GetDouble() const {
236 if (is_double())
237 return double_value_;
238 if (is_int())
239 return int_value_;
240 CHECK(false);
241 return 0.0;
242 }
243
GetString() const244 const std::string& Value::GetString() const {
245 CHECK(is_string());
246 return string_value_;
247 }
248
GetBlob() const249 const Value::BlobStorage& Value::GetBlob() const {
250 CHECK(is_blob());
251 return binary_value_;
252 }
253
GetList()254 Value::ListStorage& Value::GetList() {
255 CHECK(is_list());
256 return list_;
257 }
258
GetList() const259 const Value::ListStorage& Value::GetList() const {
260 CHECK(is_list());
261 return list_;
262 }
263
FindKey(StringPiece key)264 Value* Value::FindKey(StringPiece key) {
265 return const_cast<Value*>(static_cast<const Value*>(this)->FindKey(key));
266 }
267
FindKey(StringPiece key) const268 const Value* Value::FindKey(StringPiece key) const {
269 CHECK(is_dict());
270 auto found = dict_.find(key);
271 if (found == dict_.end())
272 return nullptr;
273 return found->second.get();
274 }
275
FindKeyOfType(StringPiece key,Type type)276 Value* Value::FindKeyOfType(StringPiece key, Type type) {
277 return const_cast<Value*>(
278 static_cast<const Value*>(this)->FindKeyOfType(key, type));
279 }
280
FindKeyOfType(StringPiece key,Type type) const281 const Value* Value::FindKeyOfType(StringPiece key, Type type) const {
282 const Value* result = FindKey(key);
283 if (!result || result->type() != type)
284 return nullptr;
285 return result;
286 }
287
RemoveKey(StringPiece key)288 bool Value::RemoveKey(StringPiece key) {
289 CHECK(is_dict());
290 // NOTE: Can't directly return dict_->erase(key) due to MSVC warning C4800.
291 return dict_.erase(key) != 0;
292 }
293
SetKey(StringPiece key,Value value)294 Value* Value::SetKey(StringPiece key, Value value) {
295 CHECK(is_dict());
296 // NOTE: We can't use |insert_or_assign| here, as only |try_emplace| does
297 // an explicit conversion from StringPiece to std::string if necessary.
298 auto val_ptr = std::make_unique<Value>(std::move(value));
299 auto result = dict_.try_emplace(key, std::move(val_ptr));
300 if (!result.second) {
301 // val_ptr is guaranteed to be still intact at this point.
302 result.first->second = std::move(val_ptr);
303 }
304 return result.first->second.get();
305 }
306
SetKey(std::string && key,Value value)307 Value* Value::SetKey(std::string&& key, Value value) {
308 CHECK(is_dict());
309 return dict_
310 .insert_or_assign(std::move(key),
311 std::make_unique<Value>(std::move(value)))
312 .first->second.get();
313 }
314
SetKey(const char * key,Value value)315 Value* Value::SetKey(const char* key, Value value) {
316 return SetKey(StringPiece(key), std::move(value));
317 }
318
FindPath(std::initializer_list<StringPiece> path)319 Value* Value::FindPath(std::initializer_list<StringPiece> path) {
320 return const_cast<Value*>(const_cast<const Value*>(this)->FindPath(path));
321 }
322
FindPath(span<const StringPiece> path)323 Value* Value::FindPath(span<const StringPiece> path) {
324 return const_cast<Value*>(const_cast<const Value*>(this)->FindPath(path));
325 }
326
FindPath(std::initializer_list<StringPiece> path) const327 const Value* Value::FindPath(std::initializer_list<StringPiece> path) const {
328 DCHECK_GE(path.size(), 2u) << "Use FindKey() for a path of length 1.";
329 return FindPath(make_span(path.begin(), path.size()));
330 }
331
FindPath(span<const StringPiece> path) const332 const Value* Value::FindPath(span<const StringPiece> path) const {
333 const Value* cur = this;
334 for (const StringPiece component : path) {
335 if (!cur->is_dict() || (cur = cur->FindKey(component)) == nullptr)
336 return nullptr;
337 }
338 return cur;
339 }
340
FindPathOfType(std::initializer_list<StringPiece> path,Type type)341 Value* Value::FindPathOfType(std::initializer_list<StringPiece> path,
342 Type type) {
343 return const_cast<Value*>(
344 const_cast<const Value*>(this)->FindPathOfType(path, type));
345 }
346
FindPathOfType(span<const StringPiece> path,Type type)347 Value* Value::FindPathOfType(span<const StringPiece> path, Type type) {
348 return const_cast<Value*>(
349 const_cast<const Value*>(this)->FindPathOfType(path, type));
350 }
351
FindPathOfType(std::initializer_list<StringPiece> path,Type type) const352 const Value* Value::FindPathOfType(std::initializer_list<StringPiece> path,
353 Type type) const {
354 DCHECK_GE(path.size(), 2u) << "Use FindKeyOfType() for a path of length 1.";
355 return FindPathOfType(make_span(path.begin(), path.size()), type);
356 }
357
FindPathOfType(span<const StringPiece> path,Type type) const358 const Value* Value::FindPathOfType(span<const StringPiece> path,
359 Type type) const {
360 const Value* result = FindPath(path);
361 if (!result || result->type() != type)
362 return nullptr;
363 return result;
364 }
365
SetPath(std::initializer_list<StringPiece> path,Value value)366 Value* Value::SetPath(std::initializer_list<StringPiece> path, Value value) {
367 DCHECK_GE(path.size(), 2u) << "Use SetKey() for a path of length 1.";
368 return SetPath(make_span(path.begin(), path.size()), std::move(value));
369 }
370
SetPath(span<const StringPiece> path,Value value)371 Value* Value::SetPath(span<const StringPiece> path, Value value) {
372 DCHECK_NE(path.begin(), path.end()); // Can't be empty path.
373
374 // Walk/construct intermediate dictionaries. The last element requires
375 // special handling so skip it in this loop.
376 Value* cur = this;
377 const StringPiece* cur_path = path.begin();
378 for (; (cur_path + 1) < path.end(); ++cur_path) {
379 if (!cur->is_dict())
380 return nullptr;
381
382 // Use lower_bound to avoid doing the search twice for missing keys.
383 const StringPiece path_component = *cur_path;
384 auto found = cur->dict_.lower_bound(path_component);
385 if (found == cur->dict_.end() || found->first != path_component) {
386 // No key found, insert one.
387 auto inserted = cur->dict_.try_emplace(
388 found, path_component, std::make_unique<Value>(Type::DICTIONARY));
389 cur = inserted->second.get();
390 } else {
391 cur = found->second.get();
392 }
393 }
394
395 // "cur" will now contain the last dictionary to insert or replace into.
396 if (!cur->is_dict())
397 return nullptr;
398 return cur->SetKey(*cur_path, std::move(value));
399 }
400
RemovePath(std::initializer_list<StringPiece> path)401 bool Value::RemovePath(std::initializer_list<StringPiece> path) {
402 DCHECK_GE(path.size(), 2u) << "Use RemoveKey() for a path of length 1.";
403 return RemovePath(make_span(path.begin(), path.size()));
404 }
405
RemovePath(span<const StringPiece> path)406 bool Value::RemovePath(span<const StringPiece> path) {
407 if (!is_dict() || path.empty())
408 return false;
409
410 if (path.size() == 1)
411 return RemoveKey(path[0]);
412
413 auto found = dict_.find(path[0]);
414 if (found == dict_.end() || !found->second->is_dict())
415 return false;
416
417 bool removed = found->second->RemovePath(path.subspan(1));
418 if (removed && found->second->dict_.empty())
419 dict_.erase(found);
420
421 return removed;
422 }
423
DictItems()424 Value::dict_iterator_proxy Value::DictItems() {
425 CHECK(is_dict());
426 return dict_iterator_proxy(&dict_);
427 }
428
DictItems() const429 Value::const_dict_iterator_proxy Value::DictItems() const {
430 CHECK(is_dict());
431 return const_dict_iterator_proxy(&dict_);
432 }
433
DictSize() const434 size_t Value::DictSize() const {
435 CHECK(is_dict());
436 return dict_.size();
437 }
438
DictEmpty() const439 bool Value::DictEmpty() const {
440 CHECK(is_dict());
441 return dict_.empty();
442 }
443
GetAsBoolean(bool * out_value) const444 bool Value::GetAsBoolean(bool* out_value) const {
445 if (out_value && is_bool()) {
446 *out_value = bool_value_;
447 return true;
448 }
449 return is_bool();
450 }
451
GetAsInteger(int * out_value) const452 bool Value::GetAsInteger(int* out_value) const {
453 if (out_value && is_int()) {
454 *out_value = int_value_;
455 return true;
456 }
457 return is_int();
458 }
459
GetAsDouble(double * out_value) const460 bool Value::GetAsDouble(double* out_value) const {
461 if (out_value && is_double()) {
462 *out_value = double_value_;
463 return true;
464 } else if (out_value && is_int()) {
465 // Allow promotion from int to double.
466 *out_value = int_value_;
467 return true;
468 }
469 return is_double() || is_int();
470 }
471
GetAsString(std::string * out_value) const472 bool Value::GetAsString(std::string* out_value) const {
473 if (out_value && is_string()) {
474 *out_value = string_value_;
475 return true;
476 }
477 return is_string();
478 }
479
GetAsString(string16 * out_value) const480 bool Value::GetAsString(string16* out_value) const {
481 if (out_value && is_string()) {
482 *out_value = UTF8ToUTF16(string_value_);
483 return true;
484 }
485 return is_string();
486 }
487
GetAsString(const Value ** out_value) const488 bool Value::GetAsString(const Value** out_value) const {
489 if (out_value && is_string()) {
490 *out_value = static_cast<const Value*>(this);
491 return true;
492 }
493 return is_string();
494 }
495
GetAsString(StringPiece * out_value) const496 bool Value::GetAsString(StringPiece* out_value) const {
497 if (out_value && is_string()) {
498 *out_value = string_value_;
499 return true;
500 }
501 return is_string();
502 }
503
GetAsList(ListValue ** out_value)504 bool Value::GetAsList(ListValue** out_value) {
505 if (out_value && is_list()) {
506 *out_value = static_cast<ListValue*>(this);
507 return true;
508 }
509 return is_list();
510 }
511
GetAsList(const ListValue ** out_value) const512 bool Value::GetAsList(const ListValue** out_value) const {
513 if (out_value && is_list()) {
514 *out_value = static_cast<const ListValue*>(this);
515 return true;
516 }
517 return is_list();
518 }
519
GetAsDictionary(DictionaryValue ** out_value)520 bool Value::GetAsDictionary(DictionaryValue** out_value) {
521 if (out_value && is_dict()) {
522 *out_value = static_cast<DictionaryValue*>(this);
523 return true;
524 }
525 return is_dict();
526 }
527
GetAsDictionary(const DictionaryValue ** out_value) const528 bool Value::GetAsDictionary(const DictionaryValue** out_value) const {
529 if (out_value && is_dict()) {
530 *out_value = static_cast<const DictionaryValue*>(this);
531 return true;
532 }
533 return is_dict();
534 }
535
DeepCopy() const536 Value* Value::DeepCopy() const {
537 return new Value(Clone());
538 }
539
CreateDeepCopy() const540 std::unique_ptr<Value> Value::CreateDeepCopy() const {
541 return std::make_unique<Value>(Clone());
542 }
543
operator ==(const Value & lhs,const Value & rhs)544 bool operator==(const Value& lhs, const Value& rhs) {
545 if (lhs.type_ != rhs.type_)
546 return false;
547
548 switch (lhs.type_) {
549 case Value::Type::NONE:
550 return true;
551 case Value::Type::BOOLEAN:
552 return lhs.bool_value_ == rhs.bool_value_;
553 case Value::Type::INTEGER:
554 return lhs.int_value_ == rhs.int_value_;
555 case Value::Type::DOUBLE:
556 return lhs.double_value_ == rhs.double_value_;
557 case Value::Type::STRING:
558 return lhs.string_value_ == rhs.string_value_;
559 case Value::Type::BINARY:
560 return lhs.binary_value_ == rhs.binary_value_;
561 // TODO(crbug.com/646113): Clean this up when DictionaryValue and ListValue
562 // are completely inlined.
563 case Value::Type::DICTIONARY:
564 if (lhs.dict_.size() != rhs.dict_.size())
565 return false;
566 return std::equal(std::begin(lhs.dict_), std::end(lhs.dict_),
567 std::begin(rhs.dict_),
568 [](const auto& u, const auto& v) {
569 return std::tie(u.first, *u.second) ==
570 std::tie(v.first, *v.second);
571 });
572 case Value::Type::LIST:
573 return lhs.list_ == rhs.list_;
574 }
575
576 NOTREACHED();
577 return false;
578 }
579
operator !=(const Value & lhs,const Value & rhs)580 bool operator!=(const Value& lhs, const Value& rhs) {
581 return !(lhs == rhs);
582 }
583
operator <(const Value & lhs,const Value & rhs)584 bool operator<(const Value& lhs, const Value& rhs) {
585 if (lhs.type_ != rhs.type_)
586 return lhs.type_ < rhs.type_;
587
588 switch (lhs.type_) {
589 case Value::Type::NONE:
590 return false;
591 case Value::Type::BOOLEAN:
592 return lhs.bool_value_ < rhs.bool_value_;
593 case Value::Type::INTEGER:
594 return lhs.int_value_ < rhs.int_value_;
595 case Value::Type::DOUBLE:
596 return lhs.double_value_ < rhs.double_value_;
597 case Value::Type::STRING:
598 return lhs.string_value_ < rhs.string_value_;
599 case Value::Type::BINARY:
600 return lhs.binary_value_ < rhs.binary_value_;
601 // TODO(crbug.com/646113): Clean this up when DictionaryValue and ListValue
602 // are completely inlined.
603 case Value::Type::DICTIONARY:
604 return std::lexicographical_compare(
605 std::begin(lhs.dict_), std::end(lhs.dict_), std::begin(rhs.dict_),
606 std::end(rhs.dict_),
607 [](const Value::DictStorage::value_type& u,
608 const Value::DictStorage::value_type& v) {
609 return std::tie(u.first, *u.second) < std::tie(v.first, *v.second);
610 });
611 case Value::Type::LIST:
612 return lhs.list_ < rhs.list_;
613 }
614
615 NOTREACHED();
616 return false;
617 }
618
operator >(const Value & lhs,const Value & rhs)619 bool operator>(const Value& lhs, const Value& rhs) {
620 return rhs < lhs;
621 }
622
operator <=(const Value & lhs,const Value & rhs)623 bool operator<=(const Value& lhs, const Value& rhs) {
624 return !(rhs < lhs);
625 }
626
operator >=(const Value & lhs,const Value & rhs)627 bool operator>=(const Value& lhs, const Value& rhs) {
628 return !(lhs < rhs);
629 }
630
Equals(const Value * other) const631 bool Value::Equals(const Value* other) const {
632 DCHECK(other);
633 return *this == *other;
634 }
635
636 // Unsupported in libchrome
637 // size_t Value::EstimateMemoryUsage() const {
638 // switch (type_) {
639 // case Type::STRING:
640 // return base::trace_event::EstimateMemoryUsage(string_value_);
641 // case Type::BINARY:
642 // return base::trace_event::EstimateMemoryUsage(binary_value_);
643 // case Type::DICTIONARY:
644 // return base::trace_event::EstimateMemoryUsage(dict_);
645 // case Type::LIST:
646 // return base::trace_event::EstimateMemoryUsage(list_);
647 // default:
648 // return 0;
649 // }
650 // }
651
InternalMoveConstructFrom(Value && that)652 void Value::InternalMoveConstructFrom(Value&& that) {
653 type_ = that.type_;
654
655 switch (type_) {
656 case Type::NONE:
657 return;
658 case Type::BOOLEAN:
659 bool_value_ = that.bool_value_;
660 return;
661 case Type::INTEGER:
662 int_value_ = that.int_value_;
663 return;
664 case Type::DOUBLE:
665 double_value_ = that.double_value_;
666 return;
667 case Type::STRING:
668 new (&string_value_) std::string(std::move(that.string_value_));
669 return;
670 case Type::BINARY:
671 new (&binary_value_) BlobStorage(std::move(that.binary_value_));
672 return;
673 case Type::DICTIONARY:
674 new (&dict_) DictStorage(std::move(that.dict_));
675 return;
676 case Type::LIST:
677 new (&list_) ListStorage(std::move(that.list_));
678 return;
679 }
680 }
681
InternalCleanup()682 void Value::InternalCleanup() {
683 switch (type_) {
684 case Type::NONE:
685 case Type::BOOLEAN:
686 case Type::INTEGER:
687 case Type::DOUBLE:
688 // Nothing to do
689 return;
690
691 case Type::STRING:
692 string_value_.~basic_string();
693 return;
694 case Type::BINARY:
695 binary_value_.~BlobStorage();
696 return;
697 case Type::DICTIONARY:
698 dict_.~DictStorage();
699 return;
700 case Type::LIST:
701 list_.~ListStorage();
702 return;
703 }
704 }
705
706 ///////////////////// DictionaryValue ////////////////////
707
708 // static
From(std::unique_ptr<Value> value)709 std::unique_ptr<DictionaryValue> DictionaryValue::From(
710 std::unique_ptr<Value> value) {
711 DictionaryValue* out;
712 if (value && value->GetAsDictionary(&out)) {
713 ignore_result(value.release());
714 return WrapUnique(out);
715 }
716 return nullptr;
717 }
718
DictionaryValue()719 DictionaryValue::DictionaryValue() : Value(Type::DICTIONARY) {}
DictionaryValue(const DictStorage & in_dict)720 DictionaryValue::DictionaryValue(const DictStorage& in_dict) : Value(in_dict) {}
DictionaryValue(DictStorage && in_dict)721 DictionaryValue::DictionaryValue(DictStorage&& in_dict) noexcept
722 : Value(std::move(in_dict)) {}
723
HasKey(StringPiece key) const724 bool DictionaryValue::HasKey(StringPiece key) const {
725 DCHECK(IsStringUTF8(key));
726 auto current_entry = dict_.find(key);
727 DCHECK((current_entry == dict_.end()) || current_entry->second);
728 return current_entry != dict_.end();
729 }
730
Clear()731 void DictionaryValue::Clear() {
732 dict_.clear();
733 }
734
Set(StringPiece path,std::unique_ptr<Value> in_value)735 Value* DictionaryValue::Set(StringPiece path, std::unique_ptr<Value> in_value) {
736 DCHECK(IsStringUTF8(path));
737 DCHECK(in_value);
738
739 StringPiece current_path(path);
740 Value* current_dictionary = this;
741 for (size_t delimiter_position = current_path.find('.');
742 delimiter_position != StringPiece::npos;
743 delimiter_position = current_path.find('.')) {
744 // Assume that we're indexing into a dictionary.
745 StringPiece key = current_path.substr(0, delimiter_position);
746 Value* child_dictionary =
747 current_dictionary->FindKeyOfType(key, Type::DICTIONARY);
748 if (!child_dictionary) {
749 child_dictionary =
750 current_dictionary->SetKey(key, Value(Type::DICTIONARY));
751 }
752
753 current_dictionary = child_dictionary;
754 current_path = current_path.substr(delimiter_position + 1);
755 }
756
757 return static_cast<DictionaryValue*>(current_dictionary)
758 ->SetWithoutPathExpansion(current_path, std::move(in_value));
759 }
760
SetBoolean(StringPiece path,bool in_value)761 Value* DictionaryValue::SetBoolean(StringPiece path, bool in_value) {
762 return Set(path, std::make_unique<Value>(in_value));
763 }
764
SetInteger(StringPiece path,int in_value)765 Value* DictionaryValue::SetInteger(StringPiece path, int in_value) {
766 return Set(path, std::make_unique<Value>(in_value));
767 }
768
SetDouble(StringPiece path,double in_value)769 Value* DictionaryValue::SetDouble(StringPiece path, double in_value) {
770 return Set(path, std::make_unique<Value>(in_value));
771 }
772
SetString(StringPiece path,StringPiece in_value)773 Value* DictionaryValue::SetString(StringPiece path, StringPiece in_value) {
774 return Set(path, std::make_unique<Value>(in_value));
775 }
776
SetString(StringPiece path,const string16 & in_value)777 Value* DictionaryValue::SetString(StringPiece path, const string16& in_value) {
778 return Set(path, std::make_unique<Value>(in_value));
779 }
780
SetDictionary(StringPiece path,std::unique_ptr<DictionaryValue> in_value)781 DictionaryValue* DictionaryValue::SetDictionary(
782 StringPiece path,
783 std::unique_ptr<DictionaryValue> in_value) {
784 return static_cast<DictionaryValue*>(Set(path, std::move(in_value)));
785 }
786
SetList(StringPiece path,std::unique_ptr<ListValue> in_value)787 ListValue* DictionaryValue::SetList(StringPiece path,
788 std::unique_ptr<ListValue> in_value) {
789 return static_cast<ListValue*>(Set(path, std::move(in_value)));
790 }
791
SetWithoutPathExpansion(StringPiece key,std::unique_ptr<Value> in_value)792 Value* DictionaryValue::SetWithoutPathExpansion(
793 StringPiece key,
794 std::unique_ptr<Value> in_value) {
795 // NOTE: We can't use |insert_or_assign| here, as only |try_emplace| does
796 // an explicit conversion from StringPiece to std::string if necessary.
797 auto result = dict_.try_emplace(key, std::move(in_value));
798 if (!result.second) {
799 // in_value is guaranteed to be still intact at this point.
800 result.first->second = std::move(in_value);
801 }
802 return result.first->second.get();
803 }
804
Get(StringPiece path,const Value ** out_value) const805 bool DictionaryValue::Get(StringPiece path,
806 const Value** out_value) const {
807 DCHECK(IsStringUTF8(path));
808 StringPiece current_path(path);
809 const DictionaryValue* current_dictionary = this;
810 for (size_t delimiter_position = current_path.find('.');
811 delimiter_position != std::string::npos;
812 delimiter_position = current_path.find('.')) {
813 const DictionaryValue* child_dictionary = nullptr;
814 if (!current_dictionary->GetDictionaryWithoutPathExpansion(
815 current_path.substr(0, delimiter_position), &child_dictionary)) {
816 return false;
817 }
818
819 current_dictionary = child_dictionary;
820 current_path = current_path.substr(delimiter_position + 1);
821 }
822
823 return current_dictionary->GetWithoutPathExpansion(current_path, out_value);
824 }
825
Get(StringPiece path,Value ** out_value)826 bool DictionaryValue::Get(StringPiece path, Value** out_value) {
827 return static_cast<const DictionaryValue&>(*this).Get(
828 path,
829 const_cast<const Value**>(out_value));
830 }
831
GetBoolean(StringPiece path,bool * bool_value) const832 bool DictionaryValue::GetBoolean(StringPiece path, bool* bool_value) const {
833 const Value* value;
834 if (!Get(path, &value))
835 return false;
836
837 return value->GetAsBoolean(bool_value);
838 }
839
GetInteger(StringPiece path,int * out_value) const840 bool DictionaryValue::GetInteger(StringPiece path, int* out_value) const {
841 const Value* value;
842 if (!Get(path, &value))
843 return false;
844
845 return value->GetAsInteger(out_value);
846 }
847
GetDouble(StringPiece path,double * out_value) const848 bool DictionaryValue::GetDouble(StringPiece path, double* out_value) const {
849 const Value* value;
850 if (!Get(path, &value))
851 return false;
852
853 return value->GetAsDouble(out_value);
854 }
855
GetString(StringPiece path,std::string * out_value) const856 bool DictionaryValue::GetString(StringPiece path,
857 std::string* out_value) const {
858 const Value* value;
859 if (!Get(path, &value))
860 return false;
861
862 return value->GetAsString(out_value);
863 }
864
GetString(StringPiece path,string16 * out_value) const865 bool DictionaryValue::GetString(StringPiece path, string16* out_value) const {
866 const Value* value;
867 if (!Get(path, &value))
868 return false;
869
870 return value->GetAsString(out_value);
871 }
872
GetStringASCII(StringPiece path,std::string * out_value) const873 bool DictionaryValue::GetStringASCII(StringPiece path,
874 std::string* out_value) const {
875 std::string out;
876 if (!GetString(path, &out))
877 return false;
878
879 if (!IsStringASCII(out)) {
880 NOTREACHED();
881 return false;
882 }
883
884 out_value->assign(out);
885 return true;
886 }
887
GetBinary(StringPiece path,const Value ** out_value) const888 bool DictionaryValue::GetBinary(StringPiece path,
889 const Value** out_value) const {
890 const Value* value;
891 bool result = Get(path, &value);
892 if (!result || !value->is_blob())
893 return false;
894
895 if (out_value)
896 *out_value = value;
897
898 return true;
899 }
900
GetBinary(StringPiece path,Value ** out_value)901 bool DictionaryValue::GetBinary(StringPiece path, Value** out_value) {
902 return static_cast<const DictionaryValue&>(*this).GetBinary(
903 path, const_cast<const Value**>(out_value));
904 }
905
GetDictionary(StringPiece path,const DictionaryValue ** out_value) const906 bool DictionaryValue::GetDictionary(StringPiece path,
907 const DictionaryValue** out_value) const {
908 const Value* value;
909 bool result = Get(path, &value);
910 if (!result || !value->is_dict())
911 return false;
912
913 if (out_value)
914 *out_value = static_cast<const DictionaryValue*>(value);
915
916 return true;
917 }
918
GetDictionary(StringPiece path,DictionaryValue ** out_value)919 bool DictionaryValue::GetDictionary(StringPiece path,
920 DictionaryValue** out_value) {
921 return static_cast<const DictionaryValue&>(*this).GetDictionary(
922 path,
923 const_cast<const DictionaryValue**>(out_value));
924 }
925
GetList(StringPiece path,const ListValue ** out_value) const926 bool DictionaryValue::GetList(StringPiece path,
927 const ListValue** out_value) const {
928 const Value* value;
929 bool result = Get(path, &value);
930 if (!result || !value->is_list())
931 return false;
932
933 if (out_value)
934 *out_value = static_cast<const ListValue*>(value);
935
936 return true;
937 }
938
GetList(StringPiece path,ListValue ** out_value)939 bool DictionaryValue::GetList(StringPiece path, ListValue** out_value) {
940 return static_cast<const DictionaryValue&>(*this).GetList(
941 path,
942 const_cast<const ListValue**>(out_value));
943 }
944
GetWithoutPathExpansion(StringPiece key,const Value ** out_value) const945 bool DictionaryValue::GetWithoutPathExpansion(StringPiece key,
946 const Value** out_value) const {
947 DCHECK(IsStringUTF8(key));
948 auto entry_iterator = dict_.find(key);
949 if (entry_iterator == dict_.end())
950 return false;
951
952 if (out_value)
953 *out_value = entry_iterator->second.get();
954 return true;
955 }
956
GetWithoutPathExpansion(StringPiece key,Value ** out_value)957 bool DictionaryValue::GetWithoutPathExpansion(StringPiece key,
958 Value** out_value) {
959 return static_cast<const DictionaryValue&>(*this).GetWithoutPathExpansion(
960 key,
961 const_cast<const Value**>(out_value));
962 }
963
GetBooleanWithoutPathExpansion(StringPiece key,bool * out_value) const964 bool DictionaryValue::GetBooleanWithoutPathExpansion(StringPiece key,
965 bool* out_value) const {
966 const Value* value;
967 if (!GetWithoutPathExpansion(key, &value))
968 return false;
969
970 return value->GetAsBoolean(out_value);
971 }
972
GetIntegerWithoutPathExpansion(StringPiece key,int * out_value) const973 bool DictionaryValue::GetIntegerWithoutPathExpansion(StringPiece key,
974 int* out_value) const {
975 const Value* value;
976 if (!GetWithoutPathExpansion(key, &value))
977 return false;
978
979 return value->GetAsInteger(out_value);
980 }
981
GetDoubleWithoutPathExpansion(StringPiece key,double * out_value) const982 bool DictionaryValue::GetDoubleWithoutPathExpansion(StringPiece key,
983 double* out_value) const {
984 const Value* value;
985 if (!GetWithoutPathExpansion(key, &value))
986 return false;
987
988 return value->GetAsDouble(out_value);
989 }
990
GetStringWithoutPathExpansion(StringPiece key,std::string * out_value) const991 bool DictionaryValue::GetStringWithoutPathExpansion(
992 StringPiece key,
993 std::string* out_value) const {
994 const Value* value;
995 if (!GetWithoutPathExpansion(key, &value))
996 return false;
997
998 return value->GetAsString(out_value);
999 }
1000
GetStringWithoutPathExpansion(StringPiece key,string16 * out_value) const1001 bool DictionaryValue::GetStringWithoutPathExpansion(StringPiece key,
1002 string16* out_value) const {
1003 const Value* value;
1004 if (!GetWithoutPathExpansion(key, &value))
1005 return false;
1006
1007 return value->GetAsString(out_value);
1008 }
1009
GetDictionaryWithoutPathExpansion(StringPiece key,const DictionaryValue ** out_value) const1010 bool DictionaryValue::GetDictionaryWithoutPathExpansion(
1011 StringPiece key,
1012 const DictionaryValue** out_value) const {
1013 const Value* value;
1014 bool result = GetWithoutPathExpansion(key, &value);
1015 if (!result || !value->is_dict())
1016 return false;
1017
1018 if (out_value)
1019 *out_value = static_cast<const DictionaryValue*>(value);
1020
1021 return true;
1022 }
1023
GetDictionaryWithoutPathExpansion(StringPiece key,DictionaryValue ** out_value)1024 bool DictionaryValue::GetDictionaryWithoutPathExpansion(
1025 StringPiece key,
1026 DictionaryValue** out_value) {
1027 const DictionaryValue& const_this =
1028 static_cast<const DictionaryValue&>(*this);
1029 return const_this.GetDictionaryWithoutPathExpansion(
1030 key,
1031 const_cast<const DictionaryValue**>(out_value));
1032 }
1033
GetListWithoutPathExpansion(StringPiece key,const ListValue ** out_value) const1034 bool DictionaryValue::GetListWithoutPathExpansion(
1035 StringPiece key,
1036 const ListValue** out_value) const {
1037 const Value* value;
1038 bool result = GetWithoutPathExpansion(key, &value);
1039 if (!result || !value->is_list())
1040 return false;
1041
1042 if (out_value)
1043 *out_value = static_cast<const ListValue*>(value);
1044
1045 return true;
1046 }
1047
GetListWithoutPathExpansion(StringPiece key,ListValue ** out_value)1048 bool DictionaryValue::GetListWithoutPathExpansion(StringPiece key,
1049 ListValue** out_value) {
1050 return
1051 static_cast<const DictionaryValue&>(*this).GetListWithoutPathExpansion(
1052 key,
1053 const_cast<const ListValue**>(out_value));
1054 }
1055
Remove(StringPiece path,std::unique_ptr<Value> * out_value)1056 bool DictionaryValue::Remove(StringPiece path,
1057 std::unique_ptr<Value>* out_value) {
1058 DCHECK(IsStringUTF8(path));
1059 StringPiece current_path(path);
1060 DictionaryValue* current_dictionary = this;
1061 size_t delimiter_position = current_path.rfind('.');
1062 if (delimiter_position != StringPiece::npos) {
1063 if (!GetDictionary(current_path.substr(0, delimiter_position),
1064 ¤t_dictionary))
1065 return false;
1066 current_path = current_path.substr(delimiter_position + 1);
1067 }
1068
1069 return current_dictionary->RemoveWithoutPathExpansion(current_path,
1070 out_value);
1071 }
1072
RemoveWithoutPathExpansion(StringPiece key,std::unique_ptr<Value> * out_value)1073 bool DictionaryValue::RemoveWithoutPathExpansion(
1074 StringPiece key,
1075 std::unique_ptr<Value>* out_value) {
1076 DCHECK(IsStringUTF8(key));
1077 auto entry_iterator = dict_.find(key);
1078 if (entry_iterator == dict_.end())
1079 return false;
1080
1081 if (out_value)
1082 *out_value = std::move(entry_iterator->second);
1083 dict_.erase(entry_iterator);
1084 return true;
1085 }
1086
RemovePath(StringPiece path,std::unique_ptr<Value> * out_value)1087 bool DictionaryValue::RemovePath(StringPiece path,
1088 std::unique_ptr<Value>* out_value) {
1089 bool result = false;
1090 size_t delimiter_position = path.find('.');
1091
1092 if (delimiter_position == std::string::npos)
1093 return RemoveWithoutPathExpansion(path, out_value);
1094
1095 StringPiece subdict_path = path.substr(0, delimiter_position);
1096 DictionaryValue* subdict = nullptr;
1097 if (!GetDictionary(subdict_path, &subdict))
1098 return false;
1099 result = subdict->RemovePath(path.substr(delimiter_position + 1),
1100 out_value);
1101 if (result && subdict->empty())
1102 RemoveWithoutPathExpansion(subdict_path, nullptr);
1103
1104 return result;
1105 }
1106
DeepCopyWithoutEmptyChildren() const1107 std::unique_ptr<DictionaryValue> DictionaryValue::DeepCopyWithoutEmptyChildren()
1108 const {
1109 std::unique_ptr<DictionaryValue> copy =
1110 CopyDictionaryWithoutEmptyChildren(*this);
1111 if (!copy)
1112 copy = std::make_unique<DictionaryValue>();
1113 return copy;
1114 }
1115
MergeDictionary(const DictionaryValue * dictionary)1116 void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) {
1117 CHECK(dictionary->is_dict());
1118 for (DictionaryValue::Iterator it(*dictionary); !it.IsAtEnd(); it.Advance()) {
1119 const Value* merge_value = &it.value();
1120 // Check whether we have to merge dictionaries.
1121 if (merge_value->is_dict()) {
1122 DictionaryValue* sub_dict;
1123 if (GetDictionaryWithoutPathExpansion(it.key(), &sub_dict)) {
1124 sub_dict->MergeDictionary(
1125 static_cast<const DictionaryValue*>(merge_value));
1126 continue;
1127 }
1128 }
1129 // All other cases: Make a copy and hook it up.
1130 SetKey(it.key(), merge_value->Clone());
1131 }
1132 }
1133
Swap(DictionaryValue * other)1134 void DictionaryValue::Swap(DictionaryValue* other) {
1135 CHECK(other->is_dict());
1136 dict_.swap(other->dict_);
1137 }
1138
Iterator(const DictionaryValue & target)1139 DictionaryValue::Iterator::Iterator(const DictionaryValue& target)
1140 : target_(target), it_(target.dict_.begin()) {}
1141
1142 DictionaryValue::Iterator::Iterator(const Iterator& other) = default;
1143
1144 DictionaryValue::Iterator::~Iterator() = default;
1145
DeepCopy() const1146 DictionaryValue* DictionaryValue::DeepCopy() const {
1147 return new DictionaryValue(dict_);
1148 }
1149
CreateDeepCopy() const1150 std::unique_ptr<DictionaryValue> DictionaryValue::CreateDeepCopy() const {
1151 return std::make_unique<DictionaryValue>(dict_);
1152 }
1153
1154 ///////////////////// ListValue ////////////////////
1155
1156 // static
From(std::unique_ptr<Value> value)1157 std::unique_ptr<ListValue> ListValue::From(std::unique_ptr<Value> value) {
1158 ListValue* out;
1159 if (value && value->GetAsList(&out)) {
1160 ignore_result(value.release());
1161 return WrapUnique(out);
1162 }
1163 return nullptr;
1164 }
1165
ListValue()1166 ListValue::ListValue() : Value(Type::LIST) {}
ListValue(const ListStorage & in_list)1167 ListValue::ListValue(const ListStorage& in_list) : Value(in_list) {}
ListValue(ListStorage && in_list)1168 ListValue::ListValue(ListStorage&& in_list) noexcept
1169 : Value(std::move(in_list)) {}
1170
Clear()1171 void ListValue::Clear() {
1172 list_.clear();
1173 }
1174
Reserve(size_t n)1175 void ListValue::Reserve(size_t n) {
1176 list_.reserve(n);
1177 }
1178
Set(size_t index,std::unique_ptr<Value> in_value)1179 bool ListValue::Set(size_t index, std::unique_ptr<Value> in_value) {
1180 if (!in_value)
1181 return false;
1182
1183 if (index >= list_.size())
1184 list_.resize(index + 1);
1185
1186 list_[index] = std::move(*in_value);
1187 return true;
1188 }
1189
Get(size_t index,const Value ** out_value) const1190 bool ListValue::Get(size_t index, const Value** out_value) const {
1191 if (index >= list_.size())
1192 return false;
1193
1194 if (out_value)
1195 *out_value = &list_[index];
1196
1197 return true;
1198 }
1199
Get(size_t index,Value ** out_value)1200 bool ListValue::Get(size_t index, Value** out_value) {
1201 return static_cast<const ListValue&>(*this).Get(
1202 index,
1203 const_cast<const Value**>(out_value));
1204 }
1205
GetBoolean(size_t index,bool * bool_value) const1206 bool ListValue::GetBoolean(size_t index, bool* bool_value) const {
1207 const Value* value;
1208 if (!Get(index, &value))
1209 return false;
1210
1211 return value->GetAsBoolean(bool_value);
1212 }
1213
GetInteger(size_t index,int * out_value) const1214 bool ListValue::GetInteger(size_t index, int* out_value) const {
1215 const Value* value;
1216 if (!Get(index, &value))
1217 return false;
1218
1219 return value->GetAsInteger(out_value);
1220 }
1221
GetDouble(size_t index,double * out_value) const1222 bool ListValue::GetDouble(size_t index, double* out_value) const {
1223 const Value* value;
1224 if (!Get(index, &value))
1225 return false;
1226
1227 return value->GetAsDouble(out_value);
1228 }
1229
GetString(size_t index,std::string * out_value) const1230 bool ListValue::GetString(size_t index, std::string* out_value) const {
1231 const Value* value;
1232 if (!Get(index, &value))
1233 return false;
1234
1235 return value->GetAsString(out_value);
1236 }
1237
GetString(size_t index,string16 * out_value) const1238 bool ListValue::GetString(size_t index, string16* out_value) const {
1239 const Value* value;
1240 if (!Get(index, &value))
1241 return false;
1242
1243 return value->GetAsString(out_value);
1244 }
1245
GetDictionary(size_t index,const DictionaryValue ** out_value) const1246 bool ListValue::GetDictionary(size_t index,
1247 const DictionaryValue** out_value) const {
1248 const Value* value;
1249 bool result = Get(index, &value);
1250 if (!result || !value->is_dict())
1251 return false;
1252
1253 if (out_value)
1254 *out_value = static_cast<const DictionaryValue*>(value);
1255
1256 return true;
1257 }
1258
GetDictionary(size_t index,DictionaryValue ** out_value)1259 bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) {
1260 return static_cast<const ListValue&>(*this).GetDictionary(
1261 index,
1262 const_cast<const DictionaryValue**>(out_value));
1263 }
1264
GetList(size_t index,const ListValue ** out_value) const1265 bool ListValue::GetList(size_t index, const ListValue** out_value) const {
1266 const Value* value;
1267 bool result = Get(index, &value);
1268 if (!result || !value->is_list())
1269 return false;
1270
1271 if (out_value)
1272 *out_value = static_cast<const ListValue*>(value);
1273
1274 return true;
1275 }
1276
GetList(size_t index,ListValue ** out_value)1277 bool ListValue::GetList(size_t index, ListValue** out_value) {
1278 return static_cast<const ListValue&>(*this).GetList(
1279 index,
1280 const_cast<const ListValue**>(out_value));
1281 }
1282
Remove(size_t index,std::unique_ptr<Value> * out_value)1283 bool ListValue::Remove(size_t index, std::unique_ptr<Value>* out_value) {
1284 if (index >= list_.size())
1285 return false;
1286
1287 if (out_value)
1288 *out_value = std::make_unique<Value>(std::move(list_[index]));
1289
1290 list_.erase(list_.begin() + index);
1291 return true;
1292 }
1293
Remove(const Value & value,size_t * index)1294 bool ListValue::Remove(const Value& value, size_t* index) {
1295 auto it = std::find(list_.begin(), list_.end(), value);
1296
1297 if (it == list_.end())
1298 return false;
1299
1300 if (index)
1301 *index = std::distance(list_.begin(), it);
1302
1303 list_.erase(it);
1304 return true;
1305 }
1306
Erase(iterator iter,std::unique_ptr<Value> * out_value)1307 ListValue::iterator ListValue::Erase(iterator iter,
1308 std::unique_ptr<Value>* out_value) {
1309 if (out_value)
1310 *out_value = std::make_unique<Value>(std::move(*iter));
1311
1312 return list_.erase(iter);
1313 }
1314
Append(std::unique_ptr<Value> in_value)1315 void ListValue::Append(std::unique_ptr<Value> in_value) {
1316 list_.push_back(std::move(*in_value));
1317 }
1318
AppendBoolean(bool in_value)1319 void ListValue::AppendBoolean(bool in_value) {
1320 list_.emplace_back(in_value);
1321 }
1322
AppendInteger(int in_value)1323 void ListValue::AppendInteger(int in_value) {
1324 list_.emplace_back(in_value);
1325 }
1326
AppendDouble(double in_value)1327 void ListValue::AppendDouble(double in_value) {
1328 list_.emplace_back(in_value);
1329 }
1330
AppendString(StringPiece in_value)1331 void ListValue::AppendString(StringPiece in_value) {
1332 list_.emplace_back(in_value);
1333 }
1334
AppendString(const string16 & in_value)1335 void ListValue::AppendString(const string16& in_value) {
1336 list_.emplace_back(in_value);
1337 }
1338
AppendStrings(const std::vector<std::string> & in_values)1339 void ListValue::AppendStrings(const std::vector<std::string>& in_values) {
1340 list_.reserve(list_.size() + in_values.size());
1341 for (const auto& in_value : in_values)
1342 list_.emplace_back(in_value);
1343 }
1344
AppendStrings(const std::vector<string16> & in_values)1345 void ListValue::AppendStrings(const std::vector<string16>& in_values) {
1346 list_.reserve(list_.size() + in_values.size());
1347 for (const auto& in_value : in_values)
1348 list_.emplace_back(in_value);
1349 }
1350
AppendIfNotPresent(std::unique_ptr<Value> in_value)1351 bool ListValue::AppendIfNotPresent(std::unique_ptr<Value> in_value) {
1352 DCHECK(in_value);
1353 if (ContainsValue(list_, *in_value))
1354 return false;
1355
1356 list_.push_back(std::move(*in_value));
1357 return true;
1358 }
1359
Insert(size_t index,std::unique_ptr<Value> in_value)1360 bool ListValue::Insert(size_t index, std::unique_ptr<Value> in_value) {
1361 DCHECK(in_value);
1362 if (index > list_.size())
1363 return false;
1364
1365 list_.insert(list_.begin() + index, std::move(*in_value));
1366 return true;
1367 }
1368
Find(const Value & value) const1369 ListValue::const_iterator ListValue::Find(const Value& value) const {
1370 return std::find(list_.begin(), list_.end(), value);
1371 }
1372
Swap(ListValue * other)1373 void ListValue::Swap(ListValue* other) {
1374 CHECK(other->is_list());
1375 list_.swap(other->list_);
1376 }
1377
DeepCopy() const1378 ListValue* ListValue::DeepCopy() const {
1379 return new ListValue(list_);
1380 }
1381
CreateDeepCopy() const1382 std::unique_ptr<ListValue> ListValue::CreateDeepCopy() const {
1383 return std::make_unique<ListValue>(list_);
1384 }
1385
1386 ValueSerializer::~ValueSerializer() = default;
1387
1388 ValueDeserializer::~ValueDeserializer() = default;
1389
operator <<(std::ostream & out,const Value & value)1390 std::ostream& operator<<(std::ostream& out, const Value& value) {
1391 std::string json;
1392 JSONWriter::WriteWithOptions(value, JSONWriter::OPTIONS_PRETTY_PRINT, &json);
1393 return out << json;
1394 }
1395
operator <<(std::ostream & out,const Value::Type & type)1396 std::ostream& operator<<(std::ostream& out, const Value::Type& type) {
1397 if (static_cast<int>(type) < 0 ||
1398 static_cast<size_t>(type) >= arraysize(kTypeNames))
1399 return out << "Invalid Type (index = " << static_cast<int>(type) << ")";
1400 return out << Value::GetTypeName(type);
1401 }
1402
1403 } // namespace base
1404