API Documentation
Loading...
Searching...
No Matches
Buffer.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: Buffer
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include <NDEVR/BaseValues.h>
34#include <NDEVR/LibAssert.h>
35#include <NDEVR/ObjectAllocator.h>
36#include <NDEVR/BufferAllocator.h>
37#include <NDEVR/ObjectInfo.h>
38#include <initializer_list>
39#include <utility>
40#include <functional>
41namespace NDEVR
42{
43 /**--------------------------------------------------------------------------------------------------
44 \brief The equivelent of std::vector but with a bit more control. The basic array unit of the library.
45
46 t_type = what the buffer holds
47 t_index_type = the index reference (default uint04 but can be made uint08 for large buffer support)
48 t_memory_allocator = The object in charge of object allocation when creating space
49 t_memory_manager = The thing that actually stores the memory
50 Author: Tyler Parke
51
52 Date: 2017-11-19
53 */
54 template<class t_type, class t_index_type = uint04, class t_memory_allocator = ObjectAllocator<ObjectInfo<t_type>::Primitive, t_index_type>, class t_memory_manager = BufferAllocator<t_type, t_index_type, false>>
56 {
57 public:
58 /**
59 Creates an empty buffer
60 **/
61 constexpr Buffer()
62 : m_memory_interface()
63 {}
64
65 /**
66 Optimized copy consturctor
67 **/
68 constexpr Buffer(const Buffer& buffer)
69 : m_memory_interface()
70 {
71 addAll(buffer);
72 }
73
74 /**
75 Optimized move constructor
76 **/
77 constexpr Buffer(Buffer&& buffer) noexcept
78 : m_memory_interface(std::move(buffer.m_memory_interface))
79 {}
80
81 /**
82 Constuctor that reserves space. Note that the buffer will still be empty, but allocation
83 will be more efficient using add or inserts.
84 **/
85 explicit Buffer(t_index_type size)
86 : m_memory_interface()
87 {
88 m_memory_interface.resizeSpace(size);
89 }
90
91 /**
92 Constuctor that allows for an a start pointer, and size, and adds all elements to the buffer
93 **/
94 explicit Buffer(const t_type* buffer, t_index_type size)
95 : m_memory_interface()
96 {
97 if (size != 0)
98 addAll(buffer, size);
99 }
100
101 /**
102 Constuctor that allows for a set size, and then fills the buffer with the specified object
103 **/
104 Buffer(t_index_type size, const t_type& fill_object)
105 : m_memory_interface()
106 {
107 m_memory_interface.template createSpace<false>(size);
108 t_memory_allocator::template AllocateElement<t_type>(m_memory_interface, 0, size, fill_object);
109 }
110
111 /**
112 Constuctor that allows for an initializer list, allowing { and } to be used
113 **/
114 Buffer(std::initializer_list<t_type> l)
115 : m_memory_interface()
116 {
117 addAll(l.begin(), cast<t_index_type>(l.size()));
118 }
119
120 /**
121 Constuctor that allows for an iterator begin and end.
122 **/
123 template<class t_iterator>
124 Buffer(const t_iterator& begin, const t_iterator& end)
125 : m_memory_interface()
126 {
127 setSize(cast<t_index_type>(std::distance(begin, end)));
128 uint04 index = 0;
129 for (auto iter = begin; iter != end; iter++)
130 {
131 get(index++) = *iter;
132 }
133 }
134
135 /**
136 Destructor.
137
138 Author: Tyler Parke
139
140 Date: 2017-11-19
141 **/
142
144 {
145 t_memory_allocator::template Deallocate<t_type>(m_memory_interface, 0, size());
146 }
147
148 /**
149 \brief Gets the first location of type* in the array.
150 \return A const pointer to the beginning of the array.
151 **/
152 operator const t_type* () const
153 {
154 return begin();
155 }
156
157 /**
158 \brief Gets the first location of type* in the array.
159 \return A const pointer to the beginning of the array.
160 **/
161 operator t_type* ()
162 {
163 return begin();
164 }
165
166 /**
167 \brief Gets a copy of this buffer, with filled objects t_other_type, where all objects are created using
168 the contents of this buffer.
169 \return a copy of the buffer.
170 **/
171 template<class t_other_type, class t_other_index_type = uint04, class t_other_memory_allocator = ObjectAllocator<ObjectInfo<t_other_type>::Primitive>, class t_other_memory_manager = BufferAllocator<t_other_type, t_index_type, false>>
173 {
175 for (t_index_type i = 0; i < size(); i++)
176 {
177 other.add(t_other_type(get(i)));
178 }
179 return other;
180 }
181
182 /**
183 \brief Adds object to the end of the buffer.
184 \param[in] object The object to add to the end.
185 **/
186 void add(t_type&& object)
187 {
188 m_memory_interface.addIndex();
189 t_memory_allocator::template AllocateElement(m_memory_interface, size() - 1, std::move(object));
190 }
191 /**
192 \brief Adds object to the end of the buffer.
193 \param[in] object The object to add to the end.
194 **/
195 void add(const t_type& object)
196 {
197 m_memory_interface.addIndex();
198 t_memory_allocator::template AllocateElement(m_memory_interface, size() - 1, object);
199 }
200
201 /**
202 \brief Adds and object to a specific location. Equivelent to insert
203 \param[in] location The index where the object should be inserted.
204 \param[in] object The object to add to the buffer at the specified location.
205 **/
206 void add(t_index_type location, const t_type& object)
207 {
208 m_memory_interface.addIndex(location);
209 t_memory_allocator::template AllocateElement(m_memory_interface, location, object);
210 }
211 /**
212 \brief Adds an object to a specific location. Equivelent to insert.
213 \param[in] location The index where the object should be inserted.
214 \param[in] object The object to add to the buffer at the specified location.
215 **/
216 void add(t_index_type location, t_type&& object)
217 {
218 m_memory_interface.addIndex(location);
219 t_memory_allocator::template AllocateElement(m_memory_interface, location, std::move(object));
220 }
221
222 /**
223 \brief Adds an object to a specific location.
224 \param[in] location The index where the object should be inserted.
225 \param[in] object The object to add to the buffer at the specified location.
226 **/
227 void insert(t_index_type location, const t_type& object)
228 {
229 m_memory_interface.addIndex(location);
230 t_memory_allocator::template AllocateElement(m_memory_interface, location, object);
231 }
232 /**
233 \brief Adds an object to a specific location.
234 \param[in] location The index where the object should be inserted.
235 \param[in] object The object to add to the buffer at the specified location.
236 **/
237 void insert(t_index_type location, t_type&& object)
238 {
239 m_memory_interface.addIndex(location);
240 t_memory_allocator::template AllocateElement(m_memory_interface, location, std::move(object));
241 }
242 template<class t_other_memory_allocator, class t_other_index_type, class t_other_memory_manager>
244 {
245 t_index_type offset = size();
246 m_memory_interface.template createSpace<false>(buffer.size());
247 if constexpr (t_memory_allocator::isPrimitive())
248 {
249 m_memory_interface.template setAll<true>(buffer.memoryInterface(), offset, 0, buffer.size());
250 }
251 else
252 {
253 for (t_index_type i = 0; i < buffer.size(); i++)
254 t_memory_allocator::template AllocateElement(m_memory_interface, i + offset, buffer[i]);
255 }
256 }
257 void addAll(const t_type* buffer, t_index_type buffer_size)
258 {
259 t_index_type offset = size();
260 m_memory_interface.template createSpace<false>(buffer_size);
261 if constexpr (t_memory_allocator::isPrimitive())
262 {
263 m_memory_interface.template setAll<true>(buffer, offset, buffer_size);
264 }
265 else
266 {
267 for (t_index_type i = 0; i < buffer_size; i++)
268 t_memory_allocator::AllocateElement(m_memory_interface, i + offset, buffer[i]);
269 }
270 }
271 void addAll(const t_type* buffer)
272 {
273 t_index_type size = 0;
274 int loc = 0;
275 for (;;)
276 {
277 if (memcmp(&buffer[size], &loc, sizeof(t_type)) == 0)
278 break;
279 ++size;
280 }
281 addAll(buffer, size);
282 }
283 void insert(t_index_type offset, const Buffer& buffer)
284 {
285 m_memory_interface.template createSpace<false>(offset, buffer.size());
286 if constexpr (t_memory_allocator::isPrimitive())
287 {
288 m_memory_interface.template setAll<true>(buffer.m_memory_interface, offset, 0, buffer.size());
289 }
290 else
291 {
292 for (t_index_type i = 0; i < buffer.size(); i++)
293 t_memory_allocator::AllocateElement(m_memory_interface, i + offset, buffer[i]);
294 }
295 }
296 void replaceIndexRange(t_index_type offset, t_index_type replace_size, const Buffer& buffer)
297 {
298 lib_assert(offset + replace_size <= size(), "end > size in buffer replace");
299 if (replace_size < buffer.size())
300 {
301 t_index_type size_dff = buffer.size() - replace_size;
302 m_memory_interface.template createSpace<false>(offset, size_dff);
303 if constexpr (!t_memory_allocator::isPrimitive())
304 {
305 for (t_index_type i = 0; i < size_dff; i++)
306 t_memory_allocator::AllocateElement(m_memory_interface, i + offset, buffer[i]);
307 }
308 }
309 else if (replace_size > buffer.size())
310 {
311 removeAllIndex(offset, offset + (replace_size - buffer.size()));
312 }
313 setAll(buffer, offset, buffer.size());
314 }
315
316
317#ifdef __clang__
318 #pragma clang diagnostic push
319 #pragma clang diagnostic ignored "-Wunused-value"//Weird error in clang thinks expression result not used
320#endif
321 /**
322 \brief Inserts data into the buffer.
323 \param[in] offset The offset where the data should be inserted.
324 \param[in] buffer The buffer of objects to insert.
325 \param[in] buffer_size number of elements of the data to insert.
326 **/
327 void insert(t_index_type offset, const t_type* const buffer, t_index_type buffer_size)
328 {
329 m_memory_interface.template createSpace<false>(offset, buffer_size);
330 if constexpr (t_memory_allocator::isPrimitive())
331 {
332 m_memory_interface.template setAll<true>(buffer, offset, buffer_size);
333 }
334 else
335 {
336 for (t_index_type i = 0; i < buffer_size; i++)
337 t_memory_allocator::AllocateElement(m_memory_interface, i + offset, buffer[i]);
338 }
339 }
340#ifdef __clang__
341 #pragma clang diagnostic pop
342#endif
343 /**
344 \brief Inserts data into the buffer, assumed to be null terminated.
345 \param[in] location The offset where the data should be inserted.
346 \param[in] buffer The buffer.
347 **/
348 void insert(const t_index_type location, const t_type* buffer)
349 {
350 t_index_type size = 0;
351 int loc = 0;
352 for (;;)
353 {
354 if (memcmp(&buffer[size], &loc, sizeof(t_type)) == 0)
355 break;
356 ++size;
357 }
358 insert(location, buffer, size);
359 }
360
361 /**
362 \brief Adds a space to the end of the buffer.
363 \param[in] space_to_add The number of elements to add.
364 **/
365 template<bool t_managed>
366 void addSpace(t_index_type space_to_add)
367 {
368 const t_index_type offset = size();
369 m_memory_interface.template createSpace<t_managed>(space_to_add);
370 t_memory_allocator::template Allocate<t_type>(m_memory_interface, offset, size() - offset);
371 }
372 template<bool t_managed = false>
373 void addAndFillSpace(t_index_type space_to_add, const t_type& fill_object)
374 {
375 const t_index_type offset = size();
376 m_memory_interface.template createSpace<t_managed>(space_to_add);
377 t_memory_allocator::template AllocateElement<t_type>(m_memory_interface, offset, size() - offset, fill_object);
378 }
379 template<bool t_managed>
380 void addSpace(t_index_type location, t_index_type size)
381 {
382 lib_assert(location <= this->size(), "Tried to insert into a bad location");
383 m_memory_interface.template createSpace<t_managed>(location, size);
384
385 t_memory_allocator::template Allocate<t_type>(m_memory_interface, location, size);
386 }
387 [[nodiscard]] decltype(auto) ptr()
388 {
389 return m_memory_interface.ptr();
390 }
391
392 [[nodiscard]] decltype(auto) ptr() const
393 {
394 return m_memory_interface.ptr();
395 }
396
397 [[nodiscard]] t_index_type memSize() const
398 {
399 return m_memory_interface.memSize();
400 }
401
402 [[nodiscard]] decltype(auto) begin()
403 {
404 return m_memory_interface.begin();
405 }
406
407 [[nodiscard]] decltype(auto) begin() const
408 {
409 return m_memory_interface.begin();
410 }
411
412 [[nodiscard]] decltype(auto) begin(t_index_type index) const
413 {
414 return m_memory_interface.begin(index);
415 }
416
417 [[nodiscard]] t_index_type capacity() const
418 {
419 return m_memory_interface.capacity();
420 }
421
422 void clear()
423 {
424 t_memory_allocator::template Deallocate<t_type>(m_memory_interface, 0U, size());
425 m_memory_interface.clear();
426 }
427 void clear(t_index_type new_capacity)
428 {
429 t_memory_allocator::template Deallocate<t_type>(m_memory_interface, 0, size());
430 m_memory_interface.clear();
431 ensureCapacity(new_capacity, true, true);
432 }
433
434 /**
435 \brief Compares this Buffer to another to determine their relative ordering.
436 \param[in] value The Buffer to compare to this object.
437 \returns Negative if 'value' is less than '', 0 if they are equal, or positive if it is greater.
438 **/
439 [[nodiscard]] sint04 compare(const Buffer& value) const
440 {
441 sint04 cmp_value = m_memory_interface.compare(value.m_memory_interface);
442 if (cmp_value != 0)
443 return cmp_value;
444 else if (value.size() > size())
445 return -1;
446 else if (value.size() < size())
447 return 1;
448 else
449 return 0;
450 }
451 [[nodiscard]] sint04 compare(const Buffer& value, t_index_type start, t_index_type end) const
452 {
453 sint04 cmp_value = m_memory_interface.compare(value.m_memory_interface, start, end);
454 if (cmp_value != 0)
455 return cmp_value;
456 else if (value.size() == size())
457 return 0;
458 else if (end > size())
459 return -1;
460 else if (end > value.size())
461 return 1;
462 else
463 return 0;
464 }
465 [[nodiscard]] bool contains(const t_type& element) const
466 {
467 for (t_index_type i = 0; i < size(); ++i)
468 {
469 if (get(i) == element)
470 return true;
471 }
472 return false;
473 }
474 [[nodiscard]] bool contains(const t_type& element, const std::function<bool(const t_type&, const t_type&)>& equal_function) const
475 {
476 for (uint04 i = 0; i < size(); ++i)
477 {
478 if (equal_function(get(i), element))
479 return true;
480 }
481 return false;
482 }
483 [[nodiscard]] bool contains(const t_type& element, t_index_type start) const
484 {
485 lib_assert(start < size(), "buffer contains using bad start value");
486 for (t_index_type i = start; i < size(); ++i)
487 {
488 if (get(i) == element)
489 return true;
490 }
491 return false;
492 }
493 [[nodiscard]] bool contains(const t_type& element, t_index_type start, t_index_type search_size) const
494 {
495 lib_assert(search_size + start <= size(), "buffer contains using bad start value");
496 for (t_index_type i = start; i < start + search_size; ++i)
497 {
498 if (get(i) == element)
499 return true;
500 }
501 return false;
502 }
503 [[nodiscard]] t_index_type count(const t_type& element) const
504 {
505 return m_memory_interface.count(element);
506 }
507 decltype(auto) end()
508 {
509 return m_memory_interface.end();
510 }
511 [[nodiscard]] decltype(auto) end() const
512 {
513 return m_memory_interface.end();
514 }
515 decltype(auto) end(t_index_type index)
516 {
517 return m_memory_interface.end(index);
518 }
519 void ensureCapacity(t_index_type new_capacity, bool ensure_not_greater = false, bool ensure_not_less = true)
520 {
521 if (new_capacity == capacity())
522 return;
523 if (new_capacity > capacity())
524 {
525 if (ensure_not_less)
526 m_memory_interface.resizeSpace(new_capacity);
527 }
528 else if (ensure_not_greater)
529 {
530 lib_assert(new_capacity >= size(), "Array can't have capacity less than size");
531 m_memory_interface.resizeSpace(new_capacity);
532 }
533 }
534 [[nodiscard]] bool equals(const Buffer& buffer) const
535 {
536 if (size() == buffer.size())
537 return _equals<t_memory_allocator::isPrimitive()>(buffer);
538 else
539 return false;
540 }
541 [[nodiscard]] decltype(auto) get(t_index_type index)
542 {
543 lib_assert(index < size(), "Buffer out of bounds");
544 return m_memory_interface.get(index);
545 }
546 [[nodiscard]] decltype(auto) get(t_index_type index) const
547 {
548 lib_assert(index < size(), "Buffer out of bounds");
549 return m_memory_interface.get(index);
550 }
551
552
553 [[nodiscard]] Buffer getAll(t_index_type start, t_index_type size)
554 {
555 Buffer buff(size);
556 buff.addAll(begin(start), size);
557 return buff;
558 }
559 [[nodiscard]] t_index_type indexOf(const t_type& element) const
560 {
561 for (t_index_type i = 0; i < size(); ++i)
562 {
563 if (get(i) == element) return i;
564 }
566 }
567 [[nodiscard]] t_index_type indexOf(const t_type& element, t_index_type start_pos) const
568 {
569 for (t_index_type i = start_pos; i < size(); ++i)
570 {
571 if (get(i) == element) return i;
572 }
574 }
575 [[nodiscard]] t_index_type indexOf(const t_type& element, t_index_type start_pos, t_index_type search_size) const
576 {
577 lib_assert(search_size + start_pos <= size(), "bad index of in equation");
578 for (t_index_type i = start_pos; i < start_pos + search_size; ++i)
579 {
580 if (get(i) == element) return i;
581 }
583 }
584 [[nodiscard]] bool isEmpty() const
585 {
586 return size() == 0;
587 }
588 [[nodiscard]] decltype(auto) last()
589 {
590 lib_assert(size() != 0, "Cannot get last: out of bounds");
591 return get(size() - 1);
592 }
593 [[nodiscard]] decltype(auto) last() const
594 {
595 lib_assert(size() != 0, "Cannot get last: out of bounds");
596 return get(size() - 1);
597 }
598 [[nodiscard]] t_index_type lastIndexOf(const t_type& element) const
599 {
600 for (t_index_type i = size() - 1; i < size(); --i)
601 {
602 if (get(i) == element) return i;
603 }
605 }
606 void removeIndex(t_index_type location)
607 {
608 lib_assert(location < size(), "Out of bounds remove");
609 t_memory_allocator::template Deallocate<t_type>(m_memory_interface, location, 1);
610 m_memory_interface.removeIndex(location);
611 }
612 void removeIndexBackSwap(t_index_type location)
613 {
614 swapIndices(location, size() - 1);//swap with back
615 removeLast();//remove back
616 }
617 bool removeElement(const t_type& element)
618 {
619 for (t_index_type i = size() - 1; !IsInvalid(i); --i)//start at last element as less expensive to removeRows
620 {
621 if (get(i) == element)
622 {
623 removeIndex(i);
624 return true;
625 }
626 }
627 return false;
628 }
630 {
631 lib_assert(size() > 0, "Cannot remove last from empty buffer");
632 t_memory_allocator::template Deallocate<t_type>(m_memory_interface, size() - 1, 1);
633 m_memory_interface.removeLast();
634 }
635
636 /**
637 \brief Removes all unordered described by object. This function does not preserve the order of the buffer.
638 \warning This function does not preserve the order of the buffer.
639 \param[in] object The object to remove.
640 **/
641 void removeAllUnordered(const t_type& object)
642 {
643 t_index_type end = size();
644 for (t_index_type i = 0; i < end; i++)
645 {
646 if (get(i) == object)
647 {
648 swapIndices(i, --end);
649 --i;
650 }
651 }
652 if (end != size())
654 }
655
656 /**
657 \brief Removes all items based on the functor. The functor should return true if the
658 item is deleted or false if the item should stay in the array. Faster function then removeAllOrdered but
659 order is not preserved.
660 \warning This function does not preserve the order of the buffer.
661 \param[in] functor A functor that takes a value and returns true if value is to be removed, or false otherwise.
662 **/
663 template<class t_functor>
664 void removeAllUnordered(const t_functor& functor)
665 {
666 t_index_type end = size();
667 for (t_index_type i = 0; i < end; i++)
668 {
669 if (functor(get(i)))
670 {
671 swapIndices(i--, --end);
672 }
673 }
674 if (end != size())
676 }
677
678 /**
679 \brief Removes all instances of the object. Function is slower than removeAllUnordered but
680 order is preserved.
681 \param[in] object The object.
682 **/
683 void removeAllOrdered(const t_type& object)
684 {
685 t_index_type start = 0;
686 uint04 end = size();
687 for (t_index_type i = 0; i < end; i++)
688 {
689 get(start) = get(i);
690 if (get(i) != object)
691 ++start;
692 }
693 if (start != end)
694 m_memory_interface.removeAllIndex(start, end);
695 }
696 /**
697 \brief Removes all items based on the functor. The functor should return true if the
698 item is deleted or false if the item should stay in the array. Function is slower than removeAllUnordered but
699 order is preserved.
700 \param[in] functor A functor that takes a value and returns true if value is to be removed, or false otherwise.
701 **/
702 template<class t_functor>
703 void removeAllOrderedFn(const t_functor& functor)
704 {
705 t_index_type start = 0;
706 t_index_type end = size();
707 for (t_index_type i = 0; i < end; i++)
708 {
709 get(start) = get(i);
710 if (!functor(get(i)))
711 ++start;
712 }
713 if (start != size())
714 m_memory_interface.removeAllIndex(start, size());
715 }
716 void removeAllIndex(t_index_type start, t_index_type end)
717 {
718 if (start == end)
719 return;
720 lib_assert(start <= end, "remove all start > end");
721 t_memory_allocator::template Deallocate<t_type>(m_memory_interface, start, end - start);
722 m_memory_interface.removeAllIndex(start, end);
723 }
724 template<class t_range_buffer>
725 void removeAllIndices(const t_range_buffer& ranges)
726 {
727#ifdef _DEBUG
728 uint04 last_delete_index = 0;
729#endif
730 for (const auto& range : ranges)
731 {
732 t_index_type start = range.first;
733 t_index_type end = range.second;
734#ifdef _DEBUG
735 lib_assert(last_delete_index <= start, "ranges must be ordered");
736 lib_assert(start <= end, "remove all start > end");
737 last_delete_index = end;
738#endif
739 t_memory_allocator::template Deallocate<t_type>(m_memory_interface, start, end - start);
740 }
741 m_memory_interface.removeAllIndices(ranges);
742 }
743 void replaceAll(const t_type& var, const t_type& replacement)
744 {
745 for (t_index_type i = 0; i < size(); i++)
746 {
747 if (get(i) == var)
748 get(i) = replacement;
749 }
750 }
751 void reverse()
752 {
753 for (t_index_type i = 0; i < size() / 2; i++)
754 {
755 m_memory_interface.swap(i, size() - i - 1);
756 }
757 }
758 void reverse(const t_index_type start, const t_index_type end)
759 {
760 const t_index_type size = end - start;
761 for (t_index_type i = 0; i < size / 2; i++)
762 {
763 m_memory_interface.swap(start + i, (start + size) - i - 1);
764 }
765 }
766 template<class t_o_type>
767 void setAll(const t_o_type* src, t_index_type offset, t_index_type size)
768 {
769 m_memory_interface.template setAll<t_memory_allocator::isPrimitive()>(src, offset, size);
770 }
771 void setAll(const Buffer& buffer, t_index_type offset, t_index_type size)
772 {
773 lib_assert(buffer.size() >= size, "too small of buffer being used in set all");
774 m_memory_interface.template setAll<t_memory_allocator::isPrimitive()>(buffer.m_memory_interface, offset, 0, size);
775 }
776 void setAll(const Buffer& buffer, t_index_type offset, t_index_type other_offset, t_index_type size)
777 {
778 lib_assert(buffer.size() >= size, "too small of buffer being used in set all");
779 m_memory_interface.template setAll<t_memory_allocator::isPrimitive()>(buffer.m_memory_interface, offset, other_offset, size);
780 }
781 template<class t_o_type>
782 void setAllToValue(const t_o_type& fill_element, const t_index_type offset = 0, t_index_type fill_size = Constant<t_index_type>::Invalid)
783 {
784 const t_index_type old_size = size();
785 if (IsInvalid(fill_size))
786 fill_size = old_size - offset;
787 else if(offset + fill_size > old_size)
788 {
789 m_memory_interface.setSize(offset + fill_size);
790 }
791 const t_type value(fill_element);
792 if (t_memory_allocator::isPrimitive() || size() == old_size)
793 {
794 m_memory_interface.setAll(value, offset, fill_size);
795 }
796 else
797 {
798 t_index_type size_a = old_size - offset;
799 m_memory_interface.setAll(value, offset, size_a);
800 t_memory_allocator::AllocateElement(m_memory_interface, offset + size_a, fill_size - size_a, value);
801 }
802 }
803 void setSize(t_index_type new_size)
804 {
805 if(new_size < size())
806 t_memory_allocator::template Deallocate<t_type>(m_memory_interface, new_size, size() - new_size);
807 const t_index_type old_size = size();
808 m_memory_interface.setSize(new_size);
809 if (old_size < size())
810 t_memory_allocator::template Allocate<t_type>(m_memory_interface, old_size, size() - old_size);
811 }
812 void resize(t_index_type new_size)
813 {
814 setSize(new_size);
815 }
816 void setSize(const t_index_type new_size, const t_type& fill_element)
817 {
818 const t_index_type old_size = size();
819 setSize(new_size);
820 if(old_size < new_size)
821 setAllToValue(fill_element, old_size);
822 }
823 [[nodiscard]] constexpr t_index_type size() const
824 {
825 return m_memory_interface.filledSize();
826 }
827 void swapElements(const t_type& element1, const t_type& element2)
828 {
829 if (element1 == element2)
830 return;
831 t_index_type index_1 = Constant<t_index_type>::Invalid;
832 t_index_type index_2 = Constant<t_index_type>::Invalid;
833 for (t_index_type i = 0; i < size(); i++)
834 {
835 if (get(i) == element1)
836 {
837 index_1 = i;
838 if (!IsInvalid(index_2))
839 {
840 swapIndices(index_1, index_2);
841 return;
842 }
843 }
844 else if (get(i) == element2)
845 {
846 index_2 = i;
847 if (!IsInvalid(index_1))
848 {
849 swapIndices(index_1, index_2);
850 return;
851 }
852 }
853 }
854 }
855 void swapAllElements(const t_type& element1, const t_type& element2)
856 {
857 if (element1 == element2)
858 return;
859 for (t_index_type ii = 0; ii < size(); ++ii)
860 {
861 if (get(ii) == element1)
862 get(ii) = element2;
863 else if (get(ii) == element2)
864 get(ii) = element1;
865 }
866 }
867 void swapIndices(t_index_type index_1, t_index_type index_2)
868 {
869 std::swap(get(index_1), get(index_2));
870 }
871 void move(t_index_type from, t_index_type to)
872 {
873 if (to == from)
874 return;
875 t_type object = get(from);
876 removeIndex(from);
877 if (to > from)
878 to--;
879 add(to, object);
880 }
881 void primitiveSort()
882 {
883 struct primitiveUniqueDataComparison
884 {
885 bool operator()(const t_type& lhs, const t_type& rhs)
886 {
887 return memcmp(&lhs, &rhs, sizeof(t_type)) > 0;
888 }
889 };
890 std::sort(begin(), end(), primitiveUniqueDataComparison());
891 }
892 void sort()
893 {
894 std::sort(begin(), end());
895 }
896 void sortRange(t_index_type start, t_index_type end)
897 {
898 std::sort(begin() + start, begin() + end);
899 }
900 void setUnique()
901 {
902 if constexpr (t_memory_allocator::isPrimitive())
903 primitiveSort();
904 else
905 sort();
906 removeAllIndex(cast<t_index_type>(std::unique(begin(), end()) - begin()), size());
907 }
908 void setUniquePresorted()
909 {
910 removeAllIndex(cast<t_index_type>(std::unique(begin(), end()) - begin()), size());
911 }
912 t_index_type sortAboutValue(t_index_type value_index)
913 {
914 return sortAboutValue(value_index, 0, size());
915 }
916 t_index_type sortAboutValue(t_index_type value_index, t_index_type start, t_index_type end)
917 {
918 const t_type value = get(value_index);
919 std::swap(get(value_index), get(--end));
920 t_index_type store = start;
921 for (t_index_type idx = start; idx < end; ++idx)
922 {
923 if (get(idx) <= value)
924 {
925 std::swap(get(idx), get(store));
926 store++;
927 }
928 }
929 std::swap(get(end), get(store));
930 return store;
931 }
932 inline Buffer& operator=(const Buffer& buffer)
933 {
934 if (&(buffer) == this)
935 return *this;//check to ensure not setting equal to ourselves
936 clear();
937 addAll(buffer);
938 return *this;
939 }
940 inline Buffer& operator=(Buffer&& buffer) noexcept
941 {
942 std::swap(m_memory_interface, buffer.m_memory_interface);
943 return *this;
944 }
945 [[nodiscard]] inline bool operator==(const Buffer& buffer) const
946 {
947 return equals(buffer);
948 }
949 [[nodiscard]] inline bool operator>(const Buffer& buffer) const
950 {
951 return compare(buffer) > 0;
952 }
953 [[nodiscard]] inline bool operator<(const Buffer& buffer) const
954 {
955 return compare(buffer) < 0;
956 }
957 [[nodiscard]] inline bool operator>=(const Buffer& buffer) const
958 {
959 return compare(buffer) >= 0;
960 }
961 [[nodiscard]] inline bool operator<=(const Buffer& buffer) const
962 {
963 return compare(buffer) <= 0;
964 }
965 [[nodiscard]] inline bool operator!=(const Buffer& buffer) const
966 {
967 return !equals(buffer);
968 }
969 [[nodiscard]] decltype(auto) operator[](const t_index_type index)
970 {
971 return get(index);
972 }
973 [[nodiscard]] decltype(auto) operator[](const int index)
974 {
975 return get(cast<t_index_type>(index));
976 }
977 [[nodiscard]] decltype(auto) operator[](const t_index_type value) const
978 {
979 return get(value);
980 }
981 [[nodiscard]] decltype(auto) operator[](const int index) const
982 {
983 return get(cast<t_index_type>(index));
984 }
985 [[nodiscard]] Buffer operator+(const t_type& element) const
986 {
987 Buffer<t_type, t_memory_allocator, t_memory_manager> buffer(1 + size());
988 buffer.addAll(*this);
989 buffer.add(element);
990 return buffer;
991 }
992 const Buffer& operator+=(const t_type& element)
993 {
994 add(element);
995 return *this;
996 }
997 inline Buffer& operator+=(const Buffer& value)
998 {
999 addAll(value);
1000 return (*this);
1001 }
1002 [[nodiscard]] inline Buffer operator+(const Buffer& value) const
1003 {
1004 Buffer buffer(size() + value.size());
1005 buffer.addAll(*this);
1006 buffer.addAll(value);
1007 return buffer;
1008 }
1009 [[nodiscard]] bool isSorted() const
1010 {
1011 if (size() <= 1)
1012 return true;
1013 for (t_index_type i = 0; i < size() - 1; i++)
1014 {
1015 if (get(i) >= get(i + 1))
1016 return false;
1017 }
1018 return true;
1019 }
1020 [[nodiscard]] bool isSortedSet() const
1021 {
1022 for (t_index_type i = 0; i < size() - 1; i++)
1023 {
1024 if (get(i) > get(i + 1))
1025 return false;
1026 }
1027 return true;
1028 }
1029 [[nodiscard]] constexpr static t_type Type() { t_type* ptr = nullptr; return *ptr; }
1030
1031 [[nodiscard]] constexpr t_memory_manager& memoryInterface()
1032 {
1033 return m_memory_interface;
1034 }
1035 [[nodiscard]] constexpr const t_memory_manager& memoryInterface() const
1036 {
1037 return m_memory_interface;
1038 }
1039 private:
1040 template<bool t_is_primitive>
1041 [[nodiscard]] bool _equals(const Buffer& buffer) const
1042 {
1043 if (t_is_primitive)
1044 {
1045 return compare(buffer) == 0;
1046 }
1047 else
1048 {
1049 for (t_index_type i = 0; i < size(); i++)
1050 {
1051 if (get(i) != buffer.get(i))
1052 return false;
1053 }
1054 return true;
1055 }
1056 }
1057 private:
1058 t_memory_manager m_memory_interface;
1059 };
1060 template<class t_type, class t_memory_allocator, class t_memory_manager>
1061 struct Constant<Buffer<t_type, t_memory_allocator, t_memory_manager>>
1062 {
1063 /** The Invalid value. This is the value that means the vector is 'not valid' or has an unset dimension. */
1064 inline const static Buffer<t_type, t_memory_allocator, t_memory_manager> Invalid{};
1065 };
1066}
1067#include "BoolBuffer.hpp"
#define lib_assert(expression, message)
Definition LibAssert.h:61
Specific logic for reserving memory for a Buffer. When managed, and more memory is needed memory is r...
Definition Pointer.hpp:311
A dummy class for easy tracking of inheritance with templated Buffers.
Definition ObjectInfo.h:42
The equivelent of std::vector but with a bit more control. The basic array unit of the library.
Definition Buffer.hpp:56
void add(t_index_type location, t_type &&object)
Adds an object to a specific location. Equivelent to insert.
Definition Buffer.hpp:216
decltype(auto) get(t_index_type index) const
Definition Buffer.hpp:546
constexpr Buffer()
Definition Buffer.hpp:61
bool equals(const Buffer &buffer) const
Definition Buffer.hpp:534
void add(t_type &&object)
Adds object to the end of the buffer.
Definition Buffer.hpp:186
void removeAllOrderedFn(const t_functor &functor)
Removes all items based on the functor. The functor should return true if the item is deleted or fals...
Definition Buffer.hpp:703
sint04 compare(const Buffer &value) const
Compares this Buffer to another to determine their relative ordering.
Definition Buffer.hpp:439
constexpr t_memory_manager & memoryInterface()
Definition Buffer.hpp:1031
void insert(t_index_type offset, const Buffer &buffer)
Definition Buffer.hpp:283
void addSpace(t_index_type space_to_add)
Adds a space to the end of the buffer.
Definition Buffer.hpp:366
void add(const t_type &object)
Adds object to the end of the buffer.
Definition Buffer.hpp:195
bool contains(const t_type &element) const
Definition Buffer.hpp:465
t_index_type lastIndexOf(const t_type &element) const
Definition Buffer.hpp:598
void addAll(const t_type *buffer)
Definition Buffer.hpp:271
decltype(auto) begin(t_index_type index) const
Definition Buffer.hpp:412
void removeAllUnordered(const t_type &object)
Removes all unordered described by object. This function does not preserve the order of the buffer.
Definition Buffer.hpp:641
void addAndFillSpace(t_index_type space_to_add, const t_type &fill_object)
Definition Buffer.hpp:373
t_index_type capacity() const
Definition Buffer.hpp:417
void setAll(const t_o_type *src, t_index_type offset, t_index_type size)
Definition Buffer.hpp:767
Buffer getAll(t_index_type start, t_index_type size)
Definition Buffer.hpp:553
constexpr t_index_type size() const
Definition Buffer.hpp:823
void removeAllOrdered(const t_type &object)
Removes all instances of the object. Function is slower than removeAllUnordered but order is preserve...
Definition Buffer.hpp:683
decltype(auto) ptr()
Definition Buffer.hpp:387
constexpr Buffer(Buffer &&buffer) noexcept
Definition Buffer.hpp:77
void removeAllIndex(t_index_type start, t_index_type end)
Definition Buffer.hpp:716
Buffer(std::initializer_list< t_type > l)
Definition Buffer.hpp:114
t_index_type indexOf(const t_type &element, t_index_type start_pos, t_index_type search_size) const
Definition Buffer.hpp:575
decltype(auto) last()
Definition Buffer.hpp:588
void addAll(const Buffer< t_type, t_other_index_type, t_other_memory_allocator, t_other_memory_manager > &buffer)
Definition Buffer.hpp:243
void addSpace(t_index_type location, t_index_type size)
Definition Buffer.hpp:380
void removeIndexBackSwap(t_index_type location)
Definition Buffer.hpp:612
decltype(auto) end()
Definition Buffer.hpp:507
void setSize(t_index_type new_size)
Definition Buffer.hpp:803
void replaceIndexRange(t_index_type offset, t_index_type replace_size, const Buffer &buffer)
Definition Buffer.hpp:296
t_index_type indexOf(const t_type &element) const
Definition Buffer.hpp:559
Buffer(const t_iterator &begin, const t_iterator &end)
Definition Buffer.hpp:124
void removeAllUnordered(const t_functor &functor)
Removes all items based on the functor. The functor should return true if the item is deleted or fals...
Definition Buffer.hpp:664
decltype(auto) end(t_index_type index)
Definition Buffer.hpp:515
void swapIndices(t_index_type index_1, t_index_type index_2)
Definition Buffer.hpp:867
void insert(t_index_type offset, const t_type *const buffer, t_index_type buffer_size)
Inserts data into the buffer.
Definition Buffer.hpp:327
sint04 compare(const Buffer &value, t_index_type start, t_index_type end) const
Definition Buffer.hpp:451
void insert(t_index_type location, const t_type &object)
Adds an object to a specific location.
Definition Buffer.hpp:227
void removeIndex(t_index_type location)
Definition Buffer.hpp:606
Buffer(t_index_type size)
Definition Buffer.hpp:85
void add(t_index_type location, const t_type &object)
Adds and object to a specific location. Equivelent to insert.
Definition Buffer.hpp:206
void ensureCapacity(t_index_type new_capacity, bool ensure_not_greater=false, bool ensure_not_less=true)
Definition Buffer.hpp:519
decltype(auto) ptr() const
Definition Buffer.hpp:392
Buffer< t_other_type, t_other_index_type, t_other_memory_allocator, t_other_memory_manager > getAs() const
Gets a copy of this buffer, with filled objects t_other_type, where all objects are created using the...
Definition Buffer.hpp:172
void insert(t_index_type location, t_type &&object)
Adds an object to a specific location.
Definition Buffer.hpp:237
void clear(t_index_type new_capacity)
Definition Buffer.hpp:427
decltype(auto) begin()
Definition Buffer.hpp:402
t_index_type memSize() const
Definition Buffer.hpp:397
Buffer(t_index_type size, const t_type &fill_object)
Definition Buffer.hpp:104
~Buffer()
Definition Buffer.hpp:143
bool contains(const t_type &element, const std::function< bool(const t_type &, const t_type &)> &equal_function) const
Definition Buffer.hpp:474
void clear()
Definition Buffer.hpp:422
Buffer(const t_type *buffer, t_index_type size)
Definition Buffer.hpp:94
decltype(auto) begin() const
Definition Buffer.hpp:407
bool isEmpty() const
Definition Buffer.hpp:584
decltype(auto) last() const
Definition Buffer.hpp:593
decltype(auto) get(t_index_type index)
Definition Buffer.hpp:541
bool contains(const t_type &element, t_index_type start) const
Definition Buffer.hpp:483
decltype(auto) end() const
Definition Buffer.hpp:511
void insert(const t_index_type location, const t_type *buffer)
Inserts data into the buffer, assumed to be null terminated.
Definition Buffer.hpp:348
bool removeElement(const t_type &element)
Definition Buffer.hpp:617
t_index_type indexOf(const t_type &element, t_index_type start_pos) const
Definition Buffer.hpp:567
t_index_type count(const t_type &element) const
Definition Buffer.hpp:503
void removeLast()
Definition Buffer.hpp:629
void addAll(const t_type *buffer, t_index_type buffer_size)
Definition Buffer.hpp:257
bool contains(const t_type &element, t_index_type start, t_index_type search_size) const
Definition Buffer.hpp:493
constexpr Buffer(const Buffer &buffer)
Definition Buffer.hpp:68
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
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
Defines for a given type (such as sint04, fltp08, UUID, etc) a maximum, minimum, and reserved 'invali...
Definition BaseValues.hpp:233