|  | // Copyright 2014 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/spdy/core/spdy_prefixed_buffer_reader.h" | 
|  |  | 
|  | #include <new> | 
|  |  | 
|  | #include "net/third_party/quiche/src/spdy/platform/api/spdy_logging.h" | 
|  |  | 
|  | namespace spdy { | 
|  |  | 
|  | SpdyPrefixedBufferReader::SpdyPrefixedBufferReader(const char* prefix, | 
|  | size_t prefix_length, | 
|  | const char* suffix, | 
|  | size_t suffix_length) | 
|  | : prefix_(prefix), | 
|  | suffix_(suffix), | 
|  | prefix_length_(prefix_length), | 
|  | suffix_length_(suffix_length) {} | 
|  |  | 
|  | size_t SpdyPrefixedBufferReader::Available() { | 
|  | return prefix_length_ + suffix_length_; | 
|  | } | 
|  |  | 
|  | bool SpdyPrefixedBufferReader::ReadN(size_t count, char* out) { | 
|  | if (Available() < count) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (prefix_length_ >= count) { | 
|  | // Read is fully satisfied by the prefix. | 
|  | std::copy(prefix_, prefix_ + count, out); | 
|  | prefix_ += count; | 
|  | prefix_length_ -= count; | 
|  | return true; | 
|  | } else if (prefix_length_ != 0) { | 
|  | // Read is partially satisfied by the prefix. | 
|  | out = std::copy(prefix_, prefix_ + prefix_length_, out); | 
|  | count -= prefix_length_; | 
|  | prefix_length_ = 0; | 
|  | // Fallthrough to suffix read. | 
|  | } | 
|  | DCHECK(suffix_length_ >= count); | 
|  | // Read is satisfied by the suffix. | 
|  | std::copy(suffix_, suffix_ + count, out); | 
|  | suffix_ += count; | 
|  | suffix_length_ -= count; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool SpdyPrefixedBufferReader::ReadN(size_t count, | 
|  | SpdyPinnableBufferPiece* out) { | 
|  | if (Available() < count) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | out->storage_.reset(); | 
|  | out->length_ = count; | 
|  |  | 
|  | if (prefix_length_ >= count) { | 
|  | // Read is fully satisfied by the prefix. | 
|  | out->buffer_ = prefix_; | 
|  | prefix_ += count; | 
|  | prefix_length_ -= count; | 
|  | return true; | 
|  | } else if (prefix_length_ != 0) { | 
|  | // Read is only partially satisfied by the prefix. We need to allocate | 
|  | // contiguous storage as the read spans the prefix & suffix. | 
|  | out->storage_.reset(new char[count]); | 
|  | out->buffer_ = out->storage_.get(); | 
|  | ReadN(count, out->storage_.get()); | 
|  | return true; | 
|  | } else { | 
|  | DCHECK(suffix_length_ >= count); | 
|  | // Read is fully satisfied by the suffix. | 
|  | out->buffer_ = suffix_; | 
|  | suffix_ += count; | 
|  | suffix_length_ -= count; | 
|  | return true; | 
|  | } | 
|  | } | 
|  |  | 
|  | }  // namespace spdy |