// 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/quic_data_reader.h" #include "net/base/int128.h" #include "net/quic/quic_protocol.h" using base::StringPiece; namespace net { QuicDataReader::QuicDataReader(const char* data, const size_t len) : data_(data), len_(len), pos_(0) { } bool QuicDataReader::ReadUInt16(uint16* result) { return ReadBytes(result, sizeof(*result)); } bool QuicDataReader::ReadUInt32(uint32* result) { return ReadBytes(result, sizeof(*result)); } bool QuicDataReader::ReadUInt64(uint64* result) { return ReadBytes(result, sizeof(*result)); } bool QuicDataReader::ReadUFloat16(uint64* result) { uint16 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 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(value, 1 << kUFloat16MantissaEffectiveBits); DCHECK_LE(value, kUFloat16MaxValue); return true; } bool QuicDataReader::ReadStringPiece16(StringPiece* result) { // Read resultant length. uint16 result_len; if (!ReadUInt16(&result_len)) { // OnFailure() already called. return false; } return ReadStringPiece(result, result_len); } bool QuicDataReader::ReadStringPiece(StringPiece* result, size_t size) { // Make sure that we have enough data to read. if (!CanRead(size)) { OnFailure(); return false; } // Set result. result->set(data_ + pos_, size); // Iterate. pos_ += size; return true; } StringPiece QuicDataReader::ReadRemainingPayload() { StringPiece payload = PeekRemainingPayload(); pos_ = len_; return payload; } StringPiece QuicDataReader::PeekRemainingPayload() { return StringPiece(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