summaryrefslogtreecommitdiff
path: root/chromium/net/tools/flip_server/simple_buffer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/tools/flip_server/simple_buffer.cc')
-rw-r--r--chromium/net/tools/flip_server/simple_buffer.cc208
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