| // 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. |
| |
| #include "components/cbor/values.h" |
| |
| #include <new> |
| #include <utility> |
| |
| #include "base/numerics/safe_conversions.h" |
| #include "base/strings/string_util.h" |
| #include "components/cbor/constants.h" |
| |
| namespace cbor { |
| |
| Value::Value() noexcept : type_(Type::NONE) {} |
| |
| Value::Value(Value&& that) noexcept { |
| InternalMoveConstructFrom(std::move(that)); |
| } |
| |
| Value::Value(Type type) : type_(type) { |
| // Initialize with the default value. |
| switch (type_) { |
| case Type::UNSIGNED: |
| case Type::NEGATIVE: |
| integer_value_ = 0; |
| return; |
| case Type::BYTE_STRING: |
| new (&bytestring_value_) BinaryValue(); |
| return; |
| case Type::STRING: |
| new (&string_value_) std::string(); |
| return; |
| case Type::ARRAY: |
| new (&array_value_) ArrayValue(); |
| return; |
| case Type::MAP: |
| new (&map_value_) MapValue(); |
| return; |
| case Type::TAG: |
| NOTREACHED() << constants::kUnsupportedMajorType; |
| return; |
| case Type::SIMPLE_VALUE: |
| simple_value_ = Value::SimpleValue::UNDEFINED; |
| return; |
| case Type::NONE: |
| return; |
| } |
| NOTREACHED(); |
| } |
| |
| Value::Value(SimpleValue in_simple) |
| : type_(Type::SIMPLE_VALUE), simple_value_(in_simple) { |
| CHECK(static_cast<int>(in_simple) >= 20 && static_cast<int>(in_simple) <= 23); |
| } |
| |
| Value::Value(bool boolean_value) : type_(Type::SIMPLE_VALUE) { |
| simple_value_ = boolean_value ? Value::SimpleValue::TRUE_VALUE |
| : Value::SimpleValue::FALSE_VALUE; |
| } |
| |
| Value::Value(int integer_value) |
| : Value(base::checked_cast<int64_t>(integer_value)) {} |
| |
| Value::Value(int64_t integer_value) : integer_value_(integer_value) { |
| type_ = integer_value >= 0 ? Type::UNSIGNED : Type::NEGATIVE; |
| } |
| |
| Value::Value(base::span<const uint8_t> in_bytes) |
| : type_(Type::BYTE_STRING), |
| bytestring_value_(in_bytes.begin(), in_bytes.end()) {} |
| |
| Value::Value(BinaryValue&& in_bytes) noexcept |
| : type_(Type::BYTE_STRING), bytestring_value_(std::move(in_bytes)) {} |
| |
| Value::Value(const char* in_string, Type type) |
| : Value(base::StringPiece(in_string), type) {} |
| |
| Value::Value(std::string&& in_string, Type type) noexcept : type_(type) { |
| switch (type_) { |
| case Type::STRING: |
| new (&string_value_) std::string(); |
| string_value_ = std::move(in_string); |
| DCHECK(base::IsStringUTF8(string_value_)); |
| break; |
| case Type::BYTE_STRING: |
| new (&bytestring_value_) BinaryValue(); |
| bytestring_value_ = BinaryValue(in_string.begin(), in_string.end()); |
| break; |
| default: |
| NOTREACHED(); |
| } |
| } |
| |
| Value::Value(base::StringPiece in_string, Type type) : type_(type) { |
| switch (type_) { |
| case Type::STRING: |
| new (&string_value_) std::string(); |
| string_value_ = in_string.as_string(); |
| DCHECK(base::IsStringUTF8(string_value_)); |
| break; |
| case Type::BYTE_STRING: |
| new (&bytestring_value_) BinaryValue(); |
| bytestring_value_ = BinaryValue(in_string.begin(), in_string.end()); |
| break; |
| default: |
| NOTREACHED(); |
| } |
| } |
| |
| Value::Value(const ArrayValue& in_array) : type_(Type::ARRAY), array_value_() { |
| array_value_.reserve(in_array.size()); |
| for (const auto& val : in_array) |
| array_value_.emplace_back(val.Clone()); |
| } |
| |
| Value::Value(ArrayValue&& in_array) noexcept |
| : type_(Type::ARRAY), array_value_(std::move(in_array)) {} |
| |
| Value::Value(const MapValue& in_map) : type_(Type::MAP), map_value_() { |
| map_value_.reserve(in_map.size()); |
| for (const auto& it : in_map) |
| map_value_.emplace_hint(map_value_.end(), it.first.Clone(), |
| it.second.Clone()); |
| } |
| |
| Value::Value(MapValue&& in_map) noexcept |
| : type_(Type::MAP), map_value_(std::move(in_map)) {} |
| |
| Value& Value::operator=(Value&& that) noexcept { |
| InternalCleanup(); |
| InternalMoveConstructFrom(std::move(that)); |
| |
| return *this; |
| } |
| |
| Value::~Value() { |
| InternalCleanup(); |
| } |
| |
| Value Value::Clone() const { |
| switch (type_) { |
| case Type::NONE: |
| return Value(); |
| case Type::UNSIGNED: |
| case Type::NEGATIVE: |
| return Value(integer_value_); |
| case Type::BYTE_STRING: |
| return Value(bytestring_value_); |
| case Type::STRING: |
| return Value(string_value_); |
| case Type::ARRAY: |
| return Value(array_value_); |
| case Type::MAP: |
| return Value(map_value_); |
| case Type::TAG: |
| NOTREACHED() << constants::kUnsupportedMajorType; |
| return Value(); |
| case Type::SIMPLE_VALUE: |
| return Value(simple_value_); |
| } |
| |
| NOTREACHED(); |
| return Value(); |
| } |
| |
| Value::SimpleValue Value::GetSimpleValue() const { |
| CHECK(is_simple()); |
| return simple_value_; |
| } |
| |
| bool Value::GetBool() const { |
| CHECK(is_bool()); |
| return simple_value_ == SimpleValue::TRUE_VALUE; |
| } |
| |
| const int64_t& Value::GetInteger() const { |
| CHECK(is_integer()); |
| return integer_value_; |
| } |
| |
| const int64_t& Value::GetUnsigned() const { |
| CHECK(is_unsigned()); |
| CHECK_GE(integer_value_, 0); |
| return integer_value_; |
| } |
| |
| const int64_t& Value::GetNegative() const { |
| CHECK(is_negative()); |
| CHECK_LT(integer_value_, 0); |
| return integer_value_; |
| } |
| |
| const std::string& Value::GetString() const { |
| CHECK(is_string()); |
| return string_value_; |
| } |
| |
| const Value::BinaryValue& Value::GetBytestring() const { |
| CHECK(is_bytestring()); |
| return bytestring_value_; |
| } |
| |
| base::StringPiece Value::GetBytestringAsString() const { |
| CHECK(is_bytestring()); |
| const auto& bytestring_value = GetBytestring(); |
| return base::StringPiece( |
| reinterpret_cast<const char*>(bytestring_value.data()), |
| bytestring_value.size()); |
| } |
| |
| const Value::ArrayValue& Value::GetArray() const { |
| CHECK(is_array()); |
| return array_value_; |
| } |
| |
| const Value::MapValue& Value::GetMap() const { |
| CHECK(is_map()); |
| return map_value_; |
| } |
| |
| void Value::InternalMoveConstructFrom(Value&& that) { |
| type_ = that.type_; |
| |
| switch (type_) { |
| case Type::UNSIGNED: |
| case Type::NEGATIVE: |
| integer_value_ = that.integer_value_; |
| return; |
| case Type::BYTE_STRING: |
| new (&bytestring_value_) BinaryValue(std::move(that.bytestring_value_)); |
| return; |
| case Type::STRING: |
| new (&string_value_) std::string(std::move(that.string_value_)); |
| return; |
| case Type::ARRAY: |
| new (&array_value_) ArrayValue(std::move(that.array_value_)); |
| return; |
| case Type::MAP: |
| new (&map_value_) MapValue(std::move(that.map_value_)); |
| return; |
| case Type::TAG: |
| NOTREACHED() << constants::kUnsupportedMajorType; |
| return; |
| case Type::SIMPLE_VALUE: |
| simple_value_ = that.simple_value_; |
| return; |
| case Type::NONE: |
| return; |
| } |
| NOTREACHED(); |
| } |
| |
| void Value::InternalCleanup() { |
| switch (type_) { |
| case Type::BYTE_STRING: |
| bytestring_value_.~BinaryValue(); |
| break; |
| case Type::STRING: |
| string_value_.~basic_string(); |
| break; |
| case Type::ARRAY: |
| array_value_.~ArrayValue(); |
| break; |
| case Type::MAP: |
| map_value_.~MapValue(); |
| break; |
| case Type::TAG: |
| NOTREACHED() << constants::kUnsupportedMajorType; |
| break; |
| case Type::NONE: |
| case Type::UNSIGNED: |
| case Type::NEGATIVE: |
| case Type::SIMPLE_VALUE: |
| break; |
| } |
| type_ = Type::NONE; |
| } |
| |
| } // namespace cbor |