1 // Copyright 2016 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 "quiche/http2/decoder/decode_buffer.h"
6
7 namespace http2 {
8
DecodeUInt8()9 uint8_t DecodeBuffer::DecodeUInt8() {
10 return static_cast<uint8_t>(DecodeChar());
11 }
12
DecodeUInt16()13 uint16_t DecodeBuffer::DecodeUInt16() {
14 QUICHE_DCHECK_LE(2u, Remaining());
15 const uint8_t b1 = DecodeUInt8();
16 const uint8_t b2 = DecodeUInt8();
17 // Note that chars are automatically promoted to ints during arithmetic,
18 // so the b1 << 8 doesn't end up as zero before being or-ed with b2.
19 // And the left-shift operator has higher precedence than the or operator.
20 return b1 << 8 | b2;
21 }
22
DecodeUInt24()23 uint32_t DecodeBuffer::DecodeUInt24() {
24 QUICHE_DCHECK_LE(3u, Remaining());
25 const uint8_t b1 = DecodeUInt8();
26 const uint8_t b2 = DecodeUInt8();
27 const uint8_t b3 = DecodeUInt8();
28 return b1 << 16 | b2 << 8 | b3;
29 }
30
DecodeUInt31()31 uint32_t DecodeBuffer::DecodeUInt31() {
32 QUICHE_DCHECK_LE(4u, Remaining());
33 const uint8_t b1 = DecodeUInt8() & 0x7f; // Mask out the high order bit.
34 const uint8_t b2 = DecodeUInt8();
35 const uint8_t b3 = DecodeUInt8();
36 const uint8_t b4 = DecodeUInt8();
37 return b1 << 24 | b2 << 16 | b3 << 8 | b4;
38 }
39
DecodeUInt32()40 uint32_t DecodeBuffer::DecodeUInt32() {
41 QUICHE_DCHECK_LE(4u, Remaining());
42 const uint8_t b1 = DecodeUInt8();
43 const uint8_t b2 = DecodeUInt8();
44 const uint8_t b3 = DecodeUInt8();
45 const uint8_t b4 = DecodeUInt8();
46 return b1 << 24 | b2 << 16 | b3 << 8 | b4;
47 }
48
49 #ifndef NDEBUG
set_subset_of_base(DecodeBuffer * base,const DecodeBufferSubset * subset)50 void DecodeBuffer::set_subset_of_base(DecodeBuffer* base,
51 const DecodeBufferSubset* subset) {
52 QUICHE_DCHECK_EQ(this, subset);
53 base->set_subset(subset);
54 }
clear_subset_of_base(DecodeBuffer * base,const DecodeBufferSubset * subset)55 void DecodeBuffer::clear_subset_of_base(DecodeBuffer* base,
56 const DecodeBufferSubset* subset) {
57 QUICHE_DCHECK_EQ(this, subset);
58 base->clear_subset(subset);
59 }
set_subset(const DecodeBufferSubset * subset)60 void DecodeBuffer::set_subset(const DecodeBufferSubset* subset) {
61 QUICHE_DCHECK(subset != nullptr);
62 QUICHE_DCHECK_EQ(subset_, nullptr) << "There is already a subset";
63 subset_ = subset;
64 }
clear_subset(const DecodeBufferSubset * subset)65 void DecodeBuffer::clear_subset(const DecodeBufferSubset* subset) {
66 QUICHE_DCHECK(subset != nullptr);
67 QUICHE_DCHECK_EQ(subset_, subset);
68 subset_ = nullptr;
69 }
DebugSetup()70 void DecodeBufferSubset::DebugSetup() {
71 start_base_offset_ = base_buffer_->Offset();
72 max_base_offset_ = start_base_offset_ + FullSize();
73 QUICHE_DCHECK_LE(max_base_offset_, base_buffer_->FullSize());
74
75 // Ensure that there is only one DecodeBufferSubset at a time for a base.
76 set_subset_of_base(base_buffer_, this);
77 }
DebugTearDown()78 void DecodeBufferSubset::DebugTearDown() {
79 // Ensure that the base hasn't been modified.
80 QUICHE_DCHECK_EQ(start_base_offset_, base_buffer_->Offset())
81 << "The base buffer was modified";
82
83 // Ensure that we haven't gone beyond the maximum allowed offset.
84 size_t offset = Offset();
85 QUICHE_DCHECK_LE(offset, FullSize());
86 QUICHE_DCHECK_LE(start_base_offset_ + offset, max_base_offset_);
87 QUICHE_DCHECK_LE(max_base_offset_, base_buffer_->FullSize());
88
89 clear_subset_of_base(base_buffer_, this);
90 }
91 #endif
92
93 } // namespace http2
94