1// Copyright (c) 2009 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/tools/flip_server/simple_buffer.h" 6#include "base/logging.h" 7 8// Some of the following member functions are marked inlined, even though they 9// are virtual. This may seem counter-intuitive, since virtual functions are 10// generally not eligible for inlining. Profiling results indicate that these 11// large amount of runtime is spent on virtual function dispatch on these 12// simple functions. They are virtual because of the interface this class 13// inherits from. However, it is very unlikely that anyone will sub-class 14// SimpleBuffer and change their implementation. To get rid of this baggage, 15// internal implementation (e.g., Write) explicitly use SimpleBuffer:: to 16// qualify the method calls, thus disabling the virtual dispatch and enable 17// inlining. 18 19namespace net { 20 21static const int kInitialSimpleBufferSize = 10; 22 23SimpleBuffer::SimpleBuffer() 24 : storage_(new char[kInitialSimpleBufferSize]), 25 write_idx_(0), 26 read_idx_(0), 27 storage_size_(kInitialSimpleBufferSize) { 28} 29 30SimpleBuffer::SimpleBuffer(int size) 31 : write_idx_(0), 32 read_idx_(0), 33 storage_size_(size) { 34 // Callers may try to allocate overly large blocks, but negative sizes are 35 // obviously wrong. 36 CHECK_GE(size, 0); 37 storage_ = new char[size]; 38} 39 40SimpleBuffer::~SimpleBuffer() { 41 delete[] storage_; 42} 43 44 45//////////////////////////////////////////////////////////////////////////////// 46 47int SimpleBuffer::ReadableBytes() const { 48 return write_idx_ - read_idx_; 49} 50 51//////////////////////////////////////////////////////////////////////////////// 52 53std::string SimpleBuffer::str() const { 54 std::string s; 55 char * readable_ptr; 56 int readable_size; 57 GetReadablePtr(&readable_ptr, &readable_size); 58 s.append(readable_ptr, readable_ptr + readable_size); 59 return s; 60} 61 62//////////////////////////////////////////////////////////////////////////////// 63 64int SimpleBuffer::BufferSize() const { 65 return storage_size_; 66} 67 68//////////////////////////////////////////////////////////////////////////////// 69 70inline int SimpleBuffer::BytesFree() const { 71 return (storage_size_ - write_idx_); 72} 73 74//////////////////////////////////////////////////////////////////////////////// 75 76bool SimpleBuffer::Empty() const { 77 return (read_idx_ == write_idx_); 78} 79 80//////////////////////////////////////////////////////////////////////////////// 81 82bool SimpleBuffer::Full() const { 83 return ((write_idx_ == storage_size_) && (read_idx_ != write_idx_)); 84} 85 86//////////////////////////////////////////////////////////////////////////////// 87 88// returns the number of characters written. 89// appends up-to-'size' bytes to the simplebuffer. 90int SimpleBuffer::Write(const char* bytes, int size) { 91 bool has_room = ((storage_size_ - write_idx_) >= size); 92 if (!has_room) { 93 (void)Reserve(size); 94 } 95 memcpy(storage_ + write_idx_, bytes, size); 96 SimpleBuffer::AdvanceWritablePtr(size); 97 return size; 98} 99 100//////////////////////////////////////////////////////////////////////////////// 101 102// stores a pointer into the simple buffer in *ptr, 103// and stores the number of characters which are allowed 104// to be written in *size. 105inline void SimpleBuffer::GetWritablePtr(char **ptr, int* size) const { 106 *ptr = storage_ + write_idx_; 107 *size = SimpleBuffer::BytesFree(); 108} 109 110//////////////////////////////////////////////////////////////////////////////// 111 112// stores a pointer into the simple buffer in *ptr, 113// and stores the number of characters which are allowed 114// to be read in *size. 115void SimpleBuffer::GetReadablePtr(char **ptr, int* size) const { 116 *ptr = storage_ + read_idx_; 117 *size = write_idx_ - read_idx_; 118} 119 120//////////////////////////////////////////////////////////////////////////////// 121 122// returns the number of bytes read into 'bytes' 123int SimpleBuffer::Read(char* bytes, int size) { 124 char * read_ptr = NULL; 125 int read_size = 0; 126 GetReadablePtr(&read_ptr, &read_size); 127 if (read_size > size) { 128 read_size = size; 129 } 130 memcpy(bytes, read_ptr, read_size); 131 AdvanceReadablePtr(read_size); 132 return read_size; 133} 134 135//////////////////////////////////////////////////////////////////////////////// 136 137// removes all data from the simple buffer 138void SimpleBuffer::Clear() { 139 read_idx_ = write_idx_ = 0; 140} 141 142//////////////////////////////////////////////////////////////////////////////// 143 144// Attempts to reserve a contiguous block of buffer space by either reclaiming 145// old data that is already read, and reallocate large storage as needed. 146bool SimpleBuffer::Reserve(int size) { 147 if (size > 0 && BytesFree() < size) { 148 char * read_ptr = NULL; 149 int read_size = 0; 150 GetReadablePtr(&read_ptr, &read_size); 151 152 if (read_size + size <= BufferSize()) { 153 // Can reclaim space from already read bytes by shifting 154 memmove(storage_, read_ptr, read_size); 155 read_idx_ = 0; 156 write_idx_ = read_size; 157 CHECK_GE(BytesFree(), size); 158 } else { 159 // what we need is to have at least size bytes available for writing. 160 // This implies that the buffer needs to be at least size bytes + 161 // read_size bytes long. Since we want linear time extensions in the case 162 // that we're extending this thing repeatedly, we should extend to twice 163 // the current size (if that is big enough), or the size + read_size 164 // bytes, whichever is larger. 165 int new_storage_size = 2 * storage_size_; 166 if (new_storage_size < size + read_size) { 167 new_storage_size = size + read_size; 168 } 169 170 // have to extend the thing 171 char* new_storage = new char[new_storage_size]; 172 173 // copy still useful info to the new buffer. 174 memcpy(new_storage, read_ptr, read_size); 175 // reset pointers. 176 read_idx_ = 0; 177 write_idx_ = read_size; 178 delete[] storage_; 179 storage_ = new_storage; 180 storage_size_ = new_storage_size; 181 } 182 } 183 return true; 184} 185 186//////////////////////////////////////////////////////////////////////////////// 187 188// removes the oldest 'amount_to_consume' characters. 189void SimpleBuffer::AdvanceReadablePtr(int amount_to_advance) { 190 read_idx_ += amount_to_advance; 191 if (read_idx_ > storage_size_) { 192 read_idx_ = storage_size_; 193 } 194} 195 196//////////////////////////////////////////////////////////////////////////////// 197 198// Moves the internal pointers around such that the 199// amount of data specified here is expected to 200// already be resident (as if it was Written) 201inline void SimpleBuffer::AdvanceWritablePtr(int amount_to_advance) { 202 write_idx_ += amount_to_advance; 203 if (write_idx_ > storage_size_) { 204 write_idx_ = storage_size_; 205 } 206} 207 208} // namespace net 209