| // 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. |
| |
| #include "quiche/quic/core/quic_data_reader.h" |
| |
| #include "absl/strings/string_view.h" |
| #include "quiche/quic/core/quic_packets.h" |
| #include "quiche/quic/core/quic_utils.h" |
| #include "quiche/quic/platform/api/quic_bug_tracker.h" |
| #include "quiche/quic/platform/api/quic_flags.h" |
| #include "quiche/common/quiche_endian.h" |
| |
| namespace quic { |
| |
| QuicDataReader::QuicDataReader(absl::string_view data) |
| : quiche::QuicheDataReader(data) {} |
| |
| QuicDataReader::QuicDataReader(const char* data, const size_t len) |
| : QuicDataReader(data, len, quiche::NETWORK_BYTE_ORDER) {} |
| |
| QuicDataReader::QuicDataReader(const char* data, const size_t len, |
| quiche::Endianness endianness) |
| : quiche::QuicheDataReader(data, len, endianness) {} |
| |
| bool QuicDataReader::ReadUFloat16(uint64_t* result) { |
| uint16_t value; |
| if (!ReadUInt16(&value)) { |
| return false; |
| } |
| |
| *result = value; |
| if (*result < (1 << kUFloat16MantissaEffectiveBits)) { |
| // Fast path: either the value is denormalized (no hidden bit), or |
| // normalized (hidden bit set, exponent offset by one) with exponent zero. |
| // Zero exponent offset by one sets the bit exactly where the hidden bit is. |
| // So in both cases the value encodes itself. |
| return true; |
| } |
| |
| uint16_t exponent = |
| value >> kUFloat16MantissaBits; // No sign extend on uint! |
| // After the fast pass, the exponent is at least one (offset by one). |
| // Un-offset the exponent. |
| --exponent; |
| QUICHE_DCHECK_GE(exponent, 1); |
| QUICHE_DCHECK_LE(exponent, kUFloat16MaxExponent); |
| // Here we need to clear the exponent and set the hidden bit. We have already |
| // decremented the exponent, so when we subtract it, it leaves behind the |
| // hidden bit. |
| *result -= exponent << kUFloat16MantissaBits; |
| *result <<= exponent; |
| QUICHE_DCHECK_GE(*result, |
| static_cast<uint64_t>(1 << kUFloat16MantissaEffectiveBits)); |
| QUICHE_DCHECK_LE(*result, kUFloat16MaxValue); |
| return true; |
| } |
| |
| bool QuicDataReader::ReadConnectionId(QuicConnectionId* connection_id, |
| uint8_t length) { |
| if (length == 0) { |
| connection_id->set_length(0); |
| return true; |
| } |
| |
| if (BytesRemaining() < length) { |
| return false; |
| } |
| |
| connection_id->set_length(length); |
| const bool ok = |
| ReadBytes(connection_id->mutable_data(), connection_id->length()); |
| QUICHE_DCHECK(ok); |
| return ok; |
| } |
| |
| bool QuicDataReader::ReadLengthPrefixedConnectionId( |
| QuicConnectionId* connection_id) { |
| uint8_t connection_id_length; |
| if (!ReadUInt8(&connection_id_length)) { |
| return false; |
| } |
| return ReadConnectionId(connection_id, connection_id_length); |
| } |
| |
| #undef ENDPOINT // undef for jumbo builds |
| } // namespace quic |