• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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                        &current_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