forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
values.h
215 lines (180 loc) · 7.14 KB
/
values.h
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
// Copyright 2017 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 COMPONENTS_CBOR_VALUES_H_
#define COMPONENTS_CBOR_VALUES_H_
#include <stdint.h>
#include <string>
#include <tuple>
#include <vector>
#include "base/check.h"
#include "base/containers/flat_map.h"
#include "base/containers/span.h"
#include "base/macros.h"
#include "base/notreached.h"
#include "base/strings/string_piece.h"
#include "components/cbor/cbor_export.h"
namespace cbor {
// A class for Concise Binary Object Representation (CBOR) values.
// This does not support:
// * Floating-point numbers.
// * Indefinite-length encodings.
class CBOR_EXPORT Value {
public:
struct Less {
// Comparison predicate to order keys in a dictionary as required by the
// canonical CBOR order defined in
// https://tools.ietf.org/html/rfc7049#section-3.9
// TODO(808022): Clarify where this stands.
bool operator()(const Value& a, const Value& b) const {
// The current implementation only supports integer, text string, byte
// string and invalid UTF8 keys.
DCHECK((a.is_integer() || a.is_string() || a.is_bytestring() ||
a.is_invalid_utf8()) &&
(b.is_integer() || b.is_string() || b.is_bytestring() ||
b.is_invalid_utf8()));
// Below text from https://tools.ietf.org/html/rfc7049 errata 4409:
// * If the major types are different, the one with the lower value
// in numerical order sorts earlier.
if (a.type() != b.type())
return a.type() < b.type();
// * If two keys have different lengths, the shorter one sorts
// earlier;
// * If two keys have the same length, the one with the lower value
// in (byte-wise) lexical order sorts earlier.
switch (a.type()) {
case Type::UNSIGNED:
// For unsigned integers, the smaller value has shorter length,
// and (byte-wise) lexical representation.
return a.GetInteger() < b.GetInteger();
case Type::NEGATIVE:
// For negative integers, the value closer to zero has shorter length,
// and (byte-wise) lexical representation.
return a.GetInteger() > b.GetInteger();
case Type::STRING: {
const auto& a_str = a.GetString();
const size_t a_length = a_str.size();
const auto& b_str = b.GetString();
const size_t b_length = b_str.size();
return std::tie(a_length, a_str) < std::tie(b_length, b_str);
}
case Type::BYTE_STRING: {
const auto& a_str = a.GetBytestring();
const size_t a_length = a_str.size();
const auto& b_str = b.GetBytestring();
const size_t b_length = b_str.size();
return std::tie(a_length, a_str) < std::tie(b_length, b_str);
}
case Type::INVALID_UTF8: {
const auto& a_str = a.GetInvalidUTF8();
const size_t a_length = a_str.size();
const auto& b_str = b.GetInvalidUTF8();
const size_t b_length = b_str.size();
return std::tie(a_length, a_str) < std::tie(b_length, b_str);
}
default:
break;
}
NOTREACHED();
return false;
}
using is_transparent = void;
};
using BinaryValue = std::vector<uint8_t>;
using ArrayValue = std::vector<Value>;
using MapValue = base::flat_map<Value, Value, Less>;
enum class Type {
UNSIGNED = 0,
NEGATIVE = 1,
BYTE_STRING = 2,
STRING = 3,
ARRAY = 4,
MAP = 5,
TAG = 6,
SIMPLE_VALUE = 7,
NONE = -1,
INVALID_UTF8 = -2,
};
enum class SimpleValue {
FALSE_VALUE = 20,
TRUE_VALUE = 21,
NULL_VALUE = 22,
UNDEFINED = 23,
};
// Returns a Value with Type::INVALID_UTF8. This factory method lets tests
// encode such a value as a CBOR string. It should never be used outside of
// tests since encoding may yield invalid CBOR data.
static Value InvalidUTF8StringValueForTesting(base::StringPiece in_string);
Value(Value&& that) noexcept;
Value() noexcept; // A NONE value.
explicit Value(Type type);
explicit Value(SimpleValue in_simple);
explicit Value(bool boolean_value);
explicit Value(int integer_value);
explicit Value(int64_t integer_value);
explicit Value(uint64_t integer_value) = delete;
explicit Value(base::span<const uint8_t> in_bytes);
explicit Value(BinaryValue&& in_bytes) noexcept;
explicit Value(const char* in_string, Type type = Type::STRING);
explicit Value(std::string&& in_string, Type type = Type::STRING) noexcept;
explicit Value(base::StringPiece in_string, Type type = Type::STRING);
explicit Value(const ArrayValue& in_array);
explicit Value(ArrayValue&& in_array) noexcept;
explicit Value(const MapValue& in_map);
explicit Value(MapValue&& in_map) noexcept;
Value& operator=(Value&& that) noexcept;
~Value();
// Value's copy constructor and copy assignment operator are deleted.
// Use this to obtain a deep copy explicitly.
Value Clone() const;
// Returns the type of the value stored by the current Value object.
Type type() const { return type_; }
// Returns true if the current object represents a given type.
bool is_type(Type type) const { return type == type_; }
bool is_none() const { return type() == Type::NONE; }
bool is_invalid_utf8() const { return type() == Type::INVALID_UTF8; }
bool is_simple() const { return type() == Type::SIMPLE_VALUE; }
bool is_bool() const {
return is_simple() && (simple_value_ == SimpleValue::TRUE_VALUE ||
simple_value_ == SimpleValue::FALSE_VALUE);
}
bool is_unsigned() const { return type() == Type::UNSIGNED; }
bool is_negative() const { return type() == Type::NEGATIVE; }
bool is_integer() const { return is_unsigned() || is_negative(); }
bool is_bytestring() const { return type() == Type::BYTE_STRING; }
bool is_string() const { return type() == Type::STRING; }
bool is_array() const { return type() == Type::ARRAY; }
bool is_map() const { return type() == Type::MAP; }
// These will all fatally assert if the type doesn't match.
SimpleValue GetSimpleValue() const;
bool GetBool() const;
const int64_t& GetInteger() const;
const int64_t& GetUnsigned() const;
const int64_t& GetNegative() const;
const BinaryValue& GetBytestring() const;
base::StringPiece GetBytestringAsString() const;
// Returned string may contain NUL characters.
const std::string& GetString() const;
const ArrayValue& GetArray() const;
const MapValue& GetMap() const;
const BinaryValue& GetInvalidUTF8() const;
private:
friend class Reader;
// This constructor allows INVALID_UTF8 values to be created, which only
// |Reader| and InvalidUTF8StringValueForTesting() may do.
Value(base::span<const uint8_t> in_bytes, Type type);
Type type_;
union {
SimpleValue simple_value_;
int64_t integer_value_;
BinaryValue bytestring_value_;
std::string string_value_;
ArrayValue array_value_;
MapValue map_value_;
};
void InternalMoveConstructFrom(Value&& that);
void InternalCleanup();
DISALLOW_COPY_AND_ASSIGN(Value);
};
} // namespace cbor
#endif // COMPONENTS_CBOR_VALUES_H_