1 // Copyright 2014 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/spdy/core/spdy_prefixed_buffer_reader.h"
6
7 #include <algorithm>
8 #include <cstddef>
9
10 #include "quiche/common/platform/api/quiche_logging.h"
11 #include "quiche/spdy/core/spdy_pinnable_buffer_piece.h"
12
13 namespace spdy {
14
SpdyPrefixedBufferReader(const char * prefix,size_t prefix_length,const char * suffix,size_t suffix_length)15 SpdyPrefixedBufferReader::SpdyPrefixedBufferReader(const char* prefix,
16 size_t prefix_length,
17 const char* suffix,
18 size_t suffix_length)
19 : prefix_(prefix),
20 suffix_(suffix),
21 prefix_length_(prefix_length),
22 suffix_length_(suffix_length) {}
23
Available()24 size_t SpdyPrefixedBufferReader::Available() {
25 return prefix_length_ + suffix_length_;
26 }
27
ReadN(size_t count,char * out)28 bool SpdyPrefixedBufferReader::ReadN(size_t count, char* out) {
29 if (Available() < count) {
30 return false;
31 }
32
33 if (prefix_length_ >= count) {
34 // Read is fully satisfied by the prefix.
35 std::copy(prefix_, prefix_ + count, out);
36 prefix_ += count;
37 prefix_length_ -= count;
38 return true;
39 } else if (prefix_length_ != 0) {
40 // Read is partially satisfied by the prefix.
41 out = std::copy(prefix_, prefix_ + prefix_length_, out);
42 count -= prefix_length_;
43 prefix_length_ = 0;
44 // Fallthrough to suffix read.
45 }
46 QUICHE_DCHECK(suffix_length_ >= count);
47 // Read is satisfied by the suffix.
48 std::copy(suffix_, suffix_ + count, out);
49 suffix_ += count;
50 suffix_length_ -= count;
51 return true;
52 }
53
ReadN(size_t count,SpdyPinnableBufferPiece * out)54 bool SpdyPrefixedBufferReader::ReadN(size_t count,
55 SpdyPinnableBufferPiece* out) {
56 if (Available() < count) {
57 return false;
58 }
59
60 out->storage_.reset();
61 out->length_ = count;
62
63 if (prefix_length_ >= count) {
64 // Read is fully satisfied by the prefix.
65 out->buffer_ = prefix_;
66 prefix_ += count;
67 prefix_length_ -= count;
68 return true;
69 } else if (prefix_length_ != 0) {
70 // Read is only partially satisfied by the prefix. We need to allocate
71 // contiguous storage as the read spans the prefix & suffix.
72 out->storage_.reset(new char[count]);
73 out->buffer_ = out->storage_.get();
74 ReadN(count, out->storage_.get());
75 return true;
76 } else {
77 QUICHE_DCHECK(suffix_length_ >= count);
78 // Read is fully satisfied by the suffix.
79 out->buffer_ = suffix_;
80 suffix_ += count;
81 suffix_length_ -= count;
82 return true;
83 }
84 }
85
86 } // namespace spdy
87