| // Copyright 2016 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/third_party/quiche/src/http2/decoder/decode_buffer.h" | |
| namespace http2 { | |
| uint8_t DecodeBuffer::DecodeUInt8() { | |
| return static_cast<uint8_t>(DecodeChar()); | |
| } | |
| uint16_t DecodeBuffer::DecodeUInt16() { | |
| DCHECK_LE(2u, Remaining()); | |
| const uint8_t b1 = DecodeUInt8(); | |
| const uint8_t b2 = DecodeUInt8(); | |
| // Note that chars are automatically promoted to ints during arithmetic, | |
| // so the b1 << 8 doesn't end up as zero before being or-ed with b2. | |
| // And the left-shift operator has higher precedence than the or operator. | |
| return b1 << 8 | b2; | |
| } | |
| uint32_t DecodeBuffer::DecodeUInt24() { | |
| DCHECK_LE(3u, Remaining()); | |
| const uint8_t b1 = DecodeUInt8(); | |
| const uint8_t b2 = DecodeUInt8(); | |
| const uint8_t b3 = DecodeUInt8(); | |
| return b1 << 16 | b2 << 8 | b3; | |
| } | |
| uint32_t DecodeBuffer::DecodeUInt31() { | |
| DCHECK_LE(4u, Remaining()); | |
| const uint8_t b1 = DecodeUInt8() & 0x7f; // Mask out the high order bit. | |
| const uint8_t b2 = DecodeUInt8(); | |
| const uint8_t b3 = DecodeUInt8(); | |
| const uint8_t b4 = DecodeUInt8(); | |
| return b1 << 24 | b2 << 16 | b3 << 8 | b4; | |
| } | |
| uint32_t DecodeBuffer::DecodeUInt32() { | |
| DCHECK_LE(4u, Remaining()); | |
| const uint8_t b1 = DecodeUInt8(); | |
| const uint8_t b2 = DecodeUInt8(); | |
| const uint8_t b3 = DecodeUInt8(); | |
| const uint8_t b4 = DecodeUInt8(); | |
| return b1 << 24 | b2 << 16 | b3 << 8 | b4; | |
| } | |
| #ifndef NDEBUG | |
| void DecodeBuffer::set_subset_of_base(DecodeBuffer* base, | |
| const DecodeBufferSubset* subset) { | |
| DCHECK_EQ(this, subset); | |
| base->set_subset(subset); | |
| } | |
| void DecodeBuffer::clear_subset_of_base(DecodeBuffer* base, | |
| const DecodeBufferSubset* subset) { | |
| DCHECK_EQ(this, subset); | |
| base->clear_subset(subset); | |
| } | |
| void DecodeBuffer::set_subset(const DecodeBufferSubset* subset) { | |
| DCHECK(subset != nullptr); | |
| DCHECK_EQ(subset_, nullptr) << "There is already a subset"; | |
| subset_ = subset; | |
| } | |
| void DecodeBuffer::clear_subset(const DecodeBufferSubset* subset) { | |
| DCHECK(subset != nullptr); | |
| DCHECK_EQ(subset_, subset); | |
| subset_ = nullptr; | |
| } | |
| void DecodeBufferSubset::DebugSetup() { | |
| start_base_offset_ = base_buffer_->Offset(); | |
| max_base_offset_ = start_base_offset_ + FullSize(); | |
| DCHECK_LE(max_base_offset_, base_buffer_->FullSize()); | |
| // Ensure that there is only one DecodeBufferSubset at a time for a base. | |
| set_subset_of_base(base_buffer_, this); | |
| } | |
| void DecodeBufferSubset::DebugTearDown() { | |
| // Ensure that the base hasn't been modified. | |
| DCHECK_EQ(start_base_offset_, base_buffer_->Offset()) | |
| << "The base buffer was modified"; | |
| // Ensure that we haven't gone beyond the maximum allowed offset. | |
| size_t offset = Offset(); | |
| DCHECK_LE(offset, FullSize()); | |
| DCHECK_LE(start_base_offset_ + offset, max_base_offset_); | |
| DCHECK_LE(max_base_offset_, base_buffer_->FullSize()); | |
| clear_subset_of_base(base_buffer_, this); | |
| } | |
| #endif | |
| } // namespace http2 |