NDEVR
API Documentation
Buffer.hpp
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/BufferBase.h>
38#include <initializer_list>
39#include <utility>
40#include <functional>
41namespace NDEVR
42{
56 template<class t_type, class t_memory_manager = BufferAllocator<t_type, AlignmentDeterminator<t_type>::Size(), ObjectInfo<t_type>::Primitive, uint04, false>>
58 {
59 public:
60 using t_index_type = typename t_memory_manager::index_type;
61 using t_allocator = typename t_memory_manager::allocator;
65 constexpr Buffer() noexcept
66 : m_memory_interface()
67 {}
68
72 constexpr Buffer(const Buffer& buffer)
73 : m_memory_interface()
74 {
75 addAll(buffer);
76 }
77
81 constexpr Buffer(Buffer&& buffer) noexcept
82 : m_memory_interface(std::move(buffer.m_memory_interface))
83 {}
84
89 explicit Buffer(t_index_type size)
90 : m_memory_interface()
91 {
92 m_memory_interface.resizeSpace(size);
93 }
94
98 constexpr explicit Buffer(const t_type* buffer, t_index_type size)
99 : m_memory_interface()
100 {
101 if (size != 0)
102 addAll(buffer, size);
103 }
104
108 constexpr Buffer(t_index_type size, const t_type& fill_object)
109 : m_memory_interface()
110 {
111 m_memory_interface.template createSpace<false>(size);
112 t_allocator::AllocateElement(m_memory_interface, 0, size, fill_object);
113 }
114
118 Buffer(std::initializer_list<t_type> l)
119 : m_memory_interface()
120 {
121 addAll(l.begin(), cast<t_index_type>(l.size()));
122 }
123
127 template<class t_iterator>
128 Buffer(const t_iterator& begin, const t_iterator& end)
129 : m_memory_interface()
130 {
131 setSize(cast<t_index_type>(std::distance(begin, end)));
132 uint04 index = 0;
133 for (auto iter = begin; iter != end; iter++)
134 {
135 get(index++) = *iter;
136 }
137 }
138
146
148 {
149 t_allocator::Deallocate(m_memory_interface, 0, size());
150 }
151
156 [[nodiscard]] operator decltype(auto) () const
157 {
158 return begin();
159 }
160
165 [[nodiscard]] operator decltype(auto) ()
166 {
167 return begin();
168 }
169
175 template<class t_other_type, class t_other_memory_manager = t_memory_manager>
177 {
179 for (t_index_type i = 0; i < size(); i++)
180 {
181 other.add(t_other_type(get(i)));
182 }
183 return other;
184 }
185
190 void add(t_type&& object)
191 {
192 m_memory_interface.addIndex();
193 t_memory_manager::allocator::AllocateElement(m_memory_interface, size() - 1, std::move(object));
194 }
195
199 void add(const t_type& object)
200 {
201 m_memory_interface.addIndex();
202 t_memory_manager::allocator::AllocateElement(m_memory_interface, size() - 1, object);
203 }
204
210 void add(t_index_type location, const t_type& object)
211 {
212 lib_assert(begin() > &object || end() <= &object, "cannot add to buffer from same buffer");
213 m_memory_interface.addIndex(location);
214 t_memory_manager::allocator::AllocateElement(m_memory_interface, location, object);
215 }
216
221 void add(t_index_type location, t_type&& object)
222 {
223 lib_assert(begin() > &object || end() <= &object, "cannot add to buffer from same buffer");
224 m_memory_interface.addIndex(location);
225 t_memory_manager::allocator::AllocateElement(m_memory_interface, location, std::move(object));
226 }
227
233 void insert(t_index_type location, const t_type& object)
234 {
235 lib_assert(begin() > &object || end() <= &object, "cannot add to buffer from same buffer");
236 m_memory_interface.addIndex(location);
237 t_memory_manager::allocator::AllocateElement(m_memory_interface, location, object);
238 }
239
244 void insert(t_index_type location, t_type&& object)
245 {
246 lib_assert(begin() > &object || end() <= &object, "cannot add to buffer from same buffer");
247 m_memory_interface.addIndex(location);
248 t_memory_manager::allocator::AllocateElement(m_memory_interface, location, std::move(object));
249 }
250 template<class t_other_memory_manager>
251 constexpr void addAll(const Buffer<t_type, t_other_memory_manager>& buffer)
252 {
253 lib_assert(buffer.begin() != begin() || size() == 0, "cannot add to buffer from same buffer");
254 t_index_type offset = size();
255 m_memory_interface.template createSpace<false>(cast<t_index_type>(buffer.size()));
256 if constexpr (t_memory_manager::allocator::isPrimitive())
257 {
258 m_memory_interface.template setAll<true>(buffer.memoryInterface(), offset, 0, cast<t_index_type>(buffer.size()));
259 }
260 else
261 {
262 for (t_index_type i = 0; i < buffer.size(); i++)
263 t_memory_manager::allocator::AllocateElement(m_memory_interface, i + offset, buffer[i]);
264 }
265 }
266 constexpr void addAll(const t_type* buffer, t_index_type buffer_size)
267 {
268 lib_assert(begin() > buffer || end() <= buffer || size() == 0, "cannot add to buffer from same buffer");
269 t_index_type offset = size();
270 m_memory_interface.template createSpace<false>(buffer_size);
271 if constexpr (t_memory_manager::allocator::isPrimitive())
272 {
273 m_memory_interface.template setAll<true>(buffer, offset, buffer_size);
274 }
275 else
276 {
277 for (t_index_type i = 0; i < buffer_size; i++)
278 t_memory_manager::allocator::AllocateElement(m_memory_interface, i + offset, buffer[i]);
279 }
280 }
281 template<class t_iterator>
282 constexpr void addAll(t_iterator buffer, t_index_type buffer_size)
283 {
284 if (buffer_size == 0U)
285 return;
286 t_index_type offset = size();
287 m_memory_interface.template createSpace<false>(buffer_size);
288 if constexpr (t_memory_manager::allocator::isPrimitive())
289 {
290 m_memory_interface.template setAll<true>(buffer, offset, buffer_size);
291 }
292 else
293 {
294 for (t_index_type i = 0; i < buffer_size; i++)
295 t_memory_manager::allocator::AllocateElement(m_memory_interface, i + offset, buffer[i]);
296 }
297 }
298 void addAll(const t_type* buffer)
299 {
300 lib_assert(begin() > buffer || end() < buffer, "cannot add to buffer from same buffer");
301 t_index_type size = 0;
302 int loc = 0;
303 for (;;)
304 {
305 if (memcmp(&buffer[size], &loc, sizeof(t_type)) == 0)
306 break;
307 ++size;
308 }
309 addAll(buffer, size);
310 }
311 void insert(t_index_type offset, const Buffer& buffer)
312 {
313 lib_assert(buffer.begin() != begin() || size() == 0, "cannot add to buffer from same buffer");
314 m_memory_interface.template createSpace<false>(offset, buffer.size());
315 if constexpr (t_memory_manager::allocator::isPrimitive())
316 {
317 m_memory_interface.template setAll<true>(buffer.m_memory_interface, offset, 0, buffer.size());
318 }
319 else
320 {
321 for (t_index_type i = 0; i < buffer.size(); i++)
322 t_memory_manager::allocator::AllocateElement(m_memory_interface, i + offset, buffer[i]);
323 }
324 }
325 template<class t_replace_buffer_type>
326 void replaceIndexRange(t_index_type offset, t_index_type replace_size, const t_replace_buffer_type& buffer)
327 {
328 replaceIndexRange(offset, replace_size, buffer.begin(), buffer.size());
329 }
330 void replaceIndexRange(t_index_type offset, t_index_type replace_size, const t_type* buffer, t_index_type buffer_size)
331 {
332 lib_assert(buffer < begin() || buffer >= end(), "cannot replace buffer from same buffer");
333 lib_assert(offset + replace_size <= size(), "end > size in buffer replace");
334 if (replace_size < buffer_size)
335 {
336 t_index_type size_dff = buffer_size - replace_size;
337 m_memory_interface.template createSpace<false>(offset, size_dff);
338 if constexpr (!t_memory_manager::allocator::isPrimitive())
339 {
340 for (t_index_type i = 0; i < size_dff; i++)
341 t_memory_manager::allocator::AllocateElement(m_memory_interface, i + offset, buffer[i]);
342 }
343 }
344 else if (replace_size > buffer_size)
345 {
346 removeIndices(offset, replace_size - buffer_size);
347 }
348 setAll(buffer, offset, buffer_size);
349 }
350
351#ifdef __clang__
352 #pragma clang diagnostic push
353 #pragma clang diagnostic ignored "-Wunused-value"//Weird error in clang thinks expression result not used
354#endif
361 void insert(t_index_type offset, const t_type* const buffer, t_index_type buffer_size)
362 {
363 m_memory_interface.template createSpace<false>(offset, buffer_size);
364 if constexpr (t_memory_manager::allocator::isPrimitive())
365 {
366 m_memory_interface.template setAll<true>(buffer, offset, buffer_size);
367 }
368 else
369 {
370 for (t_index_type i = 0; i < buffer_size; i++)
371 t_memory_manager::allocator::AllocateElement(m_memory_interface, i + offset, buffer[i]);
372 }
373 }
374#ifdef __clang__
375 #pragma clang diagnostic pop
376#endif
382 void insert(const t_index_type location, const t_type* buffer)
383 {
384 t_index_type size = 0;
385 int loc = 0;
386 for (;;)
387 {
388 if (memcmp(&buffer[size], &loc, sizeof(t_type)) == 0)
389 break;
390 ++size;
391 }
392 insert(location, buffer, size);
393 }
394
399 template<bool t_managed>
400 void addSpace(t_index_type space_to_add)
401 {
402 const t_index_type offset = size();
403 m_memory_interface.template createSpace<t_managed>(space_to_add);
404 t_allocator::Allocate(m_memory_interface, offset, size() - offset);
405 }
406 template<bool t_managed = false>
407 void addAndFillSpace(t_index_type space_to_add, const t_type& fill_object)
408 {
409 const t_index_type offset = size();
410 m_memory_interface.template createSpace<t_managed>(space_to_add);
411 t_allocator::AllocateElement(m_memory_interface, offset, size() - offset, fill_object);
412 }
413 template<bool t_managed>
414 void addSpace(t_index_type location, t_index_type size)
415 {
416 lib_assert(location <= this->size(), "Tried to insert into a bad location");
417 m_memory_interface.template createSpace<t_managed>(location, size);
418
419 t_allocator::Allocate(m_memory_interface, location, size);
420 }
421 [[nodiscard]] constexpr decltype(auto) ptr()
422 {
423 return m_memory_interface.ptr();
424 }
425
426 [[nodiscard]] constexpr decltype(auto) ptr() const
427 {
428 return m_memory_interface.ptr();
429 }
430
431 [[nodiscard]] auto memSize() const
432 {
433 return m_memory_interface.memSize();
434 }
435
436 [[nodiscard]] constexpr decltype(auto) begin()
437 {
438 return m_memory_interface.begin();
439 }
440
441 [[nodiscard]] constexpr decltype(auto) begin() const
442 {
443 return m_memory_interface.begin();
444 }
445
446 [[nodiscard]] constexpr decltype(auto) begin(t_index_type index) const
447 {
448 return m_memory_interface.begin(index);
449 }
450 [[nodiscard]] constexpr decltype(auto) begin(t_index_type index)
451 {
452 return m_memory_interface.begin(index);
453 }
454 [[nodiscard]] t_index_type capacity() const
455 {
456 return m_memory_interface.capacity();
457 }
458
459 constexpr void clear()
460 {
461 t_allocator::Deallocate(m_memory_interface, 0U, size());
462 m_memory_interface.clear();
463 }
464 void clear(t_index_type new_capacity)
465 {
466 t_allocator::Deallocate(m_memory_interface, 0, size());
467 m_memory_interface.clear();
468 ensureCapacity(new_capacity, true, true);
469 }
470
476 [[nodiscard]] sint04 compare(const Buffer& value) const
477 {
478 sint04 cmp_value = m_memory_interface.compare(value.m_memory_interface);
479 if (cmp_value != 0)
480 return cmp_value;
481 else if (value.size() > size())
482 return -1;
483 else if (value.size() < size())
484 return 1;
485 else
486 return 0;
487 }
488 [[nodiscard]] sint04 compare(const Buffer& value, t_index_type start, t_index_type end) const
489 {
490 sint04 cmp_value = m_memory_interface.compare(value.m_memory_interface, start, end);
491 if (cmp_value != 0)
492 return cmp_value;
493 else if (value.size() == size())
494 return 0;
495 else if (end > size())
496 return -1;
497 else if (end > value.size())
498 return 1;
499 else
500 return 0;
501 }
502 template<class t_comparable_type>
503 [[nodiscard]] bool contains(const t_comparable_type& element) const
504 {
505 return m_memory_interface.contains(element, 0, size());
506 }
507 [[nodiscard]] bool contains(const t_type& element, const std::function<bool(const t_type&, const t_type&)>& equal_function) const
508 {
509 for (uint04 i = 0; i < size(); ++i)
510 {
511 if (equal_function(get(i), element))
512 return true;
513 }
514 return false;
515 }
516 [[nodiscard]] bool contains(const t_type& element, t_index_type start) const
517 {
518 lib_assert(start < size(), "buffer contains using bad start value");
519 return m_memory_interface.contains(element, start, size() - start);
520 }
521 [[nodiscard]] bool contains(const t_type& element, t_index_type start, t_index_type search_size) const
522 {
523 lib_assert(search_size + start <= size(), "buffer contains using bad start value");
524 return m_memory_interface.contains(element, start, search_size);
525 }
526 [[nodiscard]] t_index_type count(const t_type& element) const
527 {
528 return m_memory_interface.count(element);
529 }
530 [[nodiscard]] decltype(auto) end()
531 {
532 return m_memory_interface.end();
533 }
534 [[nodiscard]] decltype(auto) end() const
535 {
536 return m_memory_interface.end();
537 }
538 [[nodiscard]] decltype(auto) end(t_index_type index)
539 {
540 return m_memory_interface.end(index);
541 }
542 void ensureCapacity(t_index_type new_capacity, bool ensure_not_greater = false, bool ensure_not_less = true)
543 {
544 if (new_capacity == capacity())
545 return;
546 if (new_capacity > capacity())
547 {
548 if (ensure_not_less)
549 m_memory_interface.resizeSpace(new_capacity);
550 }
551 else if (ensure_not_greater)
552 {
553 lib_assert(new_capacity >= size(), "Array can't have capacity less than size");
554 m_memory_interface.resizeSpace(new_capacity);
555 }
556 }
557 [[nodiscard]] bool equals(const Buffer& buffer) const
558 {
559 if (size() == buffer.size())
560 return _equals<t_memory_manager::allocator::isPrimitive()>(buffer);
561 else
562 return false;
563 }
564 [[nodiscard]] decltype(auto) get(t_index_type index)
565 {
566 lib_assert(index < size(), "Buffer out of bounds");
567 return m_memory_interface.get(index);
568 }
569 [[nodiscard]] decltype(auto) get(t_index_type index) const
570 {
571 lib_assert(index < size(), "Buffer out of bounds");
572 return m_memory_interface.get(index);
573 }
574
575
576 [[nodiscard]] Buffer getAll(t_index_type start, t_index_type size)
577 {
578 Buffer buff(size);
579 buff.addAll(begin(start), size);
580 return buff;
581 }
582 [[nodiscard]] t_index_type indexOf(const t_type& element) const
583 {
584 for (t_index_type i = 0; i < size(); ++i)
585 {
586 if (get(i) == element) return i;
587 }
588 return Constant<t_index_type>::Invalid;
589 }
590 [[nodiscard]] t_index_type indexOf(const t_type& element, t_index_type start_pos) const
591 {
592 for (t_index_type i = start_pos; i < size(); ++i)
593 {
594 if (get(i) == element) return i;
595 }
596 return Constant<t_index_type>::Invalid;
597 }
598 [[nodiscard]] t_index_type indexOf(const t_type& element, t_index_type start_pos, t_index_type search_size) const
599 {
600 lib_assert(search_size + start_pos <= size(), "bad index of in equation");
601 for (t_index_type i = start_pos; i < start_pos + search_size; ++i)
602 {
603 if (get(i) == element) return i;
604 }
605 return Constant<t_index_type>::Invalid;
606 }
607 [[nodiscard]] bool isEmpty() const
608 {
609 return size() == 0;
610 }
611 [[nodiscard]] decltype(auto) last()
612 {
613 lib_assert(size() != 0, "Cannot get last: out of bounds");
614 return get(size() - 1);
615 }
616 [[nodiscard]] decltype(auto) last() const
617 {
618 lib_assert(size() != 0, "Cannot get last: out of bounds");
619 return get(size() - 1);
620 }
621 [[nodiscard]] t_index_type lastIndexOf(const t_type& element) const
622 {
623 for (t_index_type i = size() - 1; i < size(); --i)
624 {
625 if (get(i) == element) return i;
626 }
627 return Constant<t_index_type>::Invalid;
628 }
629 void removeIndex(t_index_type location)
630 {
631 lib_assert(location < size(), "Out of bounds remove");
632 t_allocator::Deallocate(m_memory_interface, location, 1);
633 m_memory_interface.removeIndex(location);
634 }
635 void removeIndexBackSwap(t_index_type location)
636 {
637 swapIndices(location, size() - 1);//swap with back
638 removeLast();//remove back
639 }
640 template<class t_comparable_type>
641 bool removeElement(const t_comparable_type& element)
642 {
643 for (t_index_type i = size() - 1; IsValid(i); --i)//start at last element as less expensive to removeRows
644 {
645 if (get(i) == element)
646 {
647 removeIndex(i);
648 return true;
649 }
650 }
651 return false;
652 }
653 template<class t_comparable_type>
654 bool removeElement(const t_comparable_type& element, uint04 first)
655 {
656 first--;
657 for (t_index_type i = size() - 1; i != first; --i)//start at last element as less expensive to removeRows
658 {
659 if (get(i) == element)
660 {
661 removeIndex(i);
662 return true;
663 }
664 }
665 return false;
666 }
667 void removeLast()
668 {
669 lib_assert(size() > 0, "Cannot remove last from empty buffer");
670 t_allocator::Deallocate(m_memory_interface, size() - 1, 1);
671 m_memory_interface.removeLast();
672 }
673
679 void removeAllUnordered(const t_type& object)
680 {
681 t_index_type end = size();
682 for (t_index_type i = 0; i < end; i++)
683 {
684 if (get(i) == object)
685 {
686 swapIndices(i, --end);
687 --i;
688 }
689 }
690 setSize(end);
691 }
692
700 template<class t_functor>
701 void removeAllUnordered(const t_functor& functor)
702 {
703 t_index_type end = size();
704 for (t_index_type i = 0; i < end; i++)
705 {
706 if (functor(get(i)))
707 {
708 swapIndices(i--, --end);
709 }
710 }
711 setSize(end);
712 }
713
719 void removeAllOrdered(const t_type& object)
720 {
721 t_index_type start = 0;
722 uint04 end = size();
723 for (t_index_type i = 0; i < end; i++)
724 {
725 get(start) = get(i);
726 if (get(i) != object)
727 ++start;
728 }
729 if (start != end)
730 m_memory_interface.removeAllIndex(start, end);
731 }
732
738 template<class t_functor>
739 void removeAllOrderedFn(const t_functor& functor)
740 {
741 t_index_type start = 0;
742 t_index_type end = size();
743 for (t_index_type i = 0; i < end; i++)
744 {
745 get(start) = get(i);
746 if (!functor(get(i)))
747 ++start;
748 }
749 if (start != size())
750 m_memory_interface.removeAllIndex(start, size());
751 }
752 void removeIndices(t_index_type start, t_index_type size)
753 {
754 if (size == 0U)
755 return;
756 t_allocator::Deallocate(m_memory_interface, start, size);
757 m_memory_interface.removeAllIndex(start, start + size);
758 }
759 template<class t_range_buffer>
760 void removeIndices(const t_range_buffer& ranges)
761 {
762#ifdef _DEBUG
763 uint04 last_delete_index = 0;
764#endif
765 for (const auto& range : ranges)
766 {
767 t_index_type start = range.first;
768 t_index_type end = range.second;
769#ifdef _DEBUG
770 lib_assert(last_delete_index <= start, "ranges must be ordered");
771 lib_assert(start <= end, "remove all start > end");
772 last_delete_index = end;
773#endif
774 t_allocator::Deallocate(m_memory_interface, start, end - start);
775 }
776 m_memory_interface.removeIndices(ranges);
777 }
778 void replaceAll(const t_type& var, const t_type& replacement)
779 {
780 for (t_index_type i = 0; i < size(); i++)
781 {
782 if (get(i) == var)
783 get(i) = replacement;
784 }
785 }
786 void reverse()
787 {
788 for (t_index_type i = 0; i < size() / 2; i++)
789 {
790 m_memory_interface.swap(i, size() - i - 1);
791 }
792 }
793 void reverse(const t_index_type start, const t_index_type end)
794 {
795 const t_index_type size = end - start;
796 for (t_index_type i = 0; i < size / 2; i++)
797 {
798 m_memory_interface.swap(start + i, (start + size) - i - 1);
799 }
800 }
801 template<class t_o_type>
802 void setAll(const t_o_type* src, t_index_type offset, t_index_type size)
803 {
804 m_memory_interface.template setAll<t_memory_manager::allocator::isPrimitive()>(src, offset, size);
805 }
806 void setAll(const Buffer& buffer, t_index_type offset, t_index_type size)
807 {
808 lib_assert(buffer.size() >= size, "too small of buffer being used in set all");
809 m_memory_interface.template setAll<t_memory_manager::allocator::isPrimitive()>(buffer.m_memory_interface, offset, 0, size);
810 }
811 void setAll(const Buffer& buffer, t_index_type offset, t_index_type other_offset, t_index_type size)
812 {
813 lib_assert(buffer.size() >= size, "too small of buffer being used in set all");
814 m_memory_interface.template setAll<t_memory_manager::allocator::isPrimitive()>(buffer.m_memory_interface, offset, other_offset, size);
815 }
816 template<class t_o_type>
817 void setAllToValue(const t_o_type& fill_element, const t_index_type offset = 0, t_index_type fill_size = Constant<t_index_type>::Invalid)
818 {
819 const t_index_type old_size = size();
820 if (IsInvalid(fill_size))
821 fill_size = old_size - offset;
822 else if(offset + fill_size > old_size)
823 {
824 m_memory_interface.setSize(offset + fill_size);
825 }
826 const t_type value(fill_element);
827 if (t_memory_manager::allocator::isPrimitive() || size() == old_size)
828 {
829 m_memory_interface.setAll(value, offset, fill_size);
830 }
831 else
832 {
833 t_index_type size_a = old_size - offset;
834 m_memory_interface.setAll(value, offset, size_a);
835 t_memory_manager::allocator::AllocateElement(m_memory_interface, offset + size_a, fill_size - size_a, value);
836 }
837 }
838 void setSize(t_index_type new_size)
839 {
840 if (new_size == size())
841 return;
842 resize(new_size);
843 }
844 void resize(t_index_type new_size)
845 {
846 if (new_size < size())
847 t_allocator::Deallocate(m_memory_interface, new_size, size() - new_size);
848 const t_index_type old_size = size();
849 m_memory_interface.setSize(new_size);
850 if (old_size < size())
851 t_allocator::Allocate(m_memory_interface, old_size, size() - old_size);
852 }
853 void setSize(const t_index_type new_size, const t_type& fill_element)
854 {
855 if (new_size == size())
856 return;
857 if (new_size < size())
858 {
859 t_allocator::Deallocate(m_memory_interface, new_size, size() - new_size);
860 m_memory_interface.setSize(new_size);
861 }
862 else
863 {
864 const t_index_type old_size = size();
865 m_memory_interface.setSize(new_size);
866 t_allocator::AllocateElement(m_memory_interface, old_size, size() - old_size, fill_element);
867 }
868 }
869 [[nodiscard]] constexpr t_index_type size() const
870 {
871 return m_memory_interface.filledSize();
872 }
873 void swapElements(const t_type& element1, const t_type& element2)
874 {
875 if (element1 == element2)
876 return;
877 t_index_type index_1 = Constant<t_index_type>::Invalid;
878 t_index_type index_2 = Constant<t_index_type>::Invalid;
879 for (t_index_type i = 0; i < size(); i++)
880 {
881 if (get(i) == element1)
882 {
883 index_1 = i;
884 if (IsValid(index_2))
885 {
886 swapIndices(index_1, index_2);
887 return;
888 }
889 }
890 else if (get(i) == element2)
891 {
892 index_2 = i;
893 if (IsValid(index_1))
894 {
895 swapIndices(index_1, index_2);
896 return;
897 }
898 }
899 }
900 }
901 void swapAllElements(const t_type& element1, const t_type& element2)
902 {
903 if (element1 == element2)
904 return;
905 for (t_index_type ii = 0; ii < size(); ++ii)
906 {
907 if (get(ii) == element1)
908 get(ii) = element2;
909 else if (get(ii) == element2)
910 get(ii) = element1;
911 }
912 }
913 void swapIndices(t_index_type index_1, t_index_type index_2)
914 {
915 std::swap(get(index_1), get(index_2));
916 }
917 void move(t_index_type from, t_index_type to)
918 {
919 if (to == from)
920 return;
921 t_type object = get(from);
922 removeIndex(from);
923 if (to > from)
924 to--;
925 add(to, object);
926 }
927 void primitiveSort()
928 {
929 struct primitiveUniqueDataComparison
930 {
931 bool operator()(const t_type& lhs, const t_type& rhs)
932 {
933 return memcmp(&lhs, &rhs, sizeof(t_type)) > 0;
934 }
935 };
936 std::sort(begin(), end(), primitiveUniqueDataComparison());
937 }
938 void sort()
939 {
940 std::sort(begin(), end());
941 }
942 void sortRange(t_index_type start, t_index_type end)
943 {
944 std::sort(begin() + start, begin() + end);
945 }
946 void setUnique()
947 {
948 if constexpr (t_memory_manager::allocator::isPrimitive())
949 primitiveSort();
950 else
951 sort();
952 setSize(cast<t_index_type>(std::unique(begin(), end()) - begin()));
953 }
954 void setUniquePresorted()
955 {
956 setSize(cast<t_index_type>(std::unique(begin(), end()) - begin()));
957 }
958 t_index_type sortAboutValue(t_index_type value_index)
959 {
960 return sortAboutValue(value_index, 0, size());
961 }
962 t_index_type sortAboutValue(t_index_type value_index, t_index_type start, t_index_type end)
963 {
964 const t_type value = get(value_index);
965 std::swap(get(value_index), get(--end));
966 t_index_type store = start;
967 for (t_index_type idx = start; idx < end; ++idx)
968 {
969 if (get(idx) <= value)
970 {
971 std::swap(get(idx), get(store));
972 store++;
973 }
974 }
975 std::swap(get(end), get(store));
976 return store;
977 }
978 inline Buffer& operator=(const Buffer& buffer)
979 {
980 if (&(buffer) == this)
981 return *this;//check to ensure not setting equal to ourselves
982 clear();
983 addAll(buffer);
984 return *this;
985 }
986 inline Buffer& operator=(Buffer&& buffer) noexcept
987 {
988 std::swap(m_memory_interface, buffer.m_memory_interface);
989 return *this;
990 }
991 [[nodiscard]] inline bool operator==(const Buffer& buffer) const
992 {
993 return equals(buffer);
994 }
995 [[nodiscard]] inline bool operator>(const Buffer& buffer) const
996 {
997 return compare(buffer) > 0;
998 }
999 [[nodiscard]] inline bool operator<(const Buffer& buffer) const
1000 {
1001 return compare(buffer) < 0;
1002 }
1003 [[nodiscard]] inline bool operator>=(const Buffer& buffer) const
1004 {
1005 return compare(buffer) >= 0;
1006 }
1007 [[nodiscard]] inline bool operator<=(const Buffer& buffer) const
1008 {
1009 return compare(buffer) <= 0;
1010 }
1011 [[nodiscard]] inline bool operator!=(const Buffer& buffer) const
1012 {
1013 return !equals(buffer);
1014 }
1015 [[nodiscard]] decltype(auto) operator[](const t_index_type index)
1016 {
1017 return get(index);
1018 }
1019 [[nodiscard]] decltype(auto) operator[](const int index)
1020 {
1021 return get(cast<t_index_type>(index));
1022 }
1023 [[nodiscard]] decltype(auto) operator[](const t_index_type value) const
1024 {
1025 return get(value);
1026 }
1027 [[nodiscard]] decltype(auto) operator[](const int index) const
1028 {
1029 return get(cast<t_index_type>(index));
1030 }
1031 [[nodiscard]] Buffer operator+(const t_type& element) const
1032 {
1033 Buffer<t_type, t_memory_manager> buffer(1 + size());
1034 buffer.addAll(*this);
1035 buffer.add(element);
1036 return buffer;
1037 }
1038 const Buffer& operator+=(const t_type& element)
1039 {
1040 add(element);
1041 return *this;
1042 }
1043 inline Buffer& operator+=(const Buffer& value)
1044 {
1045 addAll(value);
1046 return (*this);
1047 }
1048 [[nodiscard]] inline Buffer operator+(const Buffer& value) const
1049 {
1050 Buffer buffer(size() + value.size());
1051 buffer.addAll(*this);
1052 buffer.addAll(value);
1053 return buffer;
1054 }
1055 [[nodiscard]] bool isSorted() const
1056 {
1057 if (size() <= 1)
1058 return true;
1059 for (t_index_type i = 0; i < size() - 1; i++)
1060 {
1061 if (get(i) >= get(i + 1))
1062 return false;
1063 }
1064 return true;
1065 }
1066 [[nodiscard]] bool isSortedSet() const
1067 {
1068 for (t_index_type i = 0; i < size() - 1; i++)
1069 {
1070 if (get(i) > get(i + 1))
1071 return false;
1072 }
1073 return true;
1074 }
1075 [[nodiscard]] constexpr static t_type Type() { t_type* ptr = nullptr; return *ptr; }
1076
1077 [[nodiscard]] constexpr t_memory_manager& memoryInterface()
1078 {
1079 return m_memory_interface;
1080 }
1081 [[nodiscard]] constexpr const t_memory_manager& memoryInterface() const
1082 {
1083 return m_memory_interface;
1084 }
1085 private:
1086 template<bool t_is_primitive>
1087 [[nodiscard]] bool _equals(const Buffer& buffer) const
1088 {
1089 if (t_is_primitive)
1090 {
1091 return compare(buffer) == 0;
1092 }
1093 else
1094 {
1095 for (t_index_type i = 0; i < size(); i++)
1096 {
1097 if (get(i) != buffer.get(i))
1098 return false;
1099 }
1100 return true;
1101 }
1102 }
1103 private:
1104 t_memory_manager m_memory_interface;
1105 };
1106 template<class t_type, class t_memory_manager>
1107 struct Constant<Buffer<t_type, t_memory_manager>>
1108 {
1110 inline const static Buffer<t_type, t_memory_manager> Invalid{};
1111 };
1112 template <class t_type, class t_memory_manager = BufferAllocator<t_type, DetermineAlignment<sizeof(t_type)>(), ObjectInfo<t_type>::Primitive, uint08, false>>
1113 using HighCapacityBuffer = Buffer<t_type, t_memory_manager>;
1114 template <class t_type, class t_memory_manager = BufferAllocator<t_type, DetermineAlignment<sizeof(t_type)>(), true, uint04, false>>
1115 using PrimitiveBuffer = Buffer<t_type, t_memory_manager>;
1116 template <class t_type, size_t t_alignment, class t_memory_manager = BufferAllocator<t_type, DetermineAlignment<t_alignment>(), ObjectInfo<t_type>::Primitive, uint04, false>>
1117 using AlignedBuffer = Buffer<t_type, t_memory_manager>;
1118 template <class t_type, size_t t_alignment, class t_memory_manager = BufferAllocator<t_type, DetermineAlignment<t_alignment>(), true, uint04, false>>
1119 using PrimitiveAlignedBuffer = Buffer<t_type, t_memory_manager>;
1120 template <class t_type, size_t t_alignment, class t_memory_manager = BufferAllocator<t_type, DetermineAlignment<t_alignment>(), false, uint04, false>>
1121 using AlocatingAlignedBuffer = Buffer<t_type, t_memory_manager>;
1122}
1123#include "BoolBuffer.hpp"
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.
Definition Buffer.hpp:58
void addSpace(t_index_type space_to_add)
Definition Buffer.hpp:400
constexpr Buffer(const Buffer &buffer)
Definition Buffer.hpp:72
Buffer< t_other_type, t_other_memory_manager > getAs() const
Definition Buffer.hpp:176
void insert(t_index_type location, t_type &&object)
Definition Buffer.hpp:244
void insert(t_index_type offset, const t_type *const buffer, t_index_type buffer_size)
Definition Buffer.hpp:361
void removeAllUnordered(const t_type &object)
Definition Buffer.hpp:679
void removeAllUnordered(const t_functor &functor)
Definition Buffer.hpp:701
constexpr Buffer(t_index_type size, const t_type &fill_object)
Definition Buffer.hpp:108
void add(t_index_type location, const t_type &object)
Definition Buffer.hpp:210
void removeAllOrdered(const t_type &object)
Definition Buffer.hpp:719
void add(t_index_type location, t_type &&object)
Definition Buffer.hpp:221
void add(t_type &&object)
Adds object to the end of the buffer.
Definition Buffer.hpp:190
Buffer(const t_iterator &begin, const t_iterator &end)
Definition Buffer.hpp:128
constexpr Buffer(const t_type *buffer, t_index_type size)
Definition Buffer.hpp:98
void add(const t_type &object)
Definition Buffer.hpp:199
constexpr Buffer(Buffer &&buffer) noexcept
Definition Buffer.hpp:81
void removeAllOrderedFn(const t_functor &functor)
Definition Buffer.hpp:739
constexpr Buffer() noexcept
Creates an empty buffer.
Definition Buffer.hpp:65
Buffer(std::initializer_list< t_type > l)
Definition Buffer.hpp:118
void insert(const t_index_type location, const t_type *buffer)
Definition Buffer.hpp:382
sint04 compare(const Buffer &value) const
Definition Buffer.hpp:476
void insert(t_index_type location, const t_type &object)
Definition Buffer.hpp:233
The primary namespace for the NDEVR SDK.
static constexpr bool IsValid(const Angle< t_type > &value)
Checks whether the given Angle holds a valid value.
Definition Angle.h:398
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
int32_t sint04
-Defines an alias representing a 4 byte, signed integer.
constexpr t_to cast(const Angle< t_from > &value)
Casts an Angle from one backing type to another.
Definition Angle.h:408
Information about the object.
Definition ObjectInfo.h:55