blob: abed152004a2a682d1f37b6036de6226b6ff58a4 [file] [log] [blame]
Kim Paulhamus6efcf4952017-09-14 22:46:271// Copyright 2017 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
Jun Choi9f1446c02017-12-21 23:33:275#ifndef COMPONENTS_CBOR_CBOR_VALUES_H_
6#define COMPONENTS_CBOR_CBOR_VALUES_H_
Kim Paulhamus6efcf4952017-09-14 22:46:277
Jun Choi06ae32d2017-12-21 18:52:398#include <stdint.h>
Jun Choi7b6fbff2018-01-22 19:54:019
Kim Paulhamus6efcf4952017-09-14 22:46:2710#include <string>
Adam Langley68672fd2017-10-17 19:35:2711#include <tuple>
Kim Paulhamus6efcf4952017-09-14 22:46:2712#include <vector>
13
14#include "base/containers/flat_map.h"
jdoerrieb5384422018-06-14 21:22:1915#include "base/containers/span.h"
Kim Paulhamus6efcf4952017-09-14 22:46:2716#include "base/macros.h"
Adam Langleydf763d792017-11-28 19:20:1517#include "base/strings/string_piece.h"
Jun Choi9f1446c02017-12-21 23:33:2718#include "components/cbor/cbor_export.h"
Kim Paulhamus6efcf4952017-09-14 22:46:2719
Jun Choi9f1446c02017-12-21 23:33:2720namespace cbor {
Kim Paulhamus6efcf4952017-09-14 22:46:2721
22// A class for Concise Binary Object Representation (CBOR) values.
23// This does not support:
Kim Paulhamus6efcf4952017-09-14 22:46:2724// * Floating-point numbers.
25// * Indefinite-length encodings.
Adam Langleyb4f12f92018-10-26 21:00:0226class CBOR_EXPORT Value {
Kim Paulhamus6efcf4952017-09-14 22:46:2727 public:
Kouhei Ueno6d1629e2018-02-01 17:28:0328 struct Less {
Adam Langley68672fd2017-10-17 19:35:2729 // Comparison predicate to order keys in a dictionary as required by the
Kouhei Ueno6d1629e2018-02-01 17:28:0330 // canonical CBOR order defined in
31 // https://tools.ietf.org/html/rfc7049#section-3.9
32 // TODO(808022): Clarify where this stands.
Adam Langleyb4f12f92018-10-26 21:00:0233 bool operator()(const Value& a, const Value& b) const {
Kouhei Ueno6d1629e2018-02-01 17:28:0334 // The current implementation only supports integer, text string,
35 // and byte string keys.
36 DCHECK((a.is_integer() || a.is_string() || a.is_bytestring()) &&
37 (b.is_integer() || b.is_string() || b.is_bytestring()));
38
39 // Below text from https://tools.ietf.org/html/rfc7049 errata 4409:
40 // * If the major types are different, the one with the lower value
41 // in numerical order sorts earlier.
Jun Choi98a59e462017-12-14 23:04:0942 if (a.type() != b.type())
43 return a.type() < b.type();
Kouhei Ueno6d1629e2018-02-01 17:28:0344
45 // * If two keys have different lengths, the shorter one sorts
46 // earlier;
47 // * If two keys have the same length, the one with the lower value
48 // in (byte-wise) lexical order sorts earlier.
Jun Choi98a59e462017-12-14 23:04:0949 switch (a.type()) {
50 case Type::UNSIGNED:
Kouhei Ueno6d1629e2018-02-01 17:28:0351 // For unsigned integers, the smaller value has shorter length,
52 // and (byte-wise) lexical representation.
Jun Choi06ae32d2017-12-21 18:52:3953 return a.GetInteger() < b.GetInteger();
54 case Type::NEGATIVE:
Kouhei Ueno6d1629e2018-02-01 17:28:0355 // For negative integers, the value closer to zero has shorter length,
56 // and (byte-wise) lexical representation.
Jun Choi06ae32d2017-12-21 18:52:3957 return a.GetInteger() > b.GetInteger();
Jun Choi98a59e462017-12-14 23:04:0958 case Type::STRING: {
59 const auto& a_str = a.GetString();
60 const size_t a_length = a_str.size();
61 const auto& b_str = b.GetString();
62 const size_t b_length = b_str.size();
63 return std::tie(a_length, a_str) < std::tie(b_length, b_str);
64 }
Kouhei Ueno6d1629e2018-02-01 17:28:0365 case Type::BYTE_STRING: {
66 const auto& a_str = a.GetBytestring();
67 const size_t a_length = a_str.size();
68 const auto& b_str = b.GetBytestring();
69 const size_t b_length = b_str.size();
70 return std::tie(a_length, a_str) < std::tie(b_length, b_str);
71 }
Jun Choi98a59e462017-12-14 23:04:0972 default:
73 break;
74 }
75
76 NOTREACHED();
77 return false;
Adam Langley68672fd2017-10-17 19:35:2778 }
79
Adam Langley68672fd2017-10-17 19:35:2780 using is_transparent = void;
81 };
82
Kim Paulhamus6efcf4952017-09-14 22:46:2783 using BinaryValue = std::vector<uint8_t>;
Adam Langleyb4f12f92018-10-26 21:00:0284 using ArrayValue = std::vector<Value>;
85 using MapValue = base::flat_map<Value, Value, Less>;
Kim Paulhamus6efcf4952017-09-14 22:46:2786
87 enum class Type {
Jun Choi6d30c4a2017-12-09 01:10:3288 UNSIGNED = 0,
Jun Choi06ae32d2017-12-21 18:52:3989 NEGATIVE = 1,
Jun Choi6d30c4a2017-12-09 01:10:3290 BYTE_STRING = 2,
91 STRING = 3,
92 ARRAY = 4,
93 MAP = 5,
Chris Palmerbe2d8dc2018-09-14 00:31:4294 TAG = 6,
Jun Choi07540c62017-12-21 02:51:4395 SIMPLE_VALUE = 7,
Jun Choi6d30c4a2017-12-09 01:10:3296 NONE = -1,
Kim Paulhamus6efcf4952017-09-14 22:46:2797 };
98
Jun Choi07540c62017-12-21 02:51:4399 enum class SimpleValue {
100 FALSE_VALUE = 20,
101 TRUE_VALUE = 21,
102 NULL_VALUE = 22,
103 UNDEFINED = 23,
104 };
105
Adam Langleyb4f12f92018-10-26 21:00:02106 Value(Value&& that) noexcept;
107 Value() noexcept; // A NONE value.
Kim Paulhamus6efcf4952017-09-14 22:46:27108
Adam Langleyb4f12f92018-10-26 21:00:02109 explicit Value(Type type);
Jun Choi7b6fbff2018-01-22 19:54:01110
Adam Langleyb4f12f92018-10-26 21:00:02111 explicit Value(SimpleValue in_simple);
112 explicit Value(bool boolean_value);
Jun Choi7b6fbff2018-01-22 19:54:01113
Adam Langleyb4f12f92018-10-26 21:00:02114 explicit Value(int integer_value);
115 explicit Value(int64_t integer_value);
116 explicit Value(uint64_t integer_value) = delete;
Kim Paulhamus6efcf4952017-09-14 22:46:27117
Adam Langleyb4f12f92018-10-26 21:00:02118 explicit Value(base::span<const uint8_t> in_bytes);
119 explicit Value(BinaryValue&& in_bytes) noexcept;
Kim Paulhamus6efcf4952017-09-14 22:46:27120
Adam Langleyb4f12f92018-10-26 21:00:02121 explicit Value(const char* in_string, Type type = Type::STRING);
122 explicit Value(std::string&& in_string, Type type = Type::STRING) noexcept;
123 explicit Value(base::StringPiece in_string, Type type = Type::STRING);
Kim Paulhamus6efcf4952017-09-14 22:46:27124
Adam Langleyb4f12f92018-10-26 21:00:02125 explicit Value(const ArrayValue& in_array);
126 explicit Value(ArrayValue&& in_array) noexcept;
Kim Paulhamus6efcf4952017-09-14 22:46:27127
Adam Langleyb4f12f92018-10-26 21:00:02128 explicit Value(const MapValue& in_map);
129 explicit Value(MapValue&& in_map) noexcept;
Kim Paulhamus6efcf4952017-09-14 22:46:27130
Adam Langleyb4f12f92018-10-26 21:00:02131 Value& operator=(Value&& that) noexcept;
Kim Paulhamus6efcf4952017-09-14 22:46:27132
Adam Langleyb4f12f92018-10-26 21:00:02133 ~Value();
Kim Paulhamus6efcf4952017-09-14 22:46:27134
Adam Langleyb4f12f92018-10-26 21:00:02135 // Value's copy constructor and copy assignment operator are deleted.
Kim Paulhamus6efcf4952017-09-14 22:46:27136 // Use this to obtain a deep copy explicitly.
Adam Langleyb4f12f92018-10-26 21:00:02137 Value Clone() const;
Kim Paulhamus6efcf4952017-09-14 22:46:27138
139 // Returns the type of the value stored by the current Value object.
140 Type type() const { return type_; }
141
142 // Returns true if the current object represents a given type.
143 bool is_type(Type type) const { return type == type_; }
144 bool is_none() const { return type() == Type::NONE; }
Jun Choi7b6fbff2018-01-22 19:54:01145 bool is_simple() const { return type() == Type::SIMPLE_VALUE; }
146 bool is_bool() const {
147 return is_simple() && (simple_value_ == SimpleValue::TRUE_VALUE ||
148 simple_value_ == SimpleValue::FALSE_VALUE);
149 }
Kim Paulhamus6efcf4952017-09-14 22:46:27150 bool is_unsigned() const { return type() == Type::UNSIGNED; }
Jun Choi06ae32d2017-12-21 18:52:39151 bool is_negative() const { return type() == Type::NEGATIVE; }
152 bool is_integer() const { return is_unsigned() || is_negative(); }
Jun Choi6d30c4a2017-12-09 01:10:32153 bool is_bytestring() const { return type() == Type::BYTE_STRING; }
Kim Paulhamus6efcf4952017-09-14 22:46:27154 bool is_string() const { return type() == Type::STRING; }
155 bool is_array() const { return type() == Type::ARRAY; }
156 bool is_map() const { return type() == Type::MAP; }
157
158 // These will all fatally assert if the type doesn't match.
Jun Choi07540c62017-12-21 02:51:43159 SimpleValue GetSimpleValue() const;
Jun Choi7b6fbff2018-01-22 19:54:01160 bool GetBool() const;
Jun Choi06ae32d2017-12-21 18:52:39161 const int64_t& GetInteger() const;
162 const int64_t& GetUnsigned() const;
163 const int64_t& GetNegative() const;
Kim Paulhamus6efcf4952017-09-14 22:46:27164 const BinaryValue& GetBytestring() const;
Kouhei Uenoc12b0b92018-02-01 14:02:10165 base::StringPiece GetBytestringAsString() const;
Jun Choi47be22c2017-12-14 07:55:16166 // Returned string may contain NUL characters.
Kim Paulhamus6efcf4952017-09-14 22:46:27167 const std::string& GetString() const;
168 const ArrayValue& GetArray() const;
169 const MapValue& GetMap() const;
170
171 private:
172 Type type_;
173
174 union {
Jun Choi07540c62017-12-21 02:51:43175 SimpleValue simple_value_;
Jun Choi06ae32d2017-12-21 18:52:39176 int64_t integer_value_;
Daniel Cheng9eb43fd342017-10-10 21:28:37177 BinaryValue bytestring_value_;
178 std::string string_value_;
179 ArrayValue array_value_;
180 MapValue map_value_;
Kim Paulhamus6efcf4952017-09-14 22:46:27181 };
182
Adam Langleyb4f12f92018-10-26 21:00:02183 void InternalMoveConstructFrom(Value&& that);
Kim Paulhamus6efcf4952017-09-14 22:46:27184 void InternalCleanup();
185
Adam Langleyb4f12f92018-10-26 21:00:02186 DISALLOW_COPY_AND_ASSIGN(Value);
Kim Paulhamus6efcf4952017-09-14 22:46:27187};
Jun Choi9f1446c02017-12-21 23:33:27188} // namespace cbor
Kim Paulhamus6efcf4952017-09-14 22:46:27189
Jun Choi9f1446c02017-12-21 23:33:27190#endif // COMPONENTS_CBOR_CBOR_VALUES_H_