Branch data Line data Source code
1 : : /* Copyright 2006 Savarese Software Research Corporation
2 : : *
3 : : * Licensed under the Apache License, Version 2.0 (the "License");
4 : : * you may not use this file except in compliance with the License.
5 : : * You may obtain a copy of the License at
6 : : *
7 : : * http://www.savarese.com/software/ApacheLicense-2.0
8 : : *
9 : : * Unless required by applicable law or agreed to in writing, software
10 : : * distributed under the License is distributed on an "AS IS" BASIS,
11 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : : * See the License for the specific language governing permissions and
13 : : * limitations under the License.
14 : : */
15 : :
16 : : /**
17 : : * @file
18 : : * This header defines the Buffer class.
19 : : */
20 : :
21 : : #ifndef __SSRC_SPREAD_DETAIL_BUFFER_H
22 : : #define __SSRC_SPREAD_DETAIL_BUFFER_H
23 : :
24 : : #include <cstring>
25 : : #include <iterator>
26 : :
27 : : #include <ssrc/libssrcspread-packages.h>
28 : :
29 : : __BEGIN_NS_SSRC_SPREAD
30 : :
31 : : namespace detail {
32 : :
33 : : /**
34 : : * Buffer defines a limited set of operations for managing a memory
35 : : * buffer. It is intended only for internal use by the library.
36 : : * Please do not subclass Buffer, but do examine its public methods
37 : : * that are inherited by its subclasses.
38 : : *
39 : : * We define Buffer instead of using std::vector because we
40 : : * want to avoid the overhead of std::vector::clear() and
41 : : * std::vector::resize(), both of which cause unused data elements
42 : : * to be erased. The buffers used by the library may be resized
43 : : * often (potentially on every send and receive). We are
44 : : * unconcerned with erasing (or initializing) unused elements
45 : : * because we read and write to the buffer's raw memory. Therefore,
46 : : * we merely require an index that tracks the size of the buffer.
47 : : */
48 : : template<typename type>
49 : : class Buffer {
50 : :
51 : : unsigned int _capacity;
52 : : unsigned int _size;
53 : : type * _data;
54 : :
55 : : public:
56 : : typedef type value_type;
57 : : typedef value_type & reference;
58 : : typedef const reference const_reference;
59 : : typedef value_type* pointer;
60 : : typedef const value_type* const_pointer;
61 : : typedef pointer iterator;
62 : : typedef const_pointer const_iterator;
63 : : typedef std::reverse_iterator<iterator> reverse_iterator;
64 : : typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
65 : :
66 : : /**
67 : : * Creates a buffer with the specified capacity and sets its size to zero.
68 : : *
69 : : * @param capacity The initial capacity of the buffer.
70 : : */
71 : 62 : explicit Buffer(const unsigned int capacity) :
72 : 62 : _capacity(capacity), _size(0), _data(new value_type[capacity])
73 : 62 : { }
74 : :
75 : : /**
76 : : * Deallocates all memory used by the buffer.
77 : : */
78 [ + - + - ]: 62 : ~Buffer() { delete[] _data; }
79 : :
80 : : /**
81 : : * Returns the maximum number of elements that can be written to the
82 : : * buffer without reallocating memory.
83 : : *
84 : : * @return The buffer capacity.
85 : : */
86 : 53 : unsigned int capacity() const {
87 : 53 : return _capacity;
88 : : }
89 : :
90 : : /**
91 : : * Returns the element at the specified index.
92 : : *
93 : : * @param index The index of the element to retrieve.
94 : : * @return The element at the specified index.
95 : : */
96 : 294977 : reference operator[](const unsigned int index) {
97 : 294977 : return _data[index];
98 : : }
99 : :
100 : : /**
101 : : * Returns the element at the specified index.
102 : : *
103 : : * @param index The index of the element to retrieve.
104 : : * @return The element at the specified index.
105 : : */
106 : 69 : const_reference operator[](const unsigned int index) const {
107 : 69 : return _data[index];
108 : : }
109 : :
110 : : /**
111 : : * Returns an iterator pointing to the first element in the buffer.
112 : : *
113 : : * @return An iterator pointing to the first element in the buffer.
114 : : */
115 : 2 : iterator begin() {
116 : 2 : return _data;
117 : : }
118 : :
119 : : /**
120 : : * Returns a const iterator pointing to the first element in the buffer.
121 : : *
122 : : * @return A const iterator pointing to the first element in the buffer.
123 : : */
124 : 2 : const_iterator begin() const {
125 : 2 : return _data;
126 : : }
127 : :
128 : : /**
129 : : * Returns an iterator pointing to one position beyond the last element
130 : : * in the buffer.
131 : : *
132 : : * @return An iterator pointing to one position beyond the last element
133 : : * in the buffer.
134 : : */
135 : 2 : iterator end() {
136 : 2 : return (_data + _size);
137 : : }
138 : :
139 : : /**
140 : : * Returns an iterator pointing to one position beyond the last element
141 : : * in the buffer.
142 : : *
143 : : * @return An iterator pointing to one position beyond the last element
144 : : * in the buffer.
145 : : */
146 : 2 : const_iterator end() const {
147 : 2 : return (_data + _size);
148 : : }
149 : :
150 : : /**
151 : : * Returns reverse_iterator(end()).
152 : : *
153 : : * @return reverse_iterator(end()).
154 : : */
155 : 1 : reverse_iterator rbegin() {
156 : 1 : return reverse_iterator(end());
157 : : }
158 : :
159 : : /**
160 : : * Returns const_reverse_iterator(end()).
161 : : *
162 : : * @return const_reverse_iterator(end()).
163 : : */
164 : 1 : const_reverse_iterator rbegin() const {
165 : 1 : return const_reverse_iterator(end());
166 : : }
167 : :
168 : : /**
169 : : * Returns reverse_iterator(begin()).
170 : : *
171 : : * @return reverse_iterator(begin()).
172 : : */
173 : 1 : reverse_iterator rend() {
174 : 1 : return reverse_iterator(begin());
175 : : }
176 : :
177 : : /**
178 : : * Returns const_reverse_iterator(begin()).
179 : : *
180 : : * @return const_reverse_iterator(begin()).
181 : : */
182 : 1 : const_reverse_iterator rend() const {
183 : 1 : return const_reverse_iterator(begin());
184 : : }
185 : :
186 : : /**
187 : : * Increases the buffer capacity to the specified size. If the
188 : : * new size is less than or equal to the buffer capacity, no
189 : : * action is performed. If the size is greater than the capacity,
190 : : * new memory is reserved, increasing the capacity while
191 : : * preserving the existing buffer contents.
192 : : *
193 : : * @param capacity The new buffer capacity.
194 : : */
195 : 262270 : void reserve(const unsigned int capacity) {
196 [ + + + + ]: 262270 : if(capacity > _capacity) {
197 : 31 : pointer new_data = new value_type[capacity];
198 : 31 : std::memcpy(new_data, _data, _size*sizeof(value_type));
199 [ + - + - ]: 31 : delete[] _data;
200 : 31 : _data = new_data;
201 : 31 : _capacity = capacity;
202 : : }
203 : 262270 : }
204 : :
205 : : /**
206 : : * Resizes the buffer to the specified size. If the new size is
207 : : * less than or equal to the buffer capacity, the size is simply
208 : : * set to the new value. If the size is greater than the
209 : : * capacity, new memory is reserved—preserving the existing
210 : : * buffer contents—before setting the size to the new value.
211 : : *
212 : : * @param size The new buffer size.
213 : : */
214 : 262247 : void resize(const unsigned int size) {
215 : 262247 : reserve(size);
216 : 262247 : _size = size;
217 : 262247 : }
218 : :
219 : : /**
220 : : * Returns the number of elements contained in the buffer.
221 : : * @return The number of elements contained in the buffer.
222 : : */
223 : 295094 : unsigned int size() const {
224 : 295094 : return _size;
225 : : }
226 : :
227 : : /** Same as {@link #resize resize(0)}. */
228 : 14 : void clear() {
229 : 14 : resize(0);
230 : 14 : }
231 : :
232 : : /**
233 : : * Appends a value to the end of the buffer and increments the
234 : : * size by one. If the buffer is at full capacity, its capacity
235 : : * is increased to be able to hold more data. Currently, this is
236 : : * done by doubling the current capacity, but you should not rely
237 : : * on that behavior.
238 : : *
239 : : * @param value The value to append to the buffer.
240 : : */
241 : 19 : void add(const type & value) {
242 [ - + ]: 19 : if(capacity() <= _size) {
243 : 0 : reserve(_size << 1);
244 : : }
245 : 19 : _data[_size++] = value;
246 : 19 : }
247 : : };
248 : : }
249 : :
250 : : __END_NS_SSRC_SPREAD
251 : :
252 : : #endif
|