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 19 namespace net { 20 21 static const int kInitialSimpleBufferSize = 10; 22 23 SimpleBuffer::SimpleBuffer() 24 : storage_(new char[kInitialSimpleBufferSize]), 25 write_idx_(0), 26 read_idx_(0), 27 storage_size_(kInitialSimpleBufferSize) { 28 } 29 30 SimpleBuffer::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 40 //////////////////////////////////////////////////////////////////////////////// 41 42 int SimpleBuffer::ReadableBytes() const { 43 return write_idx_ - read_idx_; 44 } 45 46 //////////////////////////////////////////////////////////////////////////////// 47 48 std::string SimpleBuffer::str() const { 49 std::string s; 50 char * readable_ptr; 51 int readable_size; 52 GetReadablePtr(&readable_ptr, &readable_size); 53 s.append(readable_ptr, readable_ptr + readable_size); 54 return s; 55 } 56 57 //////////////////////////////////////////////////////////////////////////////// 58 59 int SimpleBuffer::BufferSize() const { 60 return storage_size_; 61 } 62 63 //////////////////////////////////////////////////////////////////////////////// 64 65 inline int SimpleBuffer::BytesFree() const { 66 return (storage_size_ - write_idx_); 67 } 68 69 //////////////////////////////////////////////////////////////////////////////// 70 71 bool SimpleBuffer::Empty() const { 72 return (read_idx_ == write_idx_); 73 } 74 75 //////////////////////////////////////////////////////////////////////////////// 76 77 bool SimpleBuffer::Full() const { 78 return ((write_idx_ == storage_size_) && (read_idx_ != write_idx_)); 79 } 80 81 //////////////////////////////////////////////////////////////////////////////// 82 83 // returns the number of characters written. 84 // appends up-to-'size' bytes to the simplebuffer. 85 int SimpleBuffer::Write(const char* bytes, int size) { 86 bool has_room = ((storage_size_ - write_idx_) >= size); 87 if (!has_room) { 88 (void)Reserve(size); 89 } 90 memcpy(storage_ + write_idx_, bytes, size); 91 SimpleBuffer::AdvanceWritablePtr(size); 92 return size; 93 } 94 95 //////////////////////////////////////////////////////////////////////////////// 96 97 // stores a pointer into the simple buffer in *ptr, 98 // and stores the number of characters which are allowed 99 // to be written in *size. 100 inline void SimpleBuffer::GetWritablePtr(char **ptr, int* size) const { 101 *ptr = storage_ + write_idx_; 102 *size = SimpleBuffer::BytesFree(); 103 } 104 105 //////////////////////////////////////////////////////////////////////////////// 106 107 // stores a pointer into the simple buffer in *ptr, 108 // and stores the number of characters which are allowed 109 // to be read in *size. 110 void SimpleBuffer::GetReadablePtr(char **ptr, int* size) const { 111 *ptr = storage_ + read_idx_; 112 *size = write_idx_ - read_idx_; 113 } 114 115 //////////////////////////////////////////////////////////////////////////////// 116 117 // returns the number of bytes read into 'bytes' 118 int SimpleBuffer::Read(char* bytes, int size) { 119 char * read_ptr = NULL; 120 int read_size = 0; 121 GetReadablePtr(&read_ptr, &read_size); 122 if (read_size > size) { 123 read_size = size; 124 } 125 memcpy(bytes, read_ptr, read_size); 126 AdvanceReadablePtr(read_size); 127 return read_size; 128 } 129 130 //////////////////////////////////////////////////////////////////////////////// 131 132 // removes all data from the simple buffer 133 void SimpleBuffer::Clear() { 134 read_idx_ = write_idx_ = 0; 135 } 136 137 //////////////////////////////////////////////////////////////////////////////// 138 139 // Attempts to reserve a contiguous block of buffer space by either reclaiming 140 // old data that is already read, and reallocate large storage as needed. 141 bool SimpleBuffer::Reserve(int size) { 142 if (size > 0 && BytesFree() < size) { 143 char * read_ptr = NULL; 144 int read_size = 0; 145 GetReadablePtr(&read_ptr, &read_size); 146 147 if (read_size + size <= BufferSize()) { 148 // Can reclaim space from already read bytes by shifting 149 memmove(storage_, read_ptr, read_size); 150 read_idx_ = 0; 151 write_idx_ = read_size; 152 CHECK_GE(BytesFree(), size); 153 } else { 154 // what we need is to have at least size bytes available for writing. 155 // This implies that the buffer needs to be at least size bytes + 156 // read_size bytes long. Since we want linear time extensions in the case 157 // that we're extending this thing repeatedly, we should extend to twice 158 // the current size (if that is big enough), or the size + read_size 159 // bytes, whichever is larger. 160 int new_storage_size = 2 * storage_size_; 161 if (new_storage_size < size + read_size) { 162 new_storage_size = size + read_size; 163 } 164 165 // have to extend the thing 166 char* new_storage = new char[new_storage_size]; 167 168 // copy still useful info to the new buffer. 169 memcpy(new_storage, read_ptr, read_size); 170 // reset pointers. 171 read_idx_ = 0; 172 write_idx_ = read_size; 173 delete[] storage_; 174 storage_ = new_storage; 175 storage_size_ = new_storage_size; 176 } 177 } 178 return true; 179 } 180 181 //////////////////////////////////////////////////////////////////////////////// 182 183 // removes the oldest 'amount_to_consume' characters. 184 void SimpleBuffer::AdvanceReadablePtr(int amount_to_advance) { 185 read_idx_ += amount_to_advance; 186 if (read_idx_ > storage_size_) { 187 read_idx_ = storage_size_; 188 } 189 } 190 191 //////////////////////////////////////////////////////////////////////////////// 192 193 // Moves the internal pointers around such that the 194 // amount of data specified here is expected to 195 // already be resident (as if it was Written) 196 inline void SimpleBuffer::AdvanceWritablePtr(int amount_to_advance) { 197 write_idx_ += amount_to_advance; 198 if (write_idx_ > storage_size_) { 199 write_idx_ = storage_size_; 200 } 201 } 202 203 } // namespace net 204 205