Line data Source code
1 :
2 : /* Copyright (c) 2007-2016, Stefan Eilemann <eile@equalizergraphics.com>
3 : * Daniel Nachbaur <danielnachbaur@gmail.com>
4 : *
5 : * This library is free software; you can redistribute it and/or modify it under
6 : * the terms of the GNU Lesser General Public License version 2.1 as published
7 : * by the Free Software Foundation.
8 : *
9 : * This library is distributed in the hope that it will be useful, but WITHOUT
10 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 : * details.
13 : *
14 : * You should have received a copy of the GNU Lesser General Public License
15 : * along with this library; if not, write to the Free Software Foundation, Inc.,
16 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 : */
18 :
19 : #ifndef LUNCHBOX_BUFFER_H
20 : #define LUNCHBOX_BUFFER_H
21 :
22 : #include <lunchbox/debug.h> // LBASSERT macro
23 : #include <lunchbox/os.h> // setZero used inline
24 : #include <lunchbox/types.h>
25 :
26 : #include <cstdlib> // for malloc
27 : #include <cstring> // for memcpy
28 :
29 : namespace lunchbox
30 : {
31 : /**
32 : * A simple memory buffer with some helper functions.
33 : *
34 : * std::vector does not implement optimizations for growing bitwise-movable
35 : * vectors, i.e., it copy-constructs each element on growth.
36 : *
37 : * This buffer just memcpy's elements, i.e., it should only be used for PODs
38 : * since the copy constructor or assignment operator is not called on the copied
39 : * elements. Primarily used for binary data, e.g., in eq::Image. The
40 : * implementation works like a pool, that is, data is only released when the
41 : * buffer is deleted or clear() is called.
42 : */
43 : template <class T>
44 : class Buffer
45 : {
46 : public:
47 : /** Construct a new, empty buffer. @version 1.0 */
48 1 : Buffer()
49 : : _data(nullptr)
50 : , _size(0)
51 1 : , _maxSize(0)
52 : {
53 1 : }
54 :
55 : /** Construct a new buffer of the given size. @version 1.0 */
56 : explicit Buffer(const uint64_t size)
57 : : _data(0)
58 : , _size(0)
59 : , _maxSize(0)
60 : {
61 : reset(size);
62 : }
63 :
64 : /** Copy constructor, copies data to new Buffer. @version 1.14 */
65 : Buffer(const Buffer& from);
66 :
67 : /** Move constructor, transfers data to new Buffer. @version 1.14 */
68 : Buffer(Buffer&& from);
69 :
70 : /** Destruct the buffer. @version 1.0 */
71 2 : ~Buffer() { clear(); }
72 : /** Flush the buffer, deleting all data. @version 1.0 */
73 2 : void clear()
74 : {
75 2 : if (_data)
76 0 : free(_data);
77 2 : _data = 0;
78 2 : _size = 0;
79 2 : _maxSize = 0;
80 2 : }
81 :
82 : /**
83 : * Tighten the allocated memory to the size of the buffer.
84 : * @return the new pointer to the first element.
85 : * @version 1.0
86 : */
87 : T* pack();
88 :
89 : /** Assignment operator, copies data from Buffer. @version 1.0 */
90 : Buffer& operator=(const Buffer& from);
91 :
92 : /** Move operator, transfers ownership. @version 1.14 */
93 : Buffer& operator=(Buffer&& from);
94 :
95 : /** Direct access to the element at the given index. @version 1.0 */
96 : T& operator[](const uint64_t position)
97 : {
98 : LBASSERT(_size > position);
99 : return _data[position];
100 : }
101 :
102 : /** Direct const access to an element. @version 1.0 */
103 : const T& operator[](const uint64_t position) const
104 : {
105 : LBASSERT(_size > position);
106 : return _data[position];
107 : }
108 :
109 : /**
110 : * Ensure that the buffer contains at least newSize elements.
111 : *
112 : * Existing data is retained. The size is set.
113 : * @return the new pointer to the first element.
114 : * @version 1.0
115 : */
116 : T* resize(const uint64_t newSize);
117 :
118 : /**
119 : * Ensure that the buffer contains at least newSize elements.
120 : *
121 : * Existing data is retained. The size is increased, if necessary.
122 : * @version 1.0
123 : */
124 : void grow(const uint64_t newSize);
125 :
126 : /**
127 : * Ensure that the buffer contains at least newSize elements.
128 : *
129 : * Existing data is preserved.
130 : * @return the new pointer to the first element.
131 : * @version 1.0
132 : */
133 : T* reserve(const uint64_t newSize);
134 :
135 : /**
136 : * Set the buffer size and malloc enough memory.
137 : *
138 : * Existing data may be deleted.
139 : * @return the new pointer to the first element.
140 : * @version 1.0
141 : */
142 : T* reset(const uint64_t newSize);
143 :
144 : /** Set the buffer content to 0. @version 1.9.1 */
145 : void setZero() { ::lunchbox::setZero(_data, _size); }
146 : /** Append elements to the buffer, increasing the size. @version 1.0 */
147 : void append(const T* data, const uint64_t size);
148 :
149 : /** Append one element to the buffer. @version 1.0 */
150 : void append(const T& element);
151 :
152 : /** Replace the existing data with new data. @version 1.0 */
153 : void replace(const void* data, const uint64_t size);
154 :
155 : /** Replace the existing data. @version 1.5.1 */
156 0 : void replace(const Buffer& from) { replace(from._data, from._size); }
157 : /** Swap the buffer contents with another Buffer. @version 1.0 */
158 : void swap(Buffer& buffer);
159 :
160 : /** @return a pointer to the data. @version 1.0 */
161 2 : T* getData() { return _data; }
162 : /** @return a const pointer to the data. @version 1.0 */
163 : const T* getData() const { return _data; }
164 : /**
165 : * Set the size of the buffer without changing its allocation.
166 : *
167 : * This method only modifies the size parameter. If the current
168 : * allocation of the buffer is too small, it asserts, returns false and
169 : * does not change the size.
170 : * @version 1.0
171 : */
172 : bool setSize(const uint64_t size);
173 :
174 : /** @return the current number of elements. @version 1.0 */
175 2 : uint64_t getSize() const { return _size; }
176 : /** @return the current storage size. @version 1.5.1 */
177 : uint64_t getNumBytes() const { return _size * sizeof(T); }
178 : /** @return true if the buffer is empty, false if not. @version 1.0 */
179 1 : bool isEmpty() const { return (_size == 0); }
180 : /** @return the maximum size of the buffer. @version 1.0 */
181 : uint64_t getMaxSize() const { return _maxSize; }
182 : private:
183 : /** A pointer to the data. */
184 : T* _data;
185 :
186 : /** The number of valid items in _data. */
187 : uint64_t _size;
188 :
189 : /** The allocation _size of the buffer. */
190 : uint64_t _maxSize;
191 : };
192 : }
193 :
194 : #include "buffer.ipp" // template implementation
195 :
196 : #endif // LUNCHBOX_BUFFER_H
|