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 |