| // 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 |