blob: c196b42d2bba42bbc2cea66f328c3267a6505ad3 [file] [log] [blame]
dmcardle2b64f502020-01-07 15:22:36 -08001// Copyright (c) 2020 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
QUICHE team5be974e2020-12-29 18:35:24 -05005#include "common/quiche_data_reader.h"
dmcardle2b64f502020-01-07 15:22:36 -08006
vasilvv0a09b8f2020-04-27 08:08:55 -07007#include <cstring>
8
vasilvv23846f32020-10-27 09:53:28 -07009#include "absl/strings/numbers.h"
vasilvv6950cd82020-12-03 15:33:04 -080010#include "absl/strings/str_cat.h"
vasilvv652cd422020-10-09 15:50:02 -070011#include "absl/strings/string_view.h"
QUICHE team5be974e2020-12-29 18:35:24 -050012#include "common/platform/api/quiche_logging.h"
13#include "common/platform/api/quiche_text_utils.h"
14#include "common/quiche_endian.h"
dmcardle2b64f502020-01-07 15:22:36 -080015
16namespace quiche {
17
vasilvv652cd422020-10-09 15:50:02 -070018QuicheDataReader::QuicheDataReader(absl::string_view data)
dmcardle2b64f502020-01-07 15:22:36 -080019 : QuicheDataReader(data.data(), data.length(), quiche::NETWORK_BYTE_ORDER) {
20}
21
22QuicheDataReader::QuicheDataReader(const char* data, const size_t len)
23 : QuicheDataReader(data, len, quiche::NETWORK_BYTE_ORDER) {}
24
25QuicheDataReader::QuicheDataReader(const char* data,
26 const size_t len,
27 quiche::Endianness endianness)
28 : data_(data), len_(len), pos_(0), endianness_(endianness) {}
29
30bool QuicheDataReader::ReadUInt8(uint8_t* result) {
31 return ReadBytes(result, sizeof(*result));
32}
33
34bool QuicheDataReader::ReadUInt16(uint16_t* result) {
35 if (!ReadBytes(result, sizeof(*result))) {
36 return false;
37 }
38 if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
39 *result = quiche::QuicheEndian::NetToHost16(*result);
40 }
41 return true;
42}
43
44bool QuicheDataReader::ReadUInt32(uint32_t* result) {
45 if (!ReadBytes(result, sizeof(*result))) {
46 return false;
47 }
48 if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
49 *result = quiche::QuicheEndian::NetToHost32(*result);
50 }
51 return true;
52}
53
54bool QuicheDataReader::ReadUInt64(uint64_t* result) {
55 if (!ReadBytes(result, sizeof(*result))) {
56 return false;
57 }
58 if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
59 *result = quiche::QuicheEndian::NetToHost64(*result);
60 }
61 return true;
62}
63
64bool QuicheDataReader::ReadBytesToUInt64(size_t num_bytes, uint64_t* result) {
65 *result = 0u;
66 if (num_bytes > sizeof(*result)) {
67 return false;
68 }
69 if (endianness_ == quiche::HOST_BYTE_ORDER) {
70 return ReadBytes(result, num_bytes);
71 }
72
73 if (!ReadBytes(reinterpret_cast<char*>(result) + sizeof(*result) - num_bytes,
74 num_bytes)) {
75 return false;
76 }
77 *result = quiche::QuicheEndian::NetToHost64(*result);
78 return true;
79}
80
vasilvv652cd422020-10-09 15:50:02 -070081bool QuicheDataReader::ReadStringPiece16(absl::string_view* result) {
dmcardle2b64f502020-01-07 15:22:36 -080082 // Read resultant length.
83 uint16_t result_len;
84 if (!ReadUInt16(&result_len)) {
85 // OnFailure() already called.
86 return false;
87 }
88
89 return ReadStringPiece(result, result_len);
90}
91
vasilvv652cd422020-10-09 15:50:02 -070092bool QuicheDataReader::ReadStringPiece8(absl::string_view* result) {
dschinazia0aeda52020-04-10 16:57:18 -070093 // Read resultant length.
94 uint8_t result_len;
95 if (!ReadUInt8(&result_len)) {
96 // OnFailure() already called.
97 return false;
98 }
99
100 return ReadStringPiece(result, result_len);
101}
102
vasilvv652cd422020-10-09 15:50:02 -0700103bool QuicheDataReader::ReadStringPiece(absl::string_view* result, size_t size) {
dmcardle2b64f502020-01-07 15:22:36 -0800104 // Make sure that we have enough data to read.
105 if (!CanRead(size)) {
106 OnFailure();
107 return false;
108 }
109
110 // Set result.
vasilvv652cd422020-10-09 15:50:02 -0700111 *result = absl::string_view(data_ + pos_, size);
dmcardle2b64f502020-01-07 15:22:36 -0800112
113 // Iterate.
114 pos_ += size;
115
116 return true;
117}
118
119bool QuicheDataReader::ReadTag(uint32_t* tag) {
120 return ReadBytes(tag, sizeof(*tag));
121}
122
vasilvv52f24592020-06-02 17:32:16 -0700123bool QuicheDataReader::ReadDecimal64(size_t num_digits, uint64_t* result) {
vasilvv652cd422020-10-09 15:50:02 -0700124 absl::string_view digits;
vasilvv52f24592020-06-02 17:32:16 -0700125 if (!ReadStringPiece(&digits, num_digits)) {
126 return false;
127 }
128
vasilvv23846f32020-10-27 09:53:28 -0700129 return absl::SimpleAtoi(digits, result);
vasilvv52f24592020-06-02 17:32:16 -0700130}
131
vasilvv652cd422020-10-09 15:50:02 -0700132absl::string_view QuicheDataReader::ReadRemainingPayload() {
133 absl::string_view payload = PeekRemainingPayload();
dmcardle2b64f502020-01-07 15:22:36 -0800134 pos_ = len_;
135 return payload;
136}
137
vasilvv652cd422020-10-09 15:50:02 -0700138absl::string_view QuicheDataReader::PeekRemainingPayload() const {
139 return absl::string_view(data_ + pos_, len_ - pos_);
dmcardle2b64f502020-01-07 15:22:36 -0800140}
141
vasilvv652cd422020-10-09 15:50:02 -0700142absl::string_view QuicheDataReader::FullPayload() const {
143 return absl::string_view(data_, len_);
dmcardle2b64f502020-01-07 15:22:36 -0800144}
145
vasilvv652cd422020-10-09 15:50:02 -0700146absl::string_view QuicheDataReader::PreviouslyReadPayload() const {
147 return absl::string_view(data_, pos_);
dschinazi278efae2020-01-28 17:03:09 -0800148}
149
dmcardle2b64f502020-01-07 15:22:36 -0800150bool QuicheDataReader::ReadBytes(void* result, size_t size) {
151 // Make sure that we have enough data to read.
152 if (!CanRead(size)) {
153 OnFailure();
154 return false;
155 }
156
157 // Read into result.
158 memcpy(result, data_ + pos_, size);
159
160 // Iterate.
161 pos_ += size;
162
163 return true;
164}
165
166bool QuicheDataReader::Seek(size_t size) {
167 if (!CanRead(size)) {
168 OnFailure();
169 return false;
170 }
171 pos_ += size;
172 return true;
173}
174
175bool QuicheDataReader::IsDoneReading() const {
176 return len_ == pos_;
177}
178
179size_t QuicheDataReader::BytesRemaining() const {
180 return len_ - pos_;
181}
182
183bool QuicheDataReader::TruncateRemaining(size_t truncation_length) {
184 if (truncation_length > BytesRemaining()) {
185 return false;
186 }
187 len_ = pos_ + truncation_length;
188 return true;
189}
190
191bool QuicheDataReader::CanRead(size_t bytes) const {
192 return bytes <= (len_ - pos_);
193}
194
195void QuicheDataReader::OnFailure() {
196 // Set our iterator to the end of the buffer so that further reads fail
197 // immediately.
198 pos_ = len_;
199}
200
201uint8_t QuicheDataReader::PeekByte() const {
202 if (pos_ >= len_) {
203 QUICHE_LOG(FATAL)
204 << "Reading is done, cannot peek next byte. Tried to read pos = "
205 << pos_ << " buffer length = " << len_;
206 return 0;
207 }
208 return data_[pos_];
209}
210
211std::string QuicheDataReader::DebugString() const {
vasilvv6950cd82020-12-03 15:33:04 -0800212 return absl::StrCat(" { length: ", len_, ", position: ", pos_, " }");
dmcardle2b64f502020-01-07 15:22:36 -0800213}
214
215#undef ENDPOINT // undef for jumbo builds
216} // namespace quiche