API Documentation
Loading...
Searching...
No Matches
BoolBuffer.hpp
Go to the documentation of this file.
1/*--------------------------------------------------------------------------------------------
2Copyright (c) 2019, NDEVR LLC
3tyler.parke@ndevr.org
4 __ __ ____ _____ __ __ _______
5 | \ | | | __ \ | ___|\ \ / / | __ \
6 | \ | | | | \ \ | |___ \ \ / / | |__) |
7 | . \| | | |__/ / | |___ \ V / | _ /
8 | |\ |_|_____/__|_____|___\_/____| | \ \
9 |__| \__________________________________| \__\
10
11Subject to the terms of the Enterprise+ Agreement, NDEVR hereby grants
12Licensee a limited, non-exclusive, non-transferable, royalty-free license
13(without the right to sublicense) to use the API solely for the purpose of
14Licensee's internal development efforts to develop applications for which
15the API was provided.
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
22PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
23FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25DEALINGS IN THE SOFTWARE.
26
27Library: Base
28File: BoolBuffer
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include <NDEVR/ObjectAllocator.h>
34#include <NDEVR/BitReference.h>
35#include <NDEVR/BitIterator.h>
36namespace NDEVR
37{
38 #define bitset_wrd(pos) ((pos) >> 3)
39 #define bitset_idx(pos) ((pos) & 7)
40 #define bitmaskt(nbits,type) ((nbits) ? ~(type)0 >> (sizeof(type)*8-(nbits)): (type)0)
41 #define bitmask(nbits) cast<uint01>(bitmaskt(nbits,uint32_t))
42
43 /**--------------------------------------------------------------------------------------------------
44 \brief Specific logic for allocating booleans in a Buffer. Will allocate 8 booleans per byte for
45 quick storage and access.
46 **/
47 template<class t_index_type>
48 class BufferAllocator<bool, t_index_type, false>
49 {
50 public:
51 explicit BufferAllocator()
52 : m_buffer(nullptr)
53 , m_filled_size(0)
55 {}
56
57 BufferAllocator(BufferAllocator&& allocator) noexcept
58 : m_buffer(nullptr)
59 , m_filled_size(0)
61 {
62 std::swap(allocator.m_buffer, m_buffer);
63 std::swap(allocator.m_filled_size, m_filled_size);
64 std::swap(allocator.m_allocated_size, m_allocated_size);
65 }
67 {
68 if (m_allocated_size != 0)
69 free(m_buffer);
70 }
71 template<bool t_managed>
72 void createSpace(t_index_type size)
73 {
74 m_filled_size += size;
76 }
77 template<bool t_managed>
78 void createSpace(t_index_type location, t_index_type size)
79 {
81 bitmove(begin() + location + size, begin() + location, m_filled_size - (size + location));
82 }
83 void addLast()
84 {
86 }
88 {
90 }
91 void addIndex()
92 {
94 }
95 void addIndex(t_index_type location)
96 {
97 lib_assert(location <= m_filled_size, "Out of bounds add all");
99 bitmove(begin() + location + 1, begin() + location, (m_filled_size - location - 1));
100 }
101 void removeIndex(t_index_type location)
102 {
103 lib_assert(location <= m_filled_size, "Out of bounds add all");
104 bitmove(begin() + location, begin() + location + 1, (m_filled_size - location));
106 }
107 sint04 compare(const BufferAllocator& allocator) const
108 {
109 t_index_type min_size = bitset_wrd(getMin(allocator.filledSize(), filledSize()));
110 sint04 cmp_value = cast<sint04>(memcmp(m_buffer, allocator.m_buffer, min_size));
111 return cmp_value;
112 }
113 sint04 compare(const BufferAllocator& allocator, t_index_type start, t_index_type end) const
114 {
115 sint04 cmp_value = memcmp(&(m_buffer[start]), &(allocator.m_buffer[start]), getMin(allocator.filledSize(), filledSize(), end));
116 return cmp_value;
117 }
118 void swap(t_index_type index_a, t_index_type index_b)
119 {
120 std::swap(m_buffer[index_a], m_buffer[index_b]);
121 }
122 void clear()
123 {
124 m_filled_size = 0;
125 }
126 void setSize(t_index_type size)
127 {
128 m_filled_size = size;
130 }
131 BitReference get(t_index_type index)
132 {
133 lib_assert(index < m_filled_size, "Array out of bounds");
134 return BitReference(m_buffer[bitset_wrd(index)], bitset_idx(index));
135 }
136 bool get(t_index_type index) const
137 {
138 lib_assert(index < m_filled_size, "Array out of bounds");
139 return m_buffer[bitset_wrd(index)][bitset_idx(index)];
140 }
142 {
143 return BitIterator(m_buffer, 0);
144 }
146 {
147 return ConstBitIterator(m_buffer, 0);
148 }
149 BitIterator begin(t_index_type index) const
150 {
151 return BitIterator(m_buffer, cast<sint04>(index));
152 }
153
154 t_index_type capacity() const
155 {
156 return m_allocated_size;
157 }
159 {
161 }
163 {
165 }
166 BitIterator end(t_index_type index)
167 {
168 return BitIterator(m_buffer, m_filled_size - index);
169 }
170
172 {
173 return m_buffer;
174 }
175
176 const BitFlag* ptr() const
177 {
178 return m_buffer;
179 }
180 t_index_type memSize() const
181 {
182 if (m_filled_size == 0)
183 return 0;
184 return bitset_wrd(m_filled_size - 1) + 1;
185 }
186 void setAll(const bool& object, t_index_type offset, t_index_type size)
187 {
188 if (size == 0)
189 return;
190
191 t_index_type first_word = bitset_wrd(offset);
192 t_index_type last_word = bitset_wrd(offset + size - 1);
193 t_index_type foffset = bitset_idx(offset);
194 t_index_type loffset = bitset_idx(offset + size - 1);
195
196 if (first_word == last_word)
197 {
198 uint01 mask = bitmask(size) << foffset;
199 if(object)
200 m_buffer[first_word] |= BitFlag(mask);
201 else
202 m_buffer[first_word] &= BitFlag(~mask);
203 }
204 else
205 {
206 // Set first word
207 if (object)
208 m_buffer[first_word] |= BitFlag(~bitmask(foffset));
209 else
210 m_buffer[first_word] &= BitFlag(bitmask(foffset));
211 memset(m_buffer + first_word + 1, object ? 0xFF : 0, last_word - (first_word + 1));
212
213 if (object)
214 m_buffer[last_word] |= BitFlag(bitmask(loffset + 1));
215 else
216 m_buffer[last_word] &= BitFlag(~bitmask(loffset + 1));
217 }
218#ifdef _DEBUG
219 for (uint04 i = 0; i < size; i++)
220 lib_assert(get(i + offset) == object, "Bad optimized set");
221#endif
222 }
223 template<bool is_primitive>
224 void setAll(const bool* src, t_index_type offset, t_index_type size)
225 {
226 for (t_index_type i = 0; i < size; i++)
227 {
228 get(i + offset) = src[i];
229 }
230 }
231
232 template<bool is_primitive>
233 void setAll(const BufferAllocator& allocator, t_index_type offset, t_index_type other_offset, t_index_type size)
234 {
235 if(bitset_idx(offset) == 0 && bitset_idx(other_offset) == 0)//if we are memory aligned
236 {
237 t_index_type new_size = bitset_wrd(size);
238 t_index_type new_offset = bitset_wrd(offset);
239 t_index_type new_other_offset = bitset_wrd(other_offset);
240 memmove(m_buffer + new_offset, allocator.m_buffer + new_other_offset, new_size);
241 for (t_index_type i = 8 * new_size; i < size; i++)
242 {
243 get(i + offset) = allocator.get(i + other_offset);
244 }
245 }
246 for (t_index_type i = 0; i < size; i++)
247 {
248 get(i + offset) = allocator.get(i + other_offset);
249 }
250 }
251 template<class t_other_allocator>
252 void setAllFromSource(const t_other_allocator& allocator, t_index_type offset, t_index_type other_offset, t_index_type size)
253 {
254 for (t_index_type i = 0; i < size; i++)
255 get(i + offset) = allocator.get(i + other_offset);
256 }
257 template<bool t_managed>
259 {
260 if ((t_managed && m_filled_size > m_allocated_size) || m_filled_size == m_allocated_size + 1)//We only 1, assume more to come shortly and allocate more space than required
261 {
262 lib_assert(cast<uint08>((t_managed ? m_filled_size : m_allocated_size) * 3) / 2 < cast<uint08>(Constant<uint04>::Max), "Buffer overflow");
264 }
265 else if (m_filled_size > m_allocated_size) //We added more than 1, increase buffer only once for compaction
266 {
268 }
269 }
270 void removeAllIndex(t_index_type start, t_index_type end)
271 {
272 if (end == m_filled_size)
273 {
274 m_filled_size = start;
275 }
276 else
277 {
278 bitmove(begin() + start, begin() + end, (m_filled_size - end));
279 m_filled_size -= (end - start);
280 }
281 }
282
283 t_index_type filledSize() const
284 {
285 return m_filled_size;
286 }
287 t_index_type count(const bool& value) const
288 {
289 uint04 count = 0;
290 for (uint04 i = 0; i < m_filled_size; i++)
291 {
292 if (get(i) == value)
293 ++count;
294 }
295 return count;
296 //return value ? numSet() : filledSize() - numSet();
297 }
298
299 inline BufferAllocator& operator=(BufferAllocator&& value) noexcept
300 {
301 std::swap(value.m_buffer, m_buffer);
302 std::swap(value.m_filled_size, m_filled_size);
303 std::swap(value.m_allocated_size, m_allocated_size);
304 return *this;
305 }
306
307 inline void resizeSpace(t_index_type new_size)
308 {
309 t_index_type byte_size = new_size == 0 ? 0 : bitset_wrd(new_size - 1) + 1;
310 if (new_size == 0)
311 {
312 if (m_allocated_size != 0)
313 free(m_buffer);
314 m_buffer = nullptr;
315 }
316 else
317 {
318 if (m_allocated_size == 0)
319 m_buffer = cast<BitFlag*>(malloc(byte_size));
320 else
321 m_buffer = cast<BitFlag*>(realloc(m_buffer, byte_size));
322 lib_assert(m_buffer != nullptr, "Unable to allocate buffer");
323 }
324 m_allocated_size = 8 * byte_size;
325 }
326
327 public:
328 t_index_type numSet() const
329 {
330 static const t_index_type BitsSetTable256[256] =
331 {
332 # define NDV_B2(n) n, n+1, n+1, n+2
333 # define NDV_B4(n) NDV_B2(n), NDV_B2(n+1), NDV_B2(n+1), NDV_B2(n+2)
334 # define NDV_B6(n) NDV_B4(n), NDV_B4(n+1), NDV_B4(n+1), NDV_B4(n+2)
335 NDV_B6(0), NDV_B6(1), NDV_B6(1), NDV_B6(2)
336 };
337 t_index_type flag_size = bitset_wrd(filledSize());
338 t_index_type num_set = 0;
339 uint01* mask = new uint01(1 << (filledSize() + 1)) - 1;
340 flag_size = flag_size ^ ((flag_size ^ filledSize()) & *mask);
341 BitFlag k(~*mask);
342 for (t_index_type i = 0; i < flag_size; i++)
343 {
344 num_set += BitsSetTable256[m_buffer[i]];
345 }
346 const uint01 size_mod_8 = bitset_idx(filledSize());
347 if (size_mod_8 != 0)
348 {
349 for (t_index_type i = 0; i < size_mod_8; i++)
350 {
351 num_set += m_buffer[flag_size][i] ? 1 : 0;
352 }
353 }
354 return num_set;
355 }
356
357 protected:
358 static void bitmove(BitIterator dst, BitIterator src, t_index_type size)
359 {
360 if (dst == src)
361 {
362 return;
363 }
364 if (dst < src)//prevent overlap
365 {
366 for (t_index_type i = 0; i < size; i++)
367 {
368 *dst = *src;
369 ++dst;
370 ++src;
371 }
372 }
373 else
374 {
375 for (t_index_type i = size - 1; !IsInvalid(i); i--)
376 {
377 *(dst + i) = *(src + i);
378 }
379 }
380 }
381 void setFlag(const t_index_type index, const bool value)
382 {
383 m_buffer[bitset_wrd(index)](index & 7, value);
384 }
385
386 public:
387 void invert()
388 {
389 const t_index_type byte_size = memSize();
390 for (t_index_type i = 0; i < byte_size; i++)
391 {
392 m_buffer[i] = ~m_buffer[i];
393 }
394 }
396 {
397 lib_assert(memSize() == buffer.memSize(), "Cannot ^= two buffers of different length");
398 const t_index_type byte_size = memSize();
399 for (t_index_type i = 0; i < byte_size; i++)
400 m_buffer[i] &= (~buffer.m_buffer[i]);
401 }
403 {
404 lib_assert(memSize() == buffer.memSize(), "Cannot ^= two buffers of different length");
405 const t_index_type byte_size = memSize();
406 for (t_index_type i = 0; i < byte_size; i++)
407 m_buffer[i] ^= buffer.m_buffer[i];
408 }
410 {
411 lib_assert(memSize() == buffer.memSize(), "Cannot |= two buffers of different length");
412 const t_index_type byte_size = memSize();
413 for (t_index_type i = 0; i < byte_size; i++)
414 m_buffer[i] |= buffer.m_buffer[i];
415 }
417 {
418 lib_assert(memSize() == buffer.memSize(), "Cannot &= two buffers of different length");
419 const t_index_type byte_size = memSize();
420 for (t_index_type i = 0; i < byte_size; i++)
421 m_buffer[i] &= buffer.m_buffer[i];
422 }
423 protected:
425 t_index_type m_filled_size;
426 t_index_type m_allocated_size;
427 };
428#undef bitset_wrd
429#undef bitset_idx
430#undef bitmaskt
431#undef bitmask
432}
433
#define NDV_B6(n)
#define bitset_idx(pos)
Definition BoolBuffer.hpp:39
#define bitmask(nbits)
Definition BoolBuffer.hpp:41
#define bitset_wrd(pos)
Definition BoolBuffer.hpp:38
#define lib_assert(expression, message)
Definition LibAssert.h:61
A bitset that stores 8 bits (elements with only two possible values: 0 or 1, true or false,...
Definition BitFlag.hpp:55
Simple bit iterator, typically used for parsing Buffer of bools in loops.
Definition BitIterator.hpp:45
A convenience class used with Buffers or Vectors of bools for referencing or acting on a single bit.
Definition BitReference.hpp:42
void createSpace(t_index_type location, t_index_type size)
Definition BoolBuffer.hpp:78
void inverseAndEquals(const BufferAllocator< bool, t_index_type > &buffer)
Definition BoolBuffer.hpp:395
sint04 compare(const BufferAllocator &allocator, t_index_type start, t_index_type end) const
Definition BoolBuffer.hpp:113
void setAllFromSource(const t_other_allocator &allocator, t_index_type offset, t_index_type other_offset, t_index_type size)
Definition BoolBuffer.hpp:252
void createSpace(t_index_type size)
Definition BoolBuffer.hpp:72
BitIterator begin()
Definition BoolBuffer.hpp:141
t_index_type m_filled_size
Definition BoolBuffer.hpp:425
void addIndex(t_index_type location)
Definition BoolBuffer.hpp:95
ConstBitIterator end() const
Definition BoolBuffer.hpp:162
sint04 compare(const BufferAllocator &allocator) const
Definition BoolBuffer.hpp:107
t_index_type numSet() const
Definition BoolBuffer.hpp:328
static void bitmove(BitIterator dst, BitIterator src, t_index_type size)
Definition BoolBuffer.hpp:358
t_index_type capacity() const
Definition BoolBuffer.hpp:154
BitIterator end()
Definition BoolBuffer.hpp:158
void allocationSizeCheck()
Definition BoolBuffer.hpp:258
void removeAllIndex(t_index_type start, t_index_type end)
Definition BoolBuffer.hpp:270
const ConstBitIterator begin() const
Definition BoolBuffer.hpp:145
void operator|=(const BufferAllocator< bool, t_index_type > &buffer)
Definition BoolBuffer.hpp:409
void setAll(const bool *src, t_index_type offset, t_index_type size)
Definition BoolBuffer.hpp:224
t_index_type filledSize() const
Definition BoolBuffer.hpp:283
BitReference get(t_index_type index)
Definition BoolBuffer.hpp:131
void swap(t_index_type index_a, t_index_type index_b)
Definition BoolBuffer.hpp:118
BufferAllocator(BufferAllocator &&allocator) noexcept
Definition BoolBuffer.hpp:57
void operator^=(const BufferAllocator< bool, t_index_type > &buffer)
Definition BoolBuffer.hpp:402
BufferAllocator & operator=(BufferAllocator &&value) noexcept
Definition BoolBuffer.hpp:299
void invert()
Definition BoolBuffer.hpp:387
BitIterator end(t_index_type index)
Definition BoolBuffer.hpp:166
void removeIndex(t_index_type location)
Definition BoolBuffer.hpp:101
void setFlag(const t_index_type index, const bool value)
Definition BoolBuffer.hpp:381
t_index_type m_allocated_size
Definition BoolBuffer.hpp:426
BitFlag * ptr()
Definition BoolBuffer.hpp:171
void addLast()
Definition BoolBuffer.hpp:83
bool get(t_index_type index) const
Definition BoolBuffer.hpp:136
t_index_type memSize() const
Definition BoolBuffer.hpp:180
t_index_type count(const bool &value) const
Definition BoolBuffer.hpp:287
void clear()
Definition BoolBuffer.hpp:122
BitIterator begin(t_index_type index) const
Definition BoolBuffer.hpp:149
~BufferAllocator()
Definition BoolBuffer.hpp:66
void resizeSpace(t_index_type new_size)
Definition BoolBuffer.hpp:307
BitFlag * m_buffer
Definition BoolBuffer.hpp:424
void setAll(const bool &object, t_index_type offset, t_index_type size)
Definition BoolBuffer.hpp:186
void setAll(const BufferAllocator &allocator, t_index_type offset, t_index_type other_offset, t_index_type size)
Definition BoolBuffer.hpp:233
void operator&=(const BufferAllocator< bool, t_index_type > &buffer)
Definition BoolBuffer.hpp:416
const BitFlag * ptr() const
Definition BoolBuffer.hpp:176
void setSize(t_index_type size)
Definition BoolBuffer.hpp:126
void removeLast()
Definition BoolBuffer.hpp:87
void addIndex()
Definition BoolBuffer.hpp:91
Specific logic for reserving memory for a Buffer. When managed, and more memory is needed memory is r...
Definition Pointer.hpp:311
void createSpace(t_index_type size)
Definition MemoryManager.h:400
t_index_type m_filled_size
Definition MemoryManager.h:1122
t_type * end()
Definition MemoryManager.h:713
void allocationSizeCheck()
Definition MemoryManager.h:958
constexpr t_index_type filledSize() const
Definition MemoryManager.h:1091
t_type & get(t_index_type index)
Definition MemoryManager.h:593
t_index_type m_allocated_size
Definition MemoryManager.h:1124
t_index_type memSize() const
Definition MemoryManager.h:626
t_type * begin()
Definition MemoryManager.h:641
void resizeSpace(t_index_type new_size)
Definition MemoryManager.h:766
t_type * m_buffer
Definition MemoryManager.h:1121
t_index_type count(const t_type &value) const
Definition MemoryManager.h:422
Simple bit iterator, typically used for parsing Buffer of bools in loops.
Definition BitIterator.hpp:181
Definition ACIColor.h:37
int32_t sint04
-Defines an alias representing a 4 byte, signed integer. -Can represent exact integer values -2147483...
Definition BaseValues.hpp:64
constexpr bool IsInvalid(const t_type &value)
Query if 'value' is valid or invalid. Invalid values should return invalid if used for calculations o...
Definition BaseFunctions.hpp:170
uint8_t uint01
-Defines an alias representing a 1 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:80
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:96
constexpr t_to cast(const Angle< t_from > &value)
Definition Angle.h:375
constexpr t_type getMin(const t_type &left, const t_type &right)
Finds the minimum of the given arguments based on the < operator Author: Tyler Parke Date: 2017-11-05...
Definition BaseFunctions.hpp:56
Defines for a given type (such as sint04, fltp08, UUID, etc) a maximum, minimum, and reserved 'invali...
Definition BaseValues.hpp:233