1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/quic/quic_data_reader.h"
6
7#include "net/base/int128.h"
8#include "net/quic/quic_protocol.h"
9
10using base::StringPiece;
11
12namespace net {
13
14QuicDataReader::QuicDataReader(const char* data, const size_t len)
15    : data_(data),
16      len_(len),
17      pos_(0) {
18}
19
20bool QuicDataReader::ReadUInt16(uint16* result) {
21  return ReadBytes(result, sizeof(*result));
22}
23
24bool QuicDataReader::ReadUInt32(uint32* result) {
25  return ReadBytes(result, sizeof(*result));
26}
27
28bool QuicDataReader::ReadUInt48(uint64* result) {
29  uint32 lo;
30  if (!ReadUInt32(&lo)) {
31    return false;
32  }
33
34  uint16 hi;
35  if (!ReadUInt16(&hi)) {
36    return false;
37  }
38
39  *result = hi;
40  *result <<= 32;
41  *result += lo;
42
43  return true;
44}
45
46bool QuicDataReader::ReadUInt64(uint64* result) {
47  return ReadBytes(result, sizeof(*result));
48}
49
50bool QuicDataReader::ReadUInt128(uint128* result) {
51  uint64 high_hash;
52  uint64 low_hash;
53
54  if (!ReadUInt64(&low_hash)) {
55    return false;
56  }
57  if (!ReadUInt64(&high_hash)) {
58    return false;
59  }
60
61  *result = uint128(high_hash, low_hash);
62  return true;
63}
64
65bool QuicDataReader::ReadUFloat16(uint64* result) {
66  uint16 value;
67  if (!ReadUInt16(&value)) {
68    return false;
69  }
70
71  *result = value;
72  if (*result < (1 << kUFloat16MantissaEffectiveBits)) {
73    // Fast path: either the value is denormalized (no hidden bit), or
74    // normalized (hidden bit set, exponent offset by one) with exponent zero.
75    // Zero exponent offset by one sets the bit exactly where the hidden bit is.
76    // So in both cases the value encodes itself.
77    return true;
78  }
79
80  uint16 exponent = value >> kUFloat16MantissaBits;  // No sign extend on uint!
81  // After the fast pass, the exponent is at least one (offset by one).
82  // Un-offset the exponent.
83  --exponent;
84  DCHECK_GE(exponent, 1);
85  DCHECK_LE(exponent, kUFloat16MaxExponent);
86  // Here we need to clear the exponent and set the hidden bit. We have already
87  // decremented the exponent, so when we subtract it, it leaves behind the
88  // hidden bit.
89  *result -= exponent << kUFloat16MantissaBits;
90  *result <<= exponent;
91  DCHECK_GE(value, 1 << kUFloat16MantissaEffectiveBits);
92  DCHECK_LE(value, kUFloat16MaxValue);
93  return true;
94}
95
96bool QuicDataReader::ReadStringPiece16(StringPiece* result) {
97  // Read resultant length.
98  uint16 result_len;
99  if (!ReadUInt16(&result_len)) {
100    // OnFailure() already called.
101    return false;
102  }
103
104  return ReadStringPiece(result, result_len);
105}
106
107bool QuicDataReader::ReadStringPiece(StringPiece* result, size_t size) {
108  // Make sure that we have enough data to read.
109  if (!CanRead(size)) {
110    OnFailure();
111    return false;
112  }
113
114  // Set result.
115  result->set(data_ + pos_, size);
116
117  // Iterate.
118  pos_ += size;
119
120  return true;
121}
122
123StringPiece QuicDataReader::ReadRemainingPayload() {
124  StringPiece payload = PeekRemainingPayload();
125  pos_ = len_;
126  return payload;
127}
128
129StringPiece QuicDataReader::PeekRemainingPayload() {
130  return StringPiece(data_ + pos_, len_ - pos_);
131}
132
133bool QuicDataReader::ReadBytes(void* result, size_t size) {
134  // Make sure that we have enough data to read.
135  if (!CanRead(size)) {
136    OnFailure();
137    return false;
138  }
139
140  // Read into result.
141  memcpy(result, data_ + pos_, size);
142
143  // Iterate.
144  pos_ += size;
145
146  return true;
147}
148
149bool QuicDataReader::IsDoneReading() const {
150  return len_ == pos_;
151}
152
153size_t QuicDataReader::BytesRemaining() const {
154  return len_ - pos_;
155}
156
157bool QuicDataReader::CanRead(size_t bytes) const {
158  return bytes <= (len_ - pos_);
159}
160
161void QuicDataReader::OnFailure() {
162  // Set our iterator to the end of the buffer so that further reads fail
163  // immediately.
164  pos_ = len_;
165}
166
167}  // namespace net
168