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