// 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/spdy/spdy_prefixed_buffer_reader.h"
#include "base/logging.h"
namespace net {
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 net