diff options
Diffstat (limited to 'chromium/net/tools/flip_server/simple_buffer.cc')
-rw-r--r-- | chromium/net/tools/flip_server/simple_buffer.cc | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/chromium/net/tools/flip_server/simple_buffer.cc b/chromium/net/tools/flip_server/simple_buffer.cc new file mode 100644 index 00000000000..d94153b29ec --- /dev/null +++ b/chromium/net/tools/flip_server/simple_buffer.cc @@ -0,0 +1,208 @@ +// Copyright (c) 2009 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/tools/flip_server/simple_buffer.h" +#include "base/logging.h" + +// Some of the following member functions are marked inlined, even though they +// are virtual. This may seem counter-intuitive, since virtual functions are +// generally not eligible for inlining. Profiling results indicate that these +// large amount of runtime is spent on virtual function dispatch on these +// simple functions. They are virtual because of the interface this class +// inherits from. However, it is very unlikely that anyone will sub-class +// SimpleBuffer and change their implementation. To get rid of this baggage, +// internal implementation (e.g., Write) explicitly use SimpleBuffer:: to +// qualify the method calls, thus disabling the virtual dispatch and enable +// inlining. + +namespace net { + +static const int kInitialSimpleBufferSize = 10; + +SimpleBuffer::SimpleBuffer() + : storage_(new char[kInitialSimpleBufferSize]), + write_idx_(0), + read_idx_(0), + storage_size_(kInitialSimpleBufferSize) { +} + +SimpleBuffer::SimpleBuffer(int size) + : write_idx_(0), + read_idx_(0), + storage_size_(size) { + // Callers may try to allocate overly large blocks, but negative sizes are + // obviously wrong. + CHECK_GE(size, 0); + storage_ = new char[size]; +} + +SimpleBuffer::~SimpleBuffer() { + delete[] storage_; +} + + +//////////////////////////////////////////////////////////////////////////////// + +int SimpleBuffer::ReadableBytes() const { + return write_idx_ - read_idx_; +} + +//////////////////////////////////////////////////////////////////////////////// + +std::string SimpleBuffer::str() const { + std::string s; + char * readable_ptr; + int readable_size; + GetReadablePtr(&readable_ptr, &readable_size); + s.append(readable_ptr, readable_ptr + readable_size); + return s; +} + +//////////////////////////////////////////////////////////////////////////////// + +int SimpleBuffer::BufferSize() const { + return storage_size_; +} + +//////////////////////////////////////////////////////////////////////////////// + +inline int SimpleBuffer::BytesFree() const { + return (storage_size_ - write_idx_); +} + +//////////////////////////////////////////////////////////////////////////////// + +bool SimpleBuffer::Empty() const { + return (read_idx_ == write_idx_); +} + +//////////////////////////////////////////////////////////////////////////////// + +bool SimpleBuffer::Full() const { + return ((write_idx_ == storage_size_) && (read_idx_ != write_idx_)); +} + +//////////////////////////////////////////////////////////////////////////////// + +// returns the number of characters written. +// appends up-to-'size' bytes to the simplebuffer. +int SimpleBuffer::Write(const char* bytes, int size) { + bool has_room = ((storage_size_ - write_idx_) >= size); + if (!has_room) { + (void)Reserve(size); + } + memcpy(storage_ + write_idx_, bytes, size); + SimpleBuffer::AdvanceWritablePtr(size); + return size; +} + +//////////////////////////////////////////////////////////////////////////////// + +// stores a pointer into the simple buffer in *ptr, +// and stores the number of characters which are allowed +// to be written in *size. +inline void SimpleBuffer::GetWritablePtr(char **ptr, int* size) const { + *ptr = storage_ + write_idx_; + *size = SimpleBuffer::BytesFree(); +} + +//////////////////////////////////////////////////////////////////////////////// + +// stores a pointer into the simple buffer in *ptr, +// and stores the number of characters which are allowed +// to be read in *size. +void SimpleBuffer::GetReadablePtr(char **ptr, int* size) const { + *ptr = storage_ + read_idx_; + *size = write_idx_ - read_idx_; +} + +//////////////////////////////////////////////////////////////////////////////// + +// returns the number of bytes read into 'bytes' +int SimpleBuffer::Read(char* bytes, int size) { + char * read_ptr = NULL; + int read_size = 0; + GetReadablePtr(&read_ptr, &read_size); + if (read_size > size) { + read_size = size; + } + memcpy(bytes, read_ptr, read_size); + AdvanceReadablePtr(read_size); + return read_size; +} + +//////////////////////////////////////////////////////////////////////////////// + +// removes all data from the simple buffer +void SimpleBuffer::Clear() { + read_idx_ = write_idx_ = 0; +} + +//////////////////////////////////////////////////////////////////////////////// + +// Attempts to reserve a contiguous block of buffer space by either reclaiming +// old data that is already read, and reallocate large storage as needed. +bool SimpleBuffer::Reserve(int size) { + if (size > 0 && BytesFree() < size) { + char * read_ptr = NULL; + int read_size = 0; + GetReadablePtr(&read_ptr, &read_size); + + if (read_size + size <= BufferSize()) { + // Can reclaim space from already read bytes by shifting + memmove(storage_, read_ptr, read_size); + read_idx_ = 0; + write_idx_ = read_size; + CHECK_GE(BytesFree(), size); + } else { + // what we need is to have at least size bytes available for writing. + // This implies that the buffer needs to be at least size bytes + + // read_size bytes long. Since we want linear time extensions in the case + // that we're extending this thing repeatedly, we should extend to twice + // the current size (if that is big enough), or the size + read_size + // bytes, whichever is larger. + int new_storage_size = 2 * storage_size_; + if (new_storage_size < size + read_size) { + new_storage_size = size + read_size; + } + + // have to extend the thing + char* new_storage = new char[new_storage_size]; + + // copy still useful info to the new buffer. + memcpy(new_storage, read_ptr, read_size); + // reset pointers. + read_idx_ = 0; + write_idx_ = read_size; + delete[] storage_; + storage_ = new_storage; + storage_size_ = new_storage_size; + } + } + return true; +} + +//////////////////////////////////////////////////////////////////////////////// + +// removes the oldest 'amount_to_consume' characters. +void SimpleBuffer::AdvanceReadablePtr(int amount_to_advance) { + read_idx_ += amount_to_advance; + if (read_idx_ > storage_size_) { + read_idx_ = storage_size_; + } +} + +//////////////////////////////////////////////////////////////////////////////// + +// Moves the internal pointers around such that the +// amount of data specified here is expected to +// already be resident (as if it was Written) +inline void SimpleBuffer::AdvanceWritablePtr(int amount_to_advance) { + write_idx_ += amount_to_advance; + if (write_idx_ > storage_size_) { + write_idx_ = storage_size_; + } +} + +} // namespace net |