blob: c34034df54269ed2bb426e78ce80b8f6dddda3e2 [file] [log] [blame]
// 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 "net/quic/core/quic_data_reader.h"
#include "net/base/int128.h"
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_packets.h"
#include "net/quic/platform/api/quic_endian.h"
namespace net {
QuicDataReader::QuicDataReader(const char* data, const size_t len)
: data_(data), len_(len), pos_(0) {}
bool QuicDataReader::ReadUInt16(uint16_t* result) {
return ReadBytes(result, sizeof(*result));
}
bool QuicDataReader::ReadUInt32(uint32_t* result) {
return ReadBytes(result, sizeof(*result));
}
bool QuicDataReader::ReadUInt64(uint64_t* result) {
return ReadBytes(result, sizeof(*result));
}
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;
DCHECK_GE(exponent, 1);
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;
DCHECK_GE(*result,
static_cast<uint64_t>(1 << kUFloat16MantissaEffectiveBits));
DCHECK_LE(*result, kUFloat16MaxValue);
return true;
}
bool QuicDataReader::ReadStringPiece16(QuicStringPiece* result) {
// Read resultant length.
uint16_t result_len;
if (!ReadUInt16(&result_len)) {
// OnFailure() already called.
return false;
}
return ReadStringPiece(result, result_len);
}
bool QuicDataReader::ReadStringPiece(QuicStringPiece* result, size_t size) {
// Make sure that we have enough data to read.
if (!CanRead(size)) {
OnFailure();
return false;
}
// Set result.
*result = QuicStringPiece(data_ + pos_, size);
// Iterate.
pos_ += size;
return true;
}
bool QuicDataReader::ReadConnectionId(uint64_t* connection_id) {
if (!ReadUInt64(connection_id)) {
return false;
}
if (FLAGS_quic_restart_flag_quic_big_endian_connection_id) {
*connection_id = QuicEndian::NetToHost64(*connection_id);
}
return true;
}
QuicStringPiece QuicDataReader::ReadRemainingPayload() {
QuicStringPiece payload = PeekRemainingPayload();
pos_ = len_;
return payload;
}
QuicStringPiece QuicDataReader::PeekRemainingPayload() {
return QuicStringPiece(data_ + pos_, len_ - pos_);
}
bool QuicDataReader::ReadBytes(void* result, size_t size) {
// Make sure that we have enough data to read.
if (!CanRead(size)) {
OnFailure();
return false;
}
// Read into result.
memcpy(result, data_ + pos_, size);
// Iterate.
pos_ += size;
return true;
}
bool QuicDataReader::IsDoneReading() const {
return len_ == pos_;
}
size_t QuicDataReader::BytesRemaining() const {
return len_ - pos_;
}
bool QuicDataReader::CanRead(size_t bytes) const {
return bytes <= (len_ - pos_);
}
void QuicDataReader::OnFailure() {
// Set our iterator to the end of the buffer so that further reads fail
// immediately.
pos_ = len_;
}
} // namespace net