|  | // Copyright 2017 The Chromium Authors | 
|  | // 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 <string_view> | 
|  | #include <tuple> | 
|  | #include <vector> | 
|  |  | 
|  | #include "base/check.h" | 
|  | #include "base/containers/flat_map.h" | 
|  | #include "base/containers/span.h" | 
|  | #include "base/notreached.h" | 
|  | #include "components/cbor/cbor_export.h" | 
|  |  | 
|  | namespace cbor { | 
|  |  | 
|  | // A class for Concise Binary Object Representation (CBOR) values. | 
|  | // This does not support 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(crbug.com/40560917): 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(); | 
|  | } | 
|  |  | 
|  | 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, | 
|  | // In CBOR floating types also have major type 7, but we separate them here | 
|  | // for simplicity. | 
|  | FLOAT_VALUE = 70, | 
|  | 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(std::string_view 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(double in_float); | 
|  |  | 
|  | 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(std::string_view 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(const Value&) = delete; | 
|  | Value& operator=(const Value&) = delete; | 
|  |  | 
|  | ~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_double() const { return type() == Type::FLOAT_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; | 
|  | double GetDouble() const; | 
|  | const int64_t& GetInteger() const; | 
|  | const int64_t& GetUnsigned() const; | 
|  | const int64_t& GetNegative() const; | 
|  | const BinaryValue& GetBytestring() const; | 
|  | std::string_view 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_; | 
|  | double float_value_; | 
|  | BinaryValue bytestring_value_; | 
|  | std::string string_value_; | 
|  | ArrayValue array_value_; | 
|  | MapValue map_value_; | 
|  | }; | 
|  |  | 
|  | void InternalMoveConstructFrom(Value&& that); | 
|  | void InternalCleanup(); | 
|  | }; | 
|  |  | 
|  | }  // namespace cbor | 
|  |  | 
|  | #endif  // COMPONENTS_CBOR_VALUES_H_ |