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