1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_VALUES_H_
#define BASE_VALUES_H_
#include <stddef.h>
#include <stdint.h>
#include <array>
#include <initializer_list>
#include <iosfwd>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/base_export.h"
#include "base/bit_cast.h"
#include "base/compiler_specific.h"
#include "base/containers/checked_iterators.h"
#include "base/containers/checked_range.h"
#include "base/containers/cxx20_erase_vector.h"
#include "base/containers/flat_map.h"
#include "base/containers/span.h"
#include "base/strings/string_piece.h"
#include "base/trace_event/base_tracing_forward.h"
#include "base/value_iterators.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
namespace base {
class DictionaryValue;
class ListValue;
// The `Value` class is a variant type can hold one of the following types:
// - null
// - bool
// - int
// - double
// - string (internally UTF8-encoded)
// - binary data (i.e. a blob)
// - dictionary of string keys to `Value`s
// - list of `Value`s
//
// With the exception of binary blobs, `Value` is intended to be the C++ version
// of data types that can be represented in JSON.
//
// Warning: blob support may be removed in the future.
//
// ## Usage
//
// Do not use `Value` if a more specific type would be more appropriate. For
// example, a function that only accepts dictionary values should have a
// `base::Value::Dict` parameter, not a `base::Value` parameter.
//
// Construction:
//
// `Value` is directly constructible from `bool`, `int`, `double`, binary blobs
// (`std::vector<uint8_t>`), `base::StringPiece`, `base::StringPiece16`,
// `Value::Dict`, and `Value::List`.
//
// Copying:
//
// `Value` does not support C++ copy semantics to make it harder to accidentally
// copy large values. Instead, use `Clone()` to manually create a deep copy.
//
// Reading:
//
// `GetBool()`, GetInt()`, et cetera `CHECK()` that the `Value` has the correct
// subtype before returning the contained value. `bool`, `int`, `double` are
// returned by value. Binary blobs, `std::string`, `Value::Dict`, `Value::List`
// are returned by reference.
//
// `GetIfBool()`, `GetIfInt()`, et cetera return `absl::nullopt`/`nullptr` if
// the `Value` does not have the correct subtype; otherwise, returns the value
// wrapped in an `absl::optional` (for `bool`, `int`, `double`) or by pointer
// (for binary blobs, `std::string`, `Value::Dict`, `Value::List`).
//
// Note: both `GetDouble()` and `GetIfDouble()` still return a non-null result
// when the subtype is `Value::Type::INT`. In that case, the stored value is
// coerced to a double before being returned.
//
// Assignment:
//
// It is not possible to directly assign `bool`, `int`, et cetera to a `Value`.
// Instead, wrap the underlying type in `Value` before assigning.
//
// ## Dictionaries and Lists
//
// `Value` provides the `Value::Dict` and `Value::List` container types for
// working with dictionaries and lists of values respectively, rather than
// exposing the underlying container types directly. This allows the types to
// provide convenient helpers for dictionaries and lists, as well as giving
// greater flexibility for changing implementation details in the future.
//
// Both container types support enough STL-isms to be usable in range-based for
// loops and generic operations such as those from <algorithm>.
//
// Dictionaries support:
// - `empty()`, `size()`, `begin()`, `end()`, `cbegin()`, `cend()`,
// `contains()`, `clear()`, `erase()`: Identical to the STL container
// equivalents, with additional safety checks, e.g. iterators will
// `CHECK()` if `end()` is dereferenced.
//
// - `Clone()`: Create a deep copy.
// - `Merge()`: Merge another dictionary into this dictionary.
// - `Find()`: Find a value by `StringPiece` key, returning nullptr if the key
// is not present.
// - `FindBool()`, `FindInt()`, ...: Similar to `Find()`, but ensures that the
// `Value` also has the correct subtype. Same return semantics as
// `GetIfBool()`, `GetIfInt()`, et cetera, returning `absl::nullopt` or
// `nullptr` if the key is not present or the value has the wrong subtype.
// - `Set()`: Associate a value with a `StringPiece` key. Accepts `Value` or any
// of the subtypes that `Value` can hold.
// - `Remove()`: Remove the key from this dictionary, if present.
// - `Extract()`: If the key is present in the dictionary, removes the key from
// the dictionary and transfers ownership of `Value` to the caller.
// Otherwise, returns `absl::nullopt`.
//
// Dictionaries also support an additional set of helper methods that operate on
// "paths": `FindByDottedPath()`, `SetByDottedPath()`, `RemoveByDottedPath()`,
// and `ExtractByDottedPath()`. Dotted paths are a convenience method of naming
// intermediate nested dictionaries, separating the components of the path using
// '.' characters. For example, finding a string path on a `Value::Dict` using
// the dotted path:
//
// "aaa.bbb.ccc"
//
// Will first look for a `Value::Type::DICT` associated with the key "aaa", then
// another `Value::Type::DICT` under the "aaa" dict associated with the
// key "bbb", and then a `Value::Type::STRING` under the "bbb" dict associated
// with the key "ccc".
//
// If a path only has one component (i.e. has no dots), please use the regular,
// non-path APIs.
//
// Lists support:
// - `empty()`, `size()`, `begin()`, `end()`, `cbegin()`, `cend()`,
// `front()`, `back()`, `reserve()`, `operator[]`, `clear()`, `erase()`:
// Identical to the STL container equivalents, with additional safety
// checks, e.g. `operator[]` will `CHECK()` if the index is out of range.
// - `Clone()`: Create a deep copy.
// - `Append()`: Append a value to the end of the list. Accepts `Value` or any
// of the subtypes that `Value` can hold.
// - `Insert()`: Insert a `Value` at a specified point in the list.
// - `EraseValue()`: Erases all matching `Value`s from the list.
// - `EraseIf()`: Erase all `Value`s matching an arbitrary predicate from the
// list.
//
// ## Refactoring Notes
//
// `Value` was originally implemented as a class hierarchy, with a `Value` base
// class, and a leaf class for each of the different types of `Value` subtypes.
// https://docs.google.com/document/d/1uDLu5uTRlCWePxQUEHc8yNQdEoE1BDISYdpggWEABnw
// proposed an overhaul of the `Value` API that has now largely been
// implemented, though there remains a significant amount of legacy code that is
// still being migrated as part of the code health migration.
//
// OLD WAY:
//
// std::unique_ptr<base::Value> GetFoo() {
// std::unique_ptr<DictionaryValue> dict;
// dict->SetString("mykey", "foo");
// return dict;
// }
//
// NEW WAY:
//
// base::Value GetFoo() {
// base::Value::Dict dict;
// dict.Set("mykey", "abc");
// return base::Value(std::move(dict));
// }
//
// To avoid losing type information with the new variant-based design, migration
// off the deprecated types should use more specific subtypes where possible:
//
// OLD WAY:
//
// void AlwaysTakesList(std::unique_ptr<base::ListValue> list);
// void AlwaysTakesDict(std::unique_ptr<base::DictionaryValue> dict);
//
// DEPRECATED (PREVIOUS) WAY:
//
// void AlwaysTakesList(std::vector<base::Value> list);
// void AlwaysTakesListAlternative1(base::Value::ConstListView list);
// void AlwaysTakesListAlternative2(base::Value::ListView& list);
// void AlwaysTakesListAlterantive3(base::Value::ListStorage);
// void AlwaysTakesDict(base::flat_map<std::string, base::Value> dict);
// void AlwaysTakesDictAlternative(base::Value::DictStorage);
//
// NEW WAY:
//
// void AlwaysTakesList(base::Value::List list);
// void AlwaysTakesDict(base::Value::Dict dict);
//
// Migrating code may require conversions on API boundaries. If something seems
// awkward/inefficient, please reach out to #code-health-rotation on Slack for
// consultation: it is entirely possible that certain classes of APIs may be
// missing due to an unrealized need.
class BASE_EXPORT GSL_OWNER Value {
public:
using BlobStorage = std::vector<uint8_t>;
using DeprecatedListStorage = std::vector<Value>;
using DeprecatedDictStorage = flat_map<std::string, Value>;
// TODO(https://crbug.com/1291666): Make these private.
using ListStorage = DeprecatedListStorage;
using DictStorage = DeprecatedDictStorage;
// Like `DictStorage`, but with std::unique_ptr in the mapped type. This is
// due to legacy reasons, and should be removed once no caller relies on
// stability of pointers anymore.
using LegacyDictStorage = flat_map<std::string, std::unique_ptr<Value>>;
using DeprecatedListView = CheckedContiguousRange<ListStorage>;
using DeprecatedConstListView = CheckedContiguousConstRange<ListStorage>;
// TODO(https://crbug.com/1291666): Make these private.
using ListView = DeprecatedListView;
using ConstListView = DeprecatedConstListView;
class Dict;
class List;
enum class Type : unsigned char {
NONE = 0,
BOOLEAN,
INTEGER,
DOUBLE,
STRING,
BINARY,
DICT,
// TODO(https://crbug.com/1291670): Deprecated and will be removed.
DICTIONARY = DICT,
LIST,
// Note: Do not add more types. See the file-level comment above for why.
};
// Adaptors for converting from the old way to the new way and vice versa.
static Value FromUniquePtrValue(std::unique_ptr<Value> val);
static std::unique_ptr<Value> ToUniquePtrValue(Value val);
static const DictionaryValue& AsDictionaryValue(const Value& val);
static const ListValue& AsListValue(const Value& val);
Value() noexcept;
Value(Value&&) noexcept;
Value& operator=(Value&&) noexcept;
// Deleted to prevent accidental copying.
Value(const Value&) = delete;
Value& operator=(const Value&) = delete;
// Creates a deep copy of this value.
Value Clone() const;
// Creates a `Value` of `type`. The data of the corresponding type will be
// default constructed.
explicit Value(Type type);
// Constructor for `Value::Type::BOOLEAN`.
explicit Value(bool value);
// Prevent pointers from implicitly converting to bool. Another way to write
// this would be to template the bool constructor and use SFINAE to only allow
// use if `std::is_same_v<T, bool>` is true, but this has surprising behavior
// with range-based for loops over a `std::vector<bool>` (which will
// unintuitively match the int overload instead).
//
// The `const` is load-bearing; otherwise, a `char*` argument would prefer the
// deleted overload due to requiring a qualification conversion.
template <typename T>
explicit Value(const T*) = delete;
// Constructor for `Value::Type::INT`.
explicit Value(int value);
// Constructor for `Value::Type::DOUBLE`.
explicit Value(double value);
// Constructors for `Value::Type::STRING`.
explicit Value(StringPiece value);
explicit Value(StringPiece16 value);
// `char*` and `char16_t*` are needed to provide a more specific overload than
// the deleted `const T*` overload above.
explicit Value(const char* value);
explicit Value(const char16_t* value);
// `std::string&&` allows for efficient move construction.
explicit Value(std::string&& value) noexcept;
// Constructors for `Value::Type::BINARY`.
explicit Value(const std::vector<char>& value);
explicit Value(base::span<const uint8_t> value);
explicit Value(BlobStorage&& value) noexcept;
// Constructor for `Value::Type::DICT`.
explicit Value(Dict&& value) noexcept;
// Constructor for `Value::Type::LIST`.
explicit Value(List&& value) noexcept;
// DEPRECATED: prefer `Value(Dict&&)`.
explicit Value(const DictStorage& value);
explicit Value(DictStorage&& value);
// DEPRECATED: prefer `Value(List&&)`.
explicit Value(span<const Value> value);
explicit Value(ListStorage&& value) noexcept;
~Value();
// Returns the name for a given `type`.
static const char* GetTypeName(Type type);
// Returns the type of the value stored by the current Value object.
Type type() const { return static_cast<Type>(data_.index()); }
// Returns true if the current object represents a given type.
bool is_none() const { return type() == Type::NONE; }
bool is_bool() const { return type() == Type::BOOLEAN; }
bool is_int() const { return type() == Type::INTEGER; }
bool is_double() const { return type() == Type::DOUBLE; }
bool is_string() const { return type() == Type::STRING; }
bool is_blob() const { return type() == Type::BINARY; }
bool is_dict() const { return type() == Type::DICT; }
bool is_list() const { return type() == Type::LIST; }
// Returns the stored data if the type matches, or `absl::nullopt`/`nullptr`
// otherwise. `bool`, `int`, and `double` are returned in a wrapped
// `absl::optional`; blobs, `Value::Dict`, and `Value::List` are returned by
// pointer.
absl::optional<bool> GetIfBool() const;
absl::optional<int> GetIfInt() const;
// Returns a non-null value for both `Value::Type::DOUBLE` and
// `Value::Type::INT`, converting the latter to a double.
absl::optional<double> GetIfDouble() const;
const std::string* GetIfString() const;
std::string* GetIfString();
const BlobStorage* GetIfBlob() const;
const Dict* GetIfDict() const;
Dict* GetIfDict();
const List* GetIfList() const;
List* GetIfList();
// Similar to the `GetIf...()` variants above, but fails with a `CHECK()` on a
// type mismatch. `bool`, `int`, and `double` are returned by value; blobs,
// `Value::Dict`, and `Value::List` are returned by reference.
bool GetBool() const;
int GetInt() const;
// Returns a value for both `Value::Type::DOUBLE` and `Value::Type::INT`,
// converting the latter to a double.
double GetDouble() const;
const std::string& GetString() const;
std::string& GetString();
const BlobStorage& GetBlob() const;
const Dict& GetDict() const;
Dict& GetDict();
const List& GetList() const;
List& GetList();
// Represents a dictionary of string keys to Values.
class BASE_EXPORT GSL_OWNER Dict {
public:
using iterator = detail::dict_iterator;
using const_iterator = detail::const_dict_iterator;
Dict();
Dict(Dict&&) noexcept;
Dict& operator=(Dict&&) noexcept;
// Deleted to prevent accidental copying.
Dict(const Dict&) = delete;
Dict& operator=(const Dict&) = delete;
~Dict();
// TODO(dcheng): Probably need to allow construction from a pair of
// iterators for now due to the prevalence of DictStorage.
// Returns true if there are no entries in this dictionary and false
// otherwise.
bool empty() const;
// Returns the number of entries in this dictionary.
size_t size() const;
// Returns an iterator to the first entry in this dictionary.
iterator begin();
const_iterator begin() const;
const_iterator cbegin() const;
// Returns an iterator following the last entry in this dictionary. May not
// be dereferenced.
iterator end();
const_iterator end() const;
const_iterator cend() const;
// Returns true if `key` is an entry in this dictionary.
bool contains(base::StringPiece key) const;
// Removes all entries from this dictionary.
void clear();
// Removes the entry referenced by `pos` in this dictionary and returns an
// iterator to the entry following the removed entry.
iterator erase(iterator pos);
iterator erase(const_iterator pos);
// Creates a deep copy of this dictionary.
Dict Clone() const;
// Merges the entries from `dict` into this dictionary. If an entry with the
// same key exists in this dictionary and `dict`:
// - if both entries are dictionaries, they will be recursively merged
// - otherwise, the already-existing entry in this dictionary will be
// overwritten with the entry from `dict`.
void Merge(const Dict& dict);
// Finds the entry corresponding to `key` in this dictionary. Returns
// nullptr if there is no such entry.
const Value* Find(StringPiece key) const;
Value* Find(StringPiece key);
// Similar to `Find()` above, but returns `absl::nullopt`/`nullptr` if the
// type of the entry does not match. `bool`, `int`, and `double` are
// returned in a wrapped `absl::optional`; blobs, `Value::Dict`, and
// `Value::List` are returned by pointer.
absl::optional<bool> FindBool(StringPiece key) const;
absl::optional<int> FindInt(StringPiece key) const;
// Returns a non-null value for both `Value::Type::DOUBLE` and
// `Value::Type::INT`, converting the latter to a double.
absl::optional<double> FindDouble(StringPiece key) const;
const std::string* FindString(StringPiece key) const;
std::string* FindString(StringPiece key);
const BlobStorage* FindBlob(StringPiece key) const;
const Dict* FindDict(StringPiece key) const;
Dict* FindDict(StringPiece key);
const List* FindList(StringPiece key) const;
List* FindList(StringPiece key);
// Sets an entry with `key` and `value` in this dictionary, overwriting any
// existing entry with the same `key`. Returns a pointer to the set `value`.
Value* Set(StringPiece key, Value&& value);
Value* Set(StringPiece key, bool value);
template <typename T>
Value* Set(StringPiece, const T*) = delete;
Value* Set(StringPiece key, int value);
Value* Set(StringPiece key, double value);
Value* Set(StringPiece key, StringPiece value);
Value* Set(StringPiece key, StringPiece16 value);
Value* Set(StringPiece key, const char* value);
Value* Set(StringPiece key, const char16_t* value);
Value* Set(StringPiece key, std::string&& value);
Value* Set(StringPiece key, BlobStorage&& value);
Value* Set(StringPiece key, Dict&& value);
Value* Set(StringPiece key, List&& value);
// Removes the entry corresponding to `key` from this dictionary. Returns
// true if an entry was removed or false otherwise.
bool Remove(StringPiece key);
// Similar to `Remove()`, but returns the value corresponding to the removed
// entry or `absl::nullopt` otherwise.
absl::optional<Value> Extract(StringPiece key);
// Equivalent to the above methods but operating on paths instead of keys.
// A path is shorthand syntax for referring to a key nested inside
// intermediate dictionaries, with components delimited by ".". Paths may
// not be empty.
//
// Prefer the non-path methods above when possible. Paths that have only one
// component (i.e. no dots in the path) should never use the path-based
// methods.
//
// Originally, the path-based APIs were the only way of specifying a key, so
// there are likely to be many legacy (and unnecessary) uses of the path
// APIs that do not actually require traversing nested dictionaries.
const Value* FindByDottedPath(StringPiece path) const;
Value* FindByDottedPath(StringPiece path);
absl::optional<bool> FindBoolByDottedPath(StringPiece path) const;
absl::optional<int> FindIntByDottedPath(StringPiece path) const;
// Returns a non-null value for both `Value::Type::DOUBLE` and
// `Value::Type::INT`, converting the latter to a double.
absl::optional<double> FindDoubleByDottedPath(StringPiece path) const;
const std::string* FindStringByDottedPath(StringPiece path) const;
std::string* FindStringByDottedPath(StringPiece path);
const BlobStorage* FindBlobByDottedPath(StringPiece path) const;
const Dict* FindDictByDottedPath(StringPiece path) const;
Dict* FindDictByDottedPath(StringPiece path);
const List* FindListByDottedPath(StringPiece path) const;
List* FindListByDottedPath(StringPiece path);
// Creates a new entry with a dictionary for any non-last component that is
// missing an entry while performing the path traversal. Will fail if any
// non-last component of the path refers to an already-existing entry that
// is not a dictionary. Returns `nullptr` on failure.
Value* SetByDottedPath(StringPiece path, Value&& value);
Value* SetByDottedPath(StringPiece path, bool value);
template <typename T>
Value* SetByDottedPath(StringPiece, const T*) = delete;
Value* SetByDottedPath(StringPiece path, int value);
Value* SetByDottedPath(StringPiece path, double value);
Value* SetByDottedPath(StringPiece path, StringPiece value);
Value* SetByDottedPath(StringPiece path, StringPiece16 value);
Value* SetByDottedPath(StringPiece path, const char* value);
Value* SetByDottedPath(StringPiece path, const char16_t* value);
Value* SetByDottedPath(StringPiece path, std::string&& value);
Value* SetByDottedPath(StringPiece path, BlobStorage&& value);
Value* SetByDottedPath(StringPiece path, Dict&& value);
Value* SetByDottedPath(StringPiece path, List&& value);
bool RemoveByDottedPath(StringPiece path);
absl::optional<Value> ExtractByDottedPath(StringPiece path);
// Serializes to a string for logging and debug purposes.
std::string DebugString() const;
private:
BASE_EXPORT friend bool operator==(const Dict& lhs, const Dict& rhs);
BASE_EXPORT friend bool operator!=(const Dict& lhs, const Dict& rhs);
BASE_EXPORT friend bool operator<(const Dict& lhs, const Dict& rhs);
BASE_EXPORT friend bool operator>(const Dict& lhs, const Dict& rhs);
BASE_EXPORT friend bool operator<=(const Dict& lhs, const Dict& rhs);
BASE_EXPORT friend bool operator>=(const Dict& lhs, const Dict& rhs);
// For legacy access to the internal storage type.
friend Value;
explicit Dict(const flat_map<std::string, std::unique_ptr<Value>>& storage);
flat_map<std::string, std::unique_ptr<Value>> storage_;
};
// Represents a list of Values.
class BASE_EXPORT GSL_OWNER List {
public:
using iterator = CheckedContiguousIterator<Value>;
using const_iterator = CheckedContiguousConstIterator<Value>;
List();
List(List&&) noexcept;
List& operator=(List&&) noexcept;
// Deleted to prevent accidental copying.
List(const List&) = delete;
List& operator=(const List&) = delete;
~List();
// TODO(dcheng): Probably need to allow construction from a pair of
// iterators for now due to the prevalence of ListStorage now.
// Returns true if there are no values in this list and false otherwise.
bool empty() const;
// Returns the number of values in this list.
size_t size() const;
// Returns an iterator to the first value in this list.
iterator begin();
const_iterator begin() const;
const_iterator cbegin() const;
// Returns an iterator following the last value in this list. May not be
// dereferenced.
iterator end();
const_iterator end() const;
const_iterator cend() const;
// Returns a reference to the first value in the container. Fails with
// `CHECK()` if the list is empty.
const Value& front() const;
Value& front();
// Returns a reference to the last value in the container. Fails with
// `CHECK()` if the list is empty.
const Value& back() const;
Value& back();
// Increase the capacity of the backing container, but does not change
// the size. Assume all existing iterators will be invalidated.
void reserve(size_t capacity);
// Returns a reference to the value at `index` in this list. Fails with a
// `CHECK()` if `index >= size()`.
const Value& operator[](size_t index) const;
Value& operator[](size_t index);
// Removes all value from this list.
void clear();
// Removes the value referenced by `pos` in this list and returns an
// iterator to the value following the removed value.
iterator erase(iterator pos);
const_iterator erase(const_iterator pos);
// Creates a deep copy of this dictionary.
List Clone() const;
// Appends `value` to the end of this list.
void Append(Value&& value);
void Append(bool value);
template <typename T>
void Append(const T*) = delete;
void Append(int value);
void Append(double value);
void Append(StringPiece value);
void Append(StringPiece16 value);
void Append(const char* value);
void Append(const char16_t* value);
void Append(std::string&& value);
void Append(BlobStorage&& value);
void Append(Dict&& value);
void Append(List&& value);
// Inserts `value` before `pos` in this list. Returns an iterator to the
// inserted value.
// TODO(dcheng): Should this provide the same set of overloads that Append()
// does?
iterator Insert(const_iterator pos, Value&& value);
// Erases all values equal to `value` from this list.
size_t EraseValue(const Value& value);
// Erases all values for which `predicate` evaluates to true from this list.
template <typename Predicate>
size_t EraseIf(Predicate predicate) {
return base::EraseIf(storage_, predicate);
}
// Serializes to a string for logging and debug purposes.
std::string DebugString() const;
private:
BASE_EXPORT friend bool operator==(const List& lhs, const List& rhs);
BASE_EXPORT friend bool operator!=(const List& lhs, const List& rhs);
BASE_EXPORT friend bool operator<(const List& lhs, const List& rhs);
BASE_EXPORT friend bool operator>(const List& lhs, const List& rhs);
BASE_EXPORT friend bool operator<=(const List& lhs, const List& rhs);
BASE_EXPORT friend bool operator>=(const List& lhs, const List& rhs);
// For legacy access to the internal storage type.
friend Value;
explicit List(const std::vector<Value>& storage);
std::vector<Value> storage_;
};
// ===== DEPRECATED methods that require `type() == Type::LIST` =====
// Returns the Values in a list as a view. The mutable overload allows for
// modification of the underlying values, but does not allow changing the
// structure of the list. If this is desired, use `TakeListDeprecated()`,
// perform the operations, and return the list back to the Value via move
// assignment.
//
// DEPRECATED: prefer direct use `base::Value::List` where possible, or
// `GetList()` otherwise.
DeprecatedListView GetListDeprecated();
DeprecatedConstListView GetListDeprecated() const;
// Transfers ownership of the underlying list to the caller. Subsequent
// calls to `GetListDeprecated()` will return an empty list.
//
// DEPRECATED: prefer direct use of `base::Value::List` where possible, or
// `std::move(value.GetList())` otherwise.
DeprecatedListStorage TakeListDeprecated() &&;
// Appends `value` to the end of the list.
//
// DEPRECATED: prefer `Value::List::Append()`.
void Append(Value&& value);
// DEPRECATED: prefer `Value::List::Append()`.
void Append(bool value);
template <typename T>
void Append(const T* ptr) = delete;
// DEPRECATED: prefer `Value::List::Append()`.
void Append(int value);
// DEPRECATED: prefer `Value::List::Append()`.
void Append(double value);
// DEPRECATED: prefer `Value::List::Append()`.
void Append(StringPiece value);
// DEPRECATED: prefer `Value::List::Append()`.
void Append(StringPiece16 value);
// DEPRECATED: prefer `Value::List::Append()`.
void Append(const char* value);
// DEPRECATED: prefer `Value::List::Append()`.
void Append(const char16_t* value);
// DEPRECATED: prefer `Value::List::Append()`.
void Append(std::string&& value);
// Inserts `value` before `pos`.
//
// DEPRECATED: prefer `Value::List::Insert()`.
CheckedContiguousIterator<Value> Insert(
CheckedContiguousConstIterator<Value> pos,
Value&& value);
// Erases the Value pointed to by `iter`. Returns false if `iter` is out of
// bounds.
//
// DEPRECATED: prefer `Value::List::erase(iter)`.
bool EraseListIter(CheckedContiguousConstIterator<Value> iter);
// Erases all Values that compare equal to `val`. Returns the number of
// deleted Values.
//
// DEPRECATED: prefer `Value::List::EraseValue(val)`.
size_t EraseListValue(const Value& val);
// Erases all Values for which `pred` returns true. Returns the number of
// deleted Values.
//
// DEPRECATED: prefer `Value::List::EraseIf(pred)`.
template <typename Predicate>
size_t EraseListValueIf(Predicate pred) {
return base::EraseIf(list(), pred);
}
// Erases all Values from the list.
//
// DEPRECATED: prefer `Value::List::clear()`.
void ClearList();
// ===== DEPRECATED methods that require `type() == Type::DICT` =====
// `FindKey` looks up `key` in the underlying dictionary. If found, it returns
// a pointer to the element. Otherwise it returns nullptr.
//
// DEPRECATED: prefer `Value::Dict::Find()`.
Value* FindKey(StringPiece key);
const Value* FindKey(StringPiece key) const;
// `FindKeyOfType` is similar to `FindKey`, but it also requires the found
// value to have type `type`. If no type is found, or the found value is of a
// different type nullptr is returned.
//
// DEPRECATED: prefer `Value::Dict::FindBool()`, `Value::Dict::FindInt()`, et
// cetera.
Value* FindKeyOfType(StringPiece key, Type type);
const Value* FindKeyOfType(StringPiece key, Type type) const;
// These are convenience forms of `FindKey`. They return `absl::nullopt` or
// `nullptr` if the value is not found or doesn't have the type specified in
// the function's name.
//
// DEPRECATED: prefer `Value::Dict::FindBool()`.
absl::optional<bool> FindBoolKey(StringPiece key) const;
// DEPRECATED: prefer `Value::Dict::FindInt()`.
absl::optional<int> FindIntKey(StringPiece key) const;
// Returns a non-null value for both `Value::Type::DOUBLE` and
// `Value::Type::INT`, converting the latter to a double.
//
// DEPRECATED: prefer `Value::Dict::FindDouble()`.
absl::optional<double> FindDoubleKey(StringPiece key) const;
// DEPRECATED: prefer `Value::Dict::FindString()`.
const std::string* FindStringKey(StringPiece key) const;
std::string* FindStringKey(StringPiece key);
// DEPRECATED: prefer `Value::Dict::FindBlob()`.
const BlobStorage* FindBlobKey(StringPiece key) const;
// DEPRECATED: prefer `Value::Dict::FindDict()`.
const Value* FindDictKey(StringPiece key) const;
Value* FindDictKey(StringPiece key);
// DEPRECATED: prefer `Value::Dict::FindList()`.
const Value* FindListKey(StringPiece key) const;
Value* FindListKey(StringPiece key);
// `SetKey` looks up `key` in the underlying dictionary and sets the mapped
// value to `value`. If `key` could not be found, a new element is inserted.
// A pointer to the modified item is returned.
//
// Note: Prefer `Set<Type>Key()` if the input is not already a `Value`.
//
// DEPRECATED: Prefer `Value::Dict::Set()`.
Value* SetKey(StringPiece key, Value&& value);
// `Set`Type>Key` looks up `key` in the underlying dictionary and associates a
// corresponding Value() constructed from the second parameter. Compared to
// `SetKey()`, this avoids un-necessary temporary `Value()` creation, as well
// ambiguities in the value type.
//
// DEPRECATED: Prefer `Value::Dict::Set()`.
Value* SetBoolKey(StringPiece key, bool val);
// DEPRECATED: Prefer `Value::Dict::Set()`.
Value* SetIntKey(StringPiece key, int val);
// DEPRECATED: Prefer `Value::Dict::Set()`.
Value* SetDoubleKey(StringPiece key, double val);
// DEPRECATED: Prefer `Value::Dict::Set()`.
Value* SetStringKey(StringPiece key, StringPiece val);
// DEPRECATED: Prefer `Value::Dict::Set()`.
Value* SetStringKey(StringPiece key, StringPiece16 val);
// DEPRECATED: Prefer `Value::Dict::Set()`.
Value* SetStringKey(StringPiece key, const char* val);
// DEPRECATED: Prefer `Value::Dict::Set()`.
Value* SetStringKey(StringPiece key, std::string&& val);
// This attempts to remove the value associated with `key`. In case of
// failure, e.g. the key does not exist, false is returned and the underlying
// dictionary is not changed. In case of success, `key` is deleted from the
// dictionary and the method returns true.
//
// Deprecated: Prefer `Value::Dict::Remove()`.
bool RemoveKey(StringPiece key);
// This attempts to extract the value associated with `key`. In case of
// failure, e.g. the key does not exist, nullopt is returned and the
// underlying dictionary is not changed. In case of success, `key` is deleted
// from the dictionary and the method returns the extracted Value.
//
// DEPRECATED: Prefer `Value::Dict::Extract()`.
absl::optional<Value> ExtractKey(StringPiece key);
// Searches a hierarchy of dictionary values for a given value. If a path
// of dictionaries exist, returns the item at that path. If any of the path
// components do not exist or if any but the last path components are not
// dictionaries, returns nullptr. The type of the leaf Value is not checked.
//
// This version takes a StringPiece for the path, using dots as separators.
//
// DEPRECATED: Prefer `Value::Dict::FindByDottedPath()`.
Value* FindPath(StringPiece path);
const Value* FindPath(StringPiece path) const;
// There are also deprecated versions that take the path parameter
// as either a std::initializer_list<StringPiece> or a
// span<const StringPiece>. The latter is useful to use a
// std::vector<std::string> as a parameter but creates huge dynamic
// allocations and should be avoided!
// Note: If there is only one component in the path, use `FindKey()` instead.
//
// Example:
// std::vector<StringPiece> components = ...
// auto* found = FindPath(components);
//
// DEPRECATED: These are not common, and there is no currently planned
// replacement.
Value* FindPath(std::initializer_list<StringPiece> path);
Value* FindPath(span<const StringPiece> path);
const Value* FindPath(std::initializer_list<StringPiece> path) const;
const Value* FindPath(span<const StringPiece> path) const;
// Like FindPath() but will only return the value if the leaf Value type
// matches the given type. Will return nullptr otherwise.
// Note: Prefer `Find<Type>Path()` for simple values.
//
// Note: If there is only one component in the path, use `FindKeyOfType()`
// instead for slightly better performance.
//
// DEPRECATED: Use `Value::Dict::FindBoolByDottedPath()`,
// `Value::Dict::FindIntByDottedPath()`, et cetera.
Value* FindPathOfType(StringPiece path, Type type);
const Value* FindPathOfType(StringPiece path, Type type) const;
// Convenience accessors used when the expected type of a value is known.
// Similar to Find<Type>Key() but accepts paths instead of keys.
//
// DEPRECATED: Use `Value::Dict::FindBoolByDottedPath()`, or
// `Value::Dict::FindBool()` if the path only has one component, i.e. has no
// dots.
absl::optional<bool> FindBoolPath(StringPiece path) const;
// DEPRECATED: Use `Value::Dict::FindIntByDottedPath()`, or
// `Value::Dict::FindInt()` if the path only has one component, i.e. has no
// dots.
absl::optional<int> FindIntPath(StringPiece path) const;
// DEPRECATED: Use `Value::Dict::FindDoubleByDottedPath()`, or
// `Value::Dict::FindDouble()` if the path only has one component, i.e. has no
// dots.
absl::optional<double> FindDoublePath(StringPiece path) const;
// DEPRECATED: Use `Value::Dict::FindStringByDottedPath()`, or
// `Value::Dict::FindString()` if the path only has one component, i.e. has no
// dots.
const std::string* FindStringPath(StringPiece path) const;
std::string* FindStringPath(StringPiece path);
// DEPRECATED: Use `Value::Dict::FindBlobByDottedPath()`, or
// `Value::Dict::FindBlob()` if the path only has one component, i.e. has no
// dots.
const BlobStorage* FindBlobPath(StringPiece path) const;
// DEPRECATED: Use `Value::Dict::FindDictByDottedPath()`, or
// `Value::Dict::FindDict()` if the path only has one component, i.e. has no
// dots.
Value* FindDictPath(StringPiece path);
const Value* FindDictPath(StringPiece path) const;
// DEPRECATED: Use `Value::Dict::FindListByDottedPath()`, or
// `Value::Dict::FindList()` if the path only has one component, i.e. has no
// dots.
Value* FindListPath(StringPiece path);
const Value* FindListPath(StringPiece path) const;
// The following forms are deprecated too, use the ones that take the path
// as a single StringPiece instead.
//
// DEPRECATED: These are not common, and there is no currently planned
// replacement.
Value* FindPathOfType(std::initializer_list<StringPiece> path, Type type);
Value* FindPathOfType(span<const StringPiece> path, Type type);
const Value* FindPathOfType(std::initializer_list<StringPiece> path,
Type type) const;
const Value* FindPathOfType(span<const StringPiece> path, Type type) const;
// Sets the given path, expanding and creating dictionary keys as necessary.
//
// If the current value is not a dictionary, the function returns nullptr. If
// path components do not exist, they will be created. If any but the last
// components matches a value that is not a dictionary, the function will fail
// (it will not overwrite the value) and return nullptr. The last path
// component will be unconditionally overwritten if it exists, and created if
// it doesn't.
//
// Note: If there is only one component in the path, use `SetKey()` instead.
// Note: Using `Set<Type>Path()` might be more convenient and efficient.
//
// DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
Value* SetPath(StringPiece path, Value&& value);
// These setters are more convenient and efficient than the corresponding
// SetPath(...) call.
//
// DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
Value* SetBoolPath(StringPiece path, bool value);
// DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
Value* SetIntPath(StringPiece path, int value);
// DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
Value* SetDoublePath(StringPiece path, double value);
// DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
Value* SetStringPath(StringPiece path, StringPiece value);
// DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
Value* SetStringPath(StringPiece path, const char* value);
// DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
Value* SetStringPath(StringPiece path, std::string&& value);
// DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
Value* SetStringPath(StringPiece path, StringPiece16 value);
// DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
Value* SetPath(std::initializer_list<StringPiece> path, Value&& value);
Value* SetPath(span<const StringPiece> path, Value&& value);
// Tries to remove a Value at the given path.
//
// If the current value is not a dictionary or any path component does not
// exist, this operation fails, leaves underlying Values untouched and returns
// `false`. In case intermediate dictionaries become empty as a result of this
// path removal, they will be removed as well.
// Note: If there is only one component in the path, use `RemoveKey()`
// instead.
//
// DEPRECATED: Use `Value::Dict::RemoveByDottedPath()`.
bool RemovePath(StringPiece path);
// Tries to extract a Value at the given path.
//
// If the current value is not a dictionary or any path component does not
// exist, this operation fails, leaves underlying Values untouched and returns
// nullopt. In case intermediate dictionaries become empty as a result of this
// path removal, they will be removed as well. Returns the extracted value on
// success.
// Note: If there is only one component in the path, use `ExtractKey()`
// instead.
//
// DEPRECATED: Use `Value::Dict::ExtractByDottedPath()`.
absl::optional<Value> ExtractPath(StringPiece path);
using dict_iterator_proxy = detail::dict_iterator_proxy;
using const_dict_iterator_proxy = detail::const_dict_iterator_proxy;
// `DictItems` returns a proxy object that exposes iterators to the underlying
// dictionary. These are intended for iteration over all items in the
// dictionary and are compatible with for-each loops and standard library
// algorithms.
//
// Unlike with std::map, a range-for over the non-const version of
// `DictItems()` will range over items of type
// `pair<const std::string&, Value&>`, so code of the form
// for (auto kv : my_value.DictItems())
// Mutate(kv.second);
// will actually alter `my_value` in place (if it isn't const).
//
// DEPRECATED: Use a range-based for loop over `base::Value::Dict` directly
// instead.
dict_iterator_proxy DictItems();
const_dict_iterator_proxy DictItems() const;
// Transfers ownership of the underlying dict to the caller. Subsequent
// calls to DictItems() will return an empty dict.
//
// DEPRECATED: prefer direct use of `base::Value::Dict` where possible, or
// `std::move(value.GetDict())` otherwise.
DeprecatedDictStorage TakeDictDeprecated() &&;
// DEPRECATED: prefer `Value::Dict::size()`.
size_t DictSize() const;
// DEPRECATED: prefer `Value::Dict::empty()`.
bool DictEmpty() const;
// DEPRECATED: prefer `Value::Dict::clear()`.
void DictClear();
// Merge `dictionary` into this value. This is done recursively, i.e. any
// sub-dictionaries will be merged as well. In case of key collisions, the
// passed in dictionary takes precedence and data already present will be
// replaced. Values within `dictionary` are deep-copied, so `dictionary` may
// be freed any time after this call.
// Note: This requires that `type()` and `dictionary->type()` is
// Type::DICT.
//
// DEPRECATED: prefer `Value::Dict::Merge()`.
void MergeDictionary(const Value* dictionary);
// These methods allow the convenient retrieval of the contents of the Value.
// If the current object can be converted into the given type, the value is
// returned through the `out_value` parameter and true is returned;
// otherwise, false is returned and `out_value` is unchanged.
// ListValue::From is the equivalent for std::unique_ptr conversions.
//
// DEPRECATED: prefer direct use `base::Value::List` where possible, or
// `GetIfList()` otherwise.
bool GetAsList(ListValue** out_value);
bool GetAsList(const ListValue** out_value) const;
// DictionaryValue::From is the equivalent for std::unique_ptr conversions.
//
// DEPRECATED: prefer direct use `base::Value::Dict` where possible, or
// `GetIfDict()` otherwise.
bool GetAsDictionary(DictionaryValue** out_value);
bool GetAsDictionary(const DictionaryValue** out_value) const;
// Note: Do not add more types. See the file-level comment above for why.
// This creates a deep copy of the entire Value tree, and returns a pointer
// to the copy. The caller gets ownership of the copy, of course.
// Subclasses return their own type directly in their overrides;
// this works because C++ supports covariant return types.
// TODO(crbug.com/646113): Delete this and migrate callsites.
//
// DEPRECATED: prefer `Value::Clone()`.
std::unique_ptr<Value> CreateDeepCopy() const;
// Comparison operators so that Values can easily be used with standard
// library algorithms and associative containers.
BASE_EXPORT friend bool operator==(const Value& lhs, const Value& rhs);
BASE_EXPORT friend bool operator!=(const Value& lhs, const Value& rhs);
BASE_EXPORT friend bool operator<(const Value& lhs, const Value& rhs);
BASE_EXPORT friend bool operator>(const Value& lhs, const Value& rhs);
BASE_EXPORT friend bool operator<=(const Value& lhs, const Value& rhs);
BASE_EXPORT friend bool operator>=(const Value& lhs, const Value& rhs);
// Compares if two Value objects have equal contents.
// DEPRECATED, use `operator==(const Value& lhs, const Value& rhs)` instead.
// TODO(crbug.com/646113): Delete this and migrate callsites.
//
// DEPRECATED: prefer direct use of the equality operator instead.
bool Equals(const Value* other) const;
// Estimates dynamic memory usage. Requires tracing support
// (enable_base_tracing gn flag), otherwise always returns 0. See
// base/trace_event/memory_usage_estimator.h for more info.
size_t EstimateMemoryUsage() const;
// Serializes to a string for logging and debug purposes.
std::string DebugString() const;
#if BUILDFLAG(ENABLE_BASE_TRACING)
// Write this object into a trace.
void WriteIntoTrace(perfetto::TracedValue) const;
#endif // BUILDFLAG(ENABLE_BASE_TRACING)
template <typename Visitor>
auto Visit(Visitor&& visitor) const {
return absl::visit(std::forward<Visitor>(visitor), data_);
}
protected:
// Checked convenience accessors for dict and list.
const LegacyDictStorage& dict() const { return GetDict().storage_; }
LegacyDictStorage& dict() { return GetDict().storage_; }
const ListStorage& list() const { return GetList().storage_; }
ListStorage& list() { return GetList().storage_; }
// Internal constructors, allowing the simplify the implementation of Clone().
explicit Value(const LegacyDictStorage& storage);
explicit Value(LegacyDictStorage&& storage) noexcept;
private:
// For access to DoubleStorage.
friend class ValueView;
// Special case for doubles, which are aligned to 8 bytes on some
// 32-bit architectures. In this case, a simple declaration as a
// double member would make the whole union 8 byte-aligned, which
// would also force 4 bytes of wasted padding space before it in
// the Value layout.
//
// To override this, store the value as an array of 32-bit integers, and
// perform the appropriate bit casts when reading / writing to it.
class DoubleStorage {
public:
explicit DoubleStorage(double v);
DoubleStorage(const DoubleStorage&) = default;
DoubleStorage& operator=(const DoubleStorage&) = default;
// Provide an implicit conversion to double to simplify the use of visitors
// with `Value::Visit()`. Otherwise, visitors would need a branch for
// handling `DoubleStorage` like:
//
// value.Visit([] (const auto& member) {
// using T = std::decay_t<decltype(member)>;
// if constexpr (std::is_same_v<T, Value::DoubleStorage>) {
// SomeFunction(double{member});
// } else {
// SomeFunction(member);
// }
// });
operator double() const { return bit_cast<double>(v_); }
private:
friend bool operator==(const DoubleStorage& lhs, const DoubleStorage& rhs) {
return double{lhs} == double{rhs};
}
friend bool operator!=(const DoubleStorage& lhs, const DoubleStorage& rhs) {
return !(lhs == rhs);
}
friend bool operator<(const DoubleStorage& lhs, const DoubleStorage& rhs) {
return double{lhs} < double{rhs};
}
friend bool operator>(const DoubleStorage& lhs, const DoubleStorage& rhs) {
return rhs < lhs;
}
friend bool operator<=(const DoubleStorage& lhs, const DoubleStorage& rhs) {
return !(rhs < lhs);
}
friend bool operator>=(const DoubleStorage& lhs, const DoubleStorage& rhs) {
return !(lhs < rhs);
}
alignas(4) std::array<char, sizeof(double)> v_;
};
// Internal constructors, allowing the simplify the implementation of Clone().
explicit Value(absl::monostate);
explicit Value(DoubleStorage storage);
absl::variant<absl::monostate,
bool,
int,
DoubleStorage,
std::string,
BlobStorage,
Dict,
List>
data_;
};
// DictionaryValue provides a key-value dictionary with (optional) "path"
// parsing for recursive access; see the comment at the top of the file. Keys
// are std::string's and should be UTF-8 encoded.
//
// DEPRECATED: prefer `Value::Dict`.
class BASE_EXPORT DictionaryValue : public Value {
public:
// Returns `value` if it is a dictionary, nullptr otherwise.
static std::unique_ptr<DictionaryValue> From(std::unique_ptr<Value> value);
DictionaryValue();
explicit DictionaryValue(const LegacyDictStorage& in_dict);
explicit DictionaryValue(LegacyDictStorage&& in_dict) noexcept;
// Returns true if the current dictionary has a value for the given key.
//
// DEPRECATED: prefer `Value::Dict::contains()`.
bool HasKey(StringPiece key) const;
// Sets the Value associated with the given path starting from this object.
// A path has the form "<key>" or "<key>.<key>.[...]", where "." indexes
// into the next DictionaryValue down. Obviously, "." can't be used
// within a key, but there are no other restrictions on keys.
// If the key at any step of the way doesn't exist, or exists but isn't
// a DictionaryValue, a new DictionaryValue will be created and attached
// to the path in that location. `in_value` must be non-null.
// Returns a pointer to the inserted value.
//
// DEPRECATED: prefer `Value::Dict::Set()` (if the path only has one
// component, i.e. has no dots), or `Value::Dict::SetByDottedPath()`
// otherwise.
Value* Set(StringPiece path, std::unique_ptr<Value> in_value);
// Convenience forms of Set(). These methods will replace any existing
// value at that path, even if it has a different type.
//
// DEPRECATED: prefer `Value::Dict::Set()` (if the path only has one
// component, i.e. has no dots), or `Value::Dict::SetByDottedPath()`
// otherwise.
Value* SetBoolean(StringPiece path, bool in_value);
// DEPRECATED: prefer `Value::Dict::Set()` (if the path only has one
// component, i.e. has no dots), or `Value::Dict::SetByDottedPath()`
// otherwise.
Value* SetInteger(StringPiece path, int in_value);
// DEPRECATED: prefer `Value::Dict::Set()` (if the path only has one
// component, i.e. has no dots), or `Value::Dict::SetByDottedPath()`
// otherwise.
Value* SetDouble(StringPiece path, double in_value);
// DEPRECATED: prefer `Value::Dict::Set()` (if the path only has one
// component, i.e. has no dots), or `Value::Dict::SetByDottedPath()`
// otherwise.
Value* SetString(StringPiece path, StringPiece in_value);
// DEPRECATED: prefer `Value::Dict::Set()` (if the path only has one
// component, i.e. has no dots), or `Value::Dict::SetByDottedPath()`
// otherwise.
Value* SetString(StringPiece path, const std::u16string& in_value);
// DEPRECATED: prefer `Value::Dict::Set()` (if the path only has one
// component, i.e. has no dots), or `Value::Dict::SetByDottedPath()`
// otherwise.
ListValue* SetList(StringPiece path, std::unique_ptr<ListValue> in_value);
// Like Set(), but without special treatment of '.'. This allows e.g. URLs to
// be used as paths.
//
// DEPRECATED: prefer `Value::Dict::Set()`.
Value* SetWithoutPathExpansion(StringPiece key,
std::unique_ptr<Value> in_value);
// Gets the Value associated with the given path starting from this object.
// A path has the form "<key>" or "<key>.<key>.[...]", where "." indexes
// into the next DictionaryValue down. If the path can be resolved
// successfully, the value for the last key in the path will be returned
// through the `out_value` parameter, and the function will return true.
// Otherwise, it will return false and `out_value` will be untouched.
// Note that the dictionary always owns the value that's returned.
// `out_value` is optional and will only be set if non-NULL.
//
// DEPRECATED: prefer `Value::Dict::Find()` (if the path only has one
// component, i.e. has no dots), or `Value::Dict::FindByDottedPath()`
// otherwise.
bool Get(StringPiece path, const Value** out_value) const;
bool Get(StringPiece path, Value** out_value);
// These are convenience forms of `Get()`. The value will be retrieved
// and the return value will be true if the path is valid and the value at
// the end of the path can be returned in the form specified.
// `out_value` is optional and will only be set if non-NULL.
//
// DEPRECATED: prefer `Value::Dict::FindInt()` (if the path only has one
// component, i.e. has no dots), or `Value::Dict::FindIntByDottedPath()`
// otherwise.
bool GetInteger(StringPiece path, int* out_value) const;
// DEPRECATED: prefer `Value::Dict::FindString()` (if the path only has one
// component, i.e. has no dots), or `Value::Dict::FindStringByDottedPath()`
// otherwise.
bool GetString(StringPiece path, std::string* out_value) const;
bool GetString(StringPiece path, std::u16string* out_value) const;
// DEPRECATED: prefer `Value::Dict::FindDict()` (if the path only has one
// component, i.e. has no dots), or `Value::Dict::FindDictByDottedPath()`
// otherwise.
bool GetDictionary(StringPiece path, const DictionaryValue** out_value) const;
bool GetDictionary(StringPiece path, DictionaryValue** out_value);
// DEPRECATED: prefer `Value::Dict::FindList()` (if the path only has one
// component, i.e. has no dots), or `Value::Dict::FindListByDottedPath()`
// otherwise.
bool GetList(StringPiece path, const ListValue** out_value) const;
bool GetList(StringPiece path, ListValue** out_value);
// Like `Get()`, but without special treatment of '.'. This allows e.g. URLs
// to be used as paths.
// DEPRECATED, use `Value::FindDictKey(key)` instead.
bool GetDictionaryWithoutPathExpansion(
StringPiece key,
const DictionaryValue** out_value) const;
// DEPRECATED, use `Value::FindDictKey(key)` instead.
bool GetDictionaryWithoutPathExpansion(StringPiece key,
DictionaryValue** out_value);
// DEPRECATED, use `Value::FindListKey(key)` instead.
bool GetListWithoutPathExpansion(StringPiece key,
const ListValue** out_value) const;
// DEPRECATED, use `Value::FindListKey(key)` instead.
bool GetListWithoutPathExpansion(StringPiece key, ListValue** out_value);
// Makes a copy of `this` but doesn't include empty dictionaries and lists in
// the copy. This never returns NULL, even if `this` itself is empty.
std::unique_ptr<DictionaryValue> DeepCopyWithoutEmptyChildren() const;
// Swaps contents with the `other` dictionary.
void Swap(DictionaryValue* other);
// This class provides an iterator over both keys and values in the
// dictionary. It can't be used to modify the dictionary.
//
// DEPRECATED: Use a range-based for loop over `base::Value::Dict` directly
// instead.
class BASE_EXPORT Iterator {
public:
explicit Iterator(const DictionaryValue& target);
Iterator(const Iterator& other);
~Iterator();
bool IsAtEnd() const { return it_ == target_.DictItems().end(); }
void Advance() { ++it_; }
const std::string& key() const { return it_->first; }
const Value& value() const { return it_->second; }
private:
const DictionaryValue& target_;
detail::const_dict_iterator it_;
};
// DEPRECATED, use `Value::Dict::Clone()` instead.
// TODO(crbug.com/646113): Delete this and migrate callsites.
DictionaryValue* DeepCopy() const;
// DEPRECATED, use `Value::Dict::Clone()` instead.
// TODO(crbug.com/646113): Delete this and migrate callsites.
std::unique_ptr<DictionaryValue> CreateDeepCopy() const;
};
// This type of Value represents a list of other Value values.
//
// DEPRECATED: prefer `base::Value::List`.
class BASE_EXPORT ListValue : public Value {
public:
using const_iterator = ListView::const_iterator;
using iterator = ListView::iterator;
// Returns `value` if it is a list, nullptr otherwise.
static std::unique_ptr<ListValue> From(std::unique_ptr<Value> value);
ListValue();
explicit ListValue(span<const Value> in_list);
explicit ListValue(ListStorage&& in_list) noexcept;
// Convenience forms of `Get()`. Modifies `out_value` (and returns true)
// only if the index is valid and the Value at that index can be returned
// in the specified form.
// `out_value` is optional and will only be set if non-NULL.
//
// DEPRECATED: prefer `Value::List::operator[]` + `GetIfDict()`.
bool GetDictionary(size_t index, const DictionaryValue** out_value) const;
bool GetDictionary(size_t index, DictionaryValue** out_value);
// Appends a Value to the end of the list.
// DEPRECATED: prefer `Value::List::Append()`.
using Value::Append;
// DEPRECATED: prefer `Value::List::Append()`.
void Append(std::unique_ptr<Value> in_value);
// Swaps contents with the `other` list.
//
// DEPRECATED: prefer `base::Value::List` + `std::swap()`.
void Swap(ListValue* other);
// Iteration: Use a range-based for loop over `base::Value::List` directly
// instead.
};
// Adapter so `Value::Dict` or `Value::List` can be directly passed to JSON
// serialization methods without having to clone the contents and transfer
// ownership of the clone to a `Value` wrapper object.
//
// Like `StringPiece` and `span<T>`, this adapter does NOT retain ownership. Any
// underlying object that is passed by reference (i.e. `std::string`,
// `Value::BlobStorage`, `Value::Dict`, `Value::List`, or `Value`) MUST remain
// live as long as there is a `ValueView` referencing it.
//
// While it might be nice to just use the `absl::variant` type directly, the
// need to use `std::reference_wrapper` makes it clunky. `absl::variant` and
// `std::reference_wrapper` both support implicit construction, but C++ only
// allows at most one user-defined conversion in an implicit conversion
// sequence. If this adapter and its implicit constructors did not exist,
// callers would need to use `std::ref` or `std::cref` to pass `Value::Dict` or
// `Value::List` to a function with a `ValueView` parameter.
class BASE_EXPORT GSL_POINTER ValueView {
public:
ValueView(bool value) : data_view_(value) {}
ValueView(int value) : data_view_(value) {}
ValueView(double value)
: data_view_(absl::in_place_type_t<Value::DoubleStorage>(), value) {}
ValueView(const std::string& value) : data_view_(value) {}
ValueView(const Value::BlobStorage& value) : data_view_(value) {}
ValueView(const Value::Dict& value) : data_view_(value) {}
ValueView(const Value::List& value) : data_view_(value) {}
ValueView(const Value& value);
template <typename Visitor>
auto Visit(Visitor&& visitor) const {
return absl::visit(std::forward<Visitor>(visitor), data_view_);
}
private:
using ViewType =
absl::variant<absl::monostate,
bool,
int,
Value::DoubleStorage,
std::reference_wrapper<const std::string>,
std::reference_wrapper<const Value::BlobStorage>,
std::reference_wrapper<const Value::Dict>,
std::reference_wrapper<const Value::List>>;
ViewType data_view_;
};
// This interface is implemented by classes that know how to serialize
// Value objects.
class BASE_EXPORT ValueSerializer {
public:
virtual ~ValueSerializer();
virtual bool Serialize(ValueView root) = 0;
};
// This interface is implemented by classes that know how to deserialize Value
// objects.
class BASE_EXPORT ValueDeserializer {
public:
virtual ~ValueDeserializer();
// This method deserializes the subclass-specific format into a Value object.
// If the return value is non-NULL, the caller takes ownership of returned
// Value.
//
// If the return value is nullptr, and if `error_code` is non-nullptr,
// `*error_code` will be set to an integer value representing the underlying
// error. See "enum ErrorCode" below for more detail about the integer value.
//
// If `error_message` is non-nullptr, it will be filled in with a formatted
// error message including the location of the error if appropriate.
virtual std::unique_ptr<Value> Deserialize(int* error_code,
std::string* error_message) = 0;
// The integer-valued error codes form four groups:
// - The value 0 means no error.
// - Values between 1 and 999 inclusive mean an error in the data (i.e.
// content). The bytes being deserialized are not in the right format.
// - Values 1000 and above mean an error in the metadata (i.e. context). The
// file could not be read, the network is down, etc.
// - Negative values are reserved.
//
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum ErrorCode {
kErrorCodeNoError = 0,
// kErrorCodeInvalidFormat is a generic error code for "the data is not in
// the right format". Subclasses of ValueDeserializer may return other
// values for more specific errors.
kErrorCodeInvalidFormat = 1,
// kErrorCodeFirstMetadataError is the minimum value (inclusive) of the
// range of metadata errors.
kErrorCodeFirstMetadataError = 1000,
};
// The `error_code` argument can be one of the ErrorCode values, but it is
// not restricted to only being 0, 1 or 1000. Subclasses of ValueDeserializer
// can define their own error code values.
static inline bool ErrorCodeIsDataError(int error_code) {
return (kErrorCodeInvalidFormat <= error_code) &&
(error_code < kErrorCodeFirstMetadataError);
}
};
// Stream operator so Values can be pretty printed by gtest.
BASE_EXPORT std::ostream& operator<<(std::ostream& out, const Value& value);
BASE_EXPORT std::ostream& operator<<(std::ostream& out,
const Value::Dict& dict);
BASE_EXPORT std::ostream& operator<<(std::ostream& out,
const Value::List& list);
// Hints for DictionaryValue and ListValue; otherwise, gtest tends to prefer the
// default template implementation over an upcast to Value.
BASE_EXPORT inline std::ostream& operator<<(std::ostream& out,
const DictionaryValue& value) {
return out << static_cast<const Value&>(value);
}
BASE_EXPORT inline std::ostream& operator<<(std::ostream& out,
const ListValue& value) {
return out << static_cast<const Value&>(value);
}
// Stream operator so that enum class Types can be used in log statements.
BASE_EXPORT std::ostream& operator<<(std::ostream& out,
const Value::Type& type);
} // namespace base
#endif // BASE_VALUES_H_
|