| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 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/balsa/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 SimpleBuffer::~SimpleBuffer() { | |
| 41 delete[] storage_; | |
| 42 } | |
| 43 | |
| 44 | |
| 45 //////////////////////////////////////////////////////////////////////////////// | |
| 46 | |
| 47 int SimpleBuffer::ReadableBytes() const { | |
| 48 return write_idx_ - read_idx_; | |
| 49 } | |
| 50 | |
| 51 //////////////////////////////////////////////////////////////////////////////// | |
| 52 | |
| 53 std::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 | |
| 64 int SimpleBuffer::BufferSize() const { | |
| 65 return storage_size_; | |
| 66 } | |
| 67 | |
| 68 //////////////////////////////////////////////////////////////////////////////// | |
| 69 | |
| 70 inline int SimpleBuffer::BytesFree() const { | |
| 71 return (storage_size_ - write_idx_); | |
| 72 } | |
| 73 | |
| 74 //////////////////////////////////////////////////////////////////////////////// | |
| 75 | |
| 76 bool SimpleBuffer::Empty() const { | |
| 77 return (read_idx_ == write_idx_); | |
| 78 } | |
| 79 | |
| 80 //////////////////////////////////////////////////////////////////////////////// | |
| 81 | |
| 82 bool 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. | |
| 90 int 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. | |
| 105 inline 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. | |
| 115 void 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' | |
| 123 int 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 | |
| 138 void 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. | |
| 146 bool 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. | |
| 189 void 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) | |
| 201 inline 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 | |
| OLD | NEW |