60 using t_index_type =
typename t_memory_manager::index_type;
61 using t_allocator =
typename t_memory_manager::allocator;
66 : m_memory_interface()
73 : m_memory_interface()
82 : m_memory_interface(std::move(buffer.m_memory_interface))
90 : m_memory_interface()
92 m_memory_interface.resizeSpace(size);
98 constexpr explicit Buffer(
const t_type* buffer, t_index_type size)
99 : m_memory_interface()
102 addAll(buffer, size);
108 constexpr Buffer(t_index_type size,
const t_type& fill_object)
109 : m_memory_interface()
111 m_memory_interface.template createSpace<false>(size);
112 t_allocator::AllocateElement(m_memory_interface, 0, size, fill_object);
119 : m_memory_interface()
127 template<
class t_iterator>
128 Buffer(
const t_iterator& begin,
const t_iterator& end)
129 : m_memory_interface()
133 for (
auto iter = begin; iter != end; iter++)
135 get(index++) = *iter;
149 t_allocator::Deallocate(m_memory_interface, 0, size());
156 [[nodiscard]]
operator decltype(
auto) ()
const
165 [[nodiscard]]
operator decltype(
auto) ()
175 template<
class t_other_type,
class t_other_memory_manager = t_memory_manager>
179 for (t_index_type i = 0; i < size(); i++)
181 other.
add(t_other_type(get(i)));
192 m_memory_interface.addIndex();
193 t_memory_manager::allocator::AllocateElement(m_memory_interface, size() - 1, std::move(
object));
199 void add(
const t_type&
object)
201 m_memory_interface.addIndex();
202 t_memory_manager::allocator::AllocateElement(m_memory_interface, size() - 1,
object);
210 void add(t_index_type location,
const t_type&
object)
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);
221 void add(t_index_type location, t_type&&
object)
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));
233 void insert(t_index_type location,
const t_type&
object)
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);
244 void insert(t_index_type location, t_type&&
object)
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));
250 template<
class t_other_memory_manager>
253 lib_assert(buffer.begin() != begin() || size() == 0,
"cannot add to buffer from same buffer");
254 t_index_type offset = size();
256 if constexpr (t_memory_manager::allocator::isPrimitive())
258 m_memory_interface.template setAll<true>(buffer.memoryInterface(), offset, 0,
cast<t_index_type>(buffer.size()));
262 for (t_index_type i = 0; i < buffer.size(); i++)
263 t_memory_manager::allocator::AllocateElement(m_memory_interface, i + offset, buffer[i]);
266 constexpr void addAll(
const t_type* buffer, t_index_type buffer_size)
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())
273 m_memory_interface.template setAll<true>(buffer, offset, buffer_size);
277 for (t_index_type i = 0; i < buffer_size; i++)
278 t_memory_manager::allocator::AllocateElement(m_memory_interface, i + offset, buffer[i]);
281 template<
class t_iterator>
282 constexpr void addAll(t_iterator buffer, t_index_type buffer_size)
284 if (buffer_size == 0U)
286 t_index_type offset = size();
287 m_memory_interface.template createSpace<false>(buffer_size);
288 if constexpr (t_memory_manager::allocator::isPrimitive())
290 m_memory_interface.template setAll<true>(buffer, offset, buffer_size);
294 for (t_index_type i = 0; i < buffer_size; i++)
295 t_memory_manager::allocator::AllocateElement(m_memory_interface, i + offset, buffer[i]);
298 void addAll(
const t_type* buffer)
300 lib_assert(begin() > buffer || end() < buffer,
"cannot add to buffer from same buffer");
301 t_index_type size = 0;
305 if (memcmp(&buffer[size], &loc,
sizeof(t_type)) == 0)
309 addAll(buffer, size);
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())
317 m_memory_interface.template setAll<true>(buffer.m_memory_interface, offset, 0, buffer.size());
321 for (t_index_type i = 0; i < buffer.size(); i++)
322 t_memory_manager::allocator::AllocateElement(m_memory_interface, i + offset, buffer[i]);
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)
328 replaceIndexRange(offset, replace_size, buffer.begin(), buffer.size());
330 void replaceIndexRange(t_index_type offset, t_index_type replace_size,
const t_type* buffer, t_index_type buffer_size)
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)
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())
340 for (t_index_type i = 0; i < size_dff; i++)
341 t_memory_manager::allocator::AllocateElement(m_memory_interface, i + offset, buffer[i]);
344 else if (replace_size > buffer_size)
346 removeIndices(offset, replace_size - buffer_size);
348 setAll(buffer, offset, buffer_size);
352 #pragma clang diagnostic push
353 #pragma clang diagnostic ignored "-Wunused-value"
361 void insert(t_index_type offset,
const t_type*
const buffer, t_index_type buffer_size)
363 m_memory_interface.template createSpace<false>(offset, buffer_size);
364 if constexpr (t_memory_manager::allocator::isPrimitive())
366 m_memory_interface.template setAll<true>(buffer, offset, buffer_size);
370 for (t_index_type i = 0; i < buffer_size; i++)
371 t_memory_manager::allocator::AllocateElement(m_memory_interface, i + offset, buffer[i]);
375 #pragma clang diagnostic pop
382 void insert(
const t_index_type location,
const t_type* buffer)
384 t_index_type size = 0;
388 if (memcmp(&buffer[size], &loc,
sizeof(t_type)) == 0)
392 insert(location, buffer, size);
399 template<
bool t_managed>
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);
406 template<
bool t_managed = false>
407 void addAndFillSpace(t_index_type space_to_add,
const t_type& fill_object)
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);
413 template<
bool t_managed>
414 void addSpace(t_index_type location, t_index_type size)
416 lib_assert(location <= this->size(),
"Tried to insert into a bad location");
417 m_memory_interface.template createSpace<t_managed>(location, size);
419 t_allocator::Allocate(m_memory_interface, location, size);
421 [[nodiscard]]
constexpr decltype(
auto) ptr()
423 return m_memory_interface.ptr();
426 [[nodiscard]]
constexpr decltype(
auto) ptr()
const
428 return m_memory_interface.ptr();
431 [[nodiscard]]
auto memSize()
const
433 return m_memory_interface.memSize();
436 [[nodiscard]]
constexpr decltype(
auto) begin()
438 return m_memory_interface.begin();
441 [[nodiscard]]
constexpr decltype(
auto) begin()
const
443 return m_memory_interface.begin();
446 [[nodiscard]]
constexpr decltype(
auto) begin(t_index_type index)
const
448 return m_memory_interface.begin(index);
450 [[nodiscard]]
constexpr decltype(
auto) begin(t_index_type index)
452 return m_memory_interface.begin(index);
454 [[nodiscard]] t_index_type capacity()
const
456 return m_memory_interface.capacity();
459 constexpr void clear()
461 t_allocator::Deallocate(m_memory_interface, 0U, size());
462 m_memory_interface.clear();
464 void clear(t_index_type new_capacity)
466 t_allocator::Deallocate(m_memory_interface, 0, size());
467 m_memory_interface.clear();
468 ensureCapacity(new_capacity,
true,
true);
478 sint04 cmp_value = m_memory_interface.compare(value.m_memory_interface);
481 else if (value.size() > size())
483 else if (value.size() < size())
488 [[nodiscard]]
sint04 compare(
const Buffer& value, t_index_type start, t_index_type end)
const
490 sint04 cmp_value = m_memory_interface.compare(value.m_memory_interface, start, end);
493 else if (value.size() == size())
495 else if (end > size())
497 else if (end > value.size())
502 template<
class t_comparable_type>
503 [[nodiscard]]
bool contains(
const t_comparable_type& element)
const
505 return m_memory_interface.contains(element, 0, size());
507 [[nodiscard]]
bool contains(
const t_type& element,
const std::function<
bool(
const t_type&,
const t_type&)>& equal_function)
const
509 for (
uint04 i = 0; i < size(); ++i)
511 if (equal_function(get(i), element))
516 [[nodiscard]]
bool contains(
const t_type& element, t_index_type start)
const
518 lib_assert(start < size(),
"buffer contains using bad start value");
519 return m_memory_interface.contains(element, start, size() - start);
521 [[nodiscard]]
bool contains(
const t_type& element, t_index_type start, t_index_type search_size)
const
523 lib_assert(search_size + start <= size(),
"buffer contains using bad start value");
524 return m_memory_interface.contains(element, start, search_size);
526 [[nodiscard]] t_index_type count(
const t_type& element)
const
528 return m_memory_interface.count(element);
530 [[nodiscard]]
decltype(
auto) end()
532 return m_memory_interface.end();
534 [[nodiscard]]
decltype(
auto) end()
const
536 return m_memory_interface.end();
538 [[nodiscard]]
decltype(
auto) end(t_index_type index)
540 return m_memory_interface.end(index);
542 void ensureCapacity(t_index_type new_capacity,
bool ensure_not_greater =
false,
bool ensure_not_less =
true)
544 if (new_capacity == capacity())
546 if (new_capacity > capacity())
549 m_memory_interface.resizeSpace(new_capacity);
551 else if (ensure_not_greater)
553 lib_assert(new_capacity >= size(),
"Array can't have capacity less than size");
554 m_memory_interface.resizeSpace(new_capacity);
557 [[nodiscard]]
bool equals(
const Buffer& buffer)
const
559 if (size() == buffer.size())
560 return _equals<t_memory_manager::allocator::isPrimitive()>(buffer);
564 [[nodiscard]]
decltype(
auto) get(t_index_type index)
566 lib_assert(index < size(),
"Buffer out of bounds");
567 return m_memory_interface.get(index);
569 [[nodiscard]]
decltype(
auto) get(t_index_type index)
const
571 lib_assert(index < size(),
"Buffer out of bounds");
572 return m_memory_interface.get(index);
576 [[nodiscard]]
Buffer getAll(t_index_type start, t_index_type size)
579 buff.addAll(begin(start), size);
582 [[nodiscard]] t_index_type indexOf(
const t_type& element)
const
584 for (t_index_type i = 0; i < size(); ++i)
586 if (get(i) == element)
return i;
588 return Constant<t_index_type>::Invalid;
590 [[nodiscard]] t_index_type indexOf(
const t_type& element, t_index_type start_pos)
const
592 for (t_index_type i = start_pos; i < size(); ++i)
594 if (get(i) == element)
return i;
596 return Constant<t_index_type>::Invalid;
598 [[nodiscard]] t_index_type indexOf(
const t_type& element, t_index_type start_pos, t_index_type search_size)
const
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)
603 if (get(i) == element)
return i;
605 return Constant<t_index_type>::Invalid;
607 [[nodiscard]]
bool isEmpty()
const
611 [[nodiscard]]
decltype(
auto) last()
613 lib_assert(size() != 0,
"Cannot get last: out of bounds");
614 return get(size() - 1);
616 [[nodiscard]]
decltype(
auto) last()
const
618 lib_assert(size() != 0,
"Cannot get last: out of bounds");
619 return get(size() - 1);
621 [[nodiscard]] t_index_type lastIndexOf(
const t_type& element)
const
623 for (t_index_type i = size() - 1; i < size(); --i)
625 if (get(i) == element)
return i;
627 return Constant<t_index_type>::Invalid;
629 void removeIndex(t_index_type location)
631 lib_assert(location < size(),
"Out of bounds remove");
632 t_allocator::Deallocate(m_memory_interface, location, 1);
633 m_memory_interface.removeIndex(location);
635 void removeIndexBackSwap(t_index_type location)
637 swapIndices(location, size() - 1);
640 template<
class t_comparable_type>
641 bool removeElement(
const t_comparable_type& element)
643 for (t_index_type i = size() - 1;
IsValid(i); --i)
645 if (get(i) == element)
653 template<
class t_comparable_type>
654 bool removeElement(
const t_comparable_type& element,
uint04 first)
657 for (t_index_type i = size() - 1; i != first; --i)
659 if (get(i) == element)
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();
681 t_index_type end = size();
682 for (t_index_type i = 0; i < end; i++)
684 if (get(i) ==
object)
686 swapIndices(i, --end);
700 template<
class t_functor>
703 t_index_type end = size();
704 for (t_index_type i = 0; i < end; i++)
708 swapIndices(i--, --end);
721 t_index_type start = 0;
723 for (t_index_type i = 0; i < end; i++)
726 if (get(i) !=
object)
730 m_memory_interface.removeAllIndex(start, end);
738 template<
class t_functor>
741 t_index_type start = 0;
742 t_index_type end = size();
743 for (t_index_type i = 0; i < end; i++)
746 if (!functor(get(i)))
750 m_memory_interface.removeAllIndex(start, size());
752 void removeIndices(t_index_type start, t_index_type size)
756 t_allocator::Deallocate(m_memory_interface, start, size);
757 m_memory_interface.removeAllIndex(start, start + size);
759 template<
class t_range_buffer>
760 void removeIndices(
const t_range_buffer& ranges)
763 uint04 last_delete_index = 0;
765 for (
const auto& range : ranges)
767 t_index_type start = range.first;
768 t_index_type end = range.second;
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;
774 t_allocator::Deallocate(m_memory_interface, start, end - start);
776 m_memory_interface.removeIndices(ranges);
778 void replaceAll(const t_type& var, const t_type& replacement)
780 for (t_index_type i = 0; i < size(); i++)
783 get(i) = replacement;
788 for (t_index_type i = 0; i < size() / 2; i++)
790 m_memory_interface.swap(i, size() - i - 1);
793 void reverse(const t_index_type start, const t_index_type end)
795 const t_index_type size = end - start;
796 for (t_index_type i = 0; i < size / 2; i++)
798 m_memory_interface.swap(start + i, (start + size) - i - 1);
801 template<class t_o_type>
802 void setAll(const t_o_type* src, t_index_type offset, t_index_type size)
804 m_memory_interface.template setAll<t_memory_manager::allocator::isPrimitive()>(src, offset, size);
806 void setAll(const Buffer& buffer, t_index_type offset, t_index_type size)
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);
811 void setAll(const Buffer& buffer, t_index_type offset, t_index_type other_offset, t_index_type size)
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);
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)
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)
824 m_memory_interface.setSize(offset + fill_size);
826 const t_type value(fill_element);
827 if (t_memory_manager::allocator::isPrimitive() || size() == old_size)
829 m_memory_interface.setAll(value, offset, fill_size);
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);
838 void setSize(t_index_type new_size)
840 if (new_size == size())
844 void resize(t_index_type new_size)
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);
853 void setSize(const t_index_type new_size, const t_type& fill_element)
855 if (new_size == size())
857 if (new_size < size())
859 t_allocator::Deallocate(m_memory_interface, new_size, size() - new_size);
860 m_memory_interface.setSize(new_size);
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);
869 [[nodiscard]] constexpr t_index_type size() const
871 return m_memory_interface.filledSize();
873 void swapElements(const t_type& element1, const t_type& element2)
875 if (element1 == element2)
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++)
881 if (get(i) == element1)
884 if (IsValid(index_2))
886 swapIndices(index_1, index_2);
890 else if (get(i) == element2)
893 if (IsValid(index_1))
895 swapIndices(index_1, index_2);
901 void swapAllElements(const t_type& element1, const t_type& element2)
903 if (element1 == element2)
905 for (t_index_type ii = 0; ii < size(); ++ii)
907 if (get(ii) == element1)
909 else if (get(ii) == element2)
913 void swapIndices(t_index_type index_1, t_index_type index_2)
915 std::swap(get(index_1), get(index_2));
917 void move(t_index_type from, t_index_type to)
921 t_type object = get(from);
929 struct primitiveUniqueDataComparison
931 bool operator()(const t_type& lhs, const t_type& rhs)
933 return memcmp(&lhs, &rhs, sizeof(t_type)) > 0;
936 std::sort(begin(), end(), primitiveUniqueDataComparison());
940 std::sort(begin(), end());
942 void sortRange(t_index_type start, t_index_type end)
944 std::sort(begin() + start, begin() + end);
948 if constexpr (t_memory_manager::allocator::isPrimitive())
952 setSize(cast<t_index_type>(std::unique(begin(), end()) - begin()));
954 void setUniquePresorted()
956 setSize(cast<t_index_type>(std::unique(begin(), end()) - begin()));
958 t_index_type sortAboutValue(t_index_type value_index)
960 return sortAboutValue(value_index, 0, size());
962 t_index_type sortAboutValue(t_index_type value_index, t_index_type start, t_index_type end)
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)
969 if (get(idx) <= value)
971 std::swap(get(idx), get(store));
975 std::swap(get(end), get(store));
978 inline Buffer& operator=(const Buffer& buffer)
980 if (&(buffer) == this)
981 return *this;//check to ensure not setting equal to ourselves
986 inline Buffer& operator=(Buffer&& buffer) noexcept
988 std::swap(m_memory_interface, buffer.m_memory_interface);
991 [[nodiscard]] inline bool operator==(const Buffer& buffer) const
993 return equals(buffer);
995 [[nodiscard]] inline bool operator>(const Buffer& buffer) const
997 return compare(buffer) > 0;
999 [[nodiscard]] inline bool operator<(const Buffer& buffer) const
1001 return compare(buffer) < 0;
1003 [[nodiscard]] inline bool operator>=(const Buffer& buffer) const
1005 return compare(buffer) >= 0;
1007 [[nodiscard]] inline bool operator<=(const Buffer& buffer) const
1009 return compare(buffer) <= 0;
1011 [[nodiscard]] inline bool operator!=(const Buffer& buffer) const
1013 return !equals(buffer);
1015 [[nodiscard]] decltype(auto) operator[](const t_index_type index)
1019 [[nodiscard]] decltype(auto) operator[](const int index)
1021 return get(cast<t_index_type>(index));
1023 [[nodiscard]] decltype(auto) operator[](const t_index_type value) const
1027 [[nodiscard]] decltype(auto) operator[](const int index) const
1029 return get(cast<t_index_type>(index));
1031 [[nodiscard]] Buffer operator+(const t_type& element) const
1033 Buffer<t_type, t_memory_manager> buffer(1 + size());
1034 buffer.addAll(*this);
1035 buffer.add(element);
1038 const Buffer& operator+=(const t_type& element)
1043 inline Buffer& operator+=(const Buffer& value)
1048 [[nodiscard]] inline Buffer operator+(const Buffer& value) const
1050 Buffer buffer(size() + value.size());
1051 buffer.addAll(*this);
1052 buffer.addAll(value);
1055 [[nodiscard]] bool isSorted() const
1059 for (t_index_type i = 0; i < size() - 1; i++)
1061 if (get(i) >= get(i + 1))
1066 [[nodiscard]] bool isSortedSet() const
1068 for (t_index_type i = 0; i < size() - 1; i++)
1070 if (get(i) > get(i + 1))
1075 [[nodiscard]] constexpr static t_type Type() { t_type* ptr = nullptr; return *ptr; }
1077 [[nodiscard]] constexpr t_memory_manager& memoryInterface()
1079 return m_memory_interface;
1081 [[nodiscard]] constexpr const t_memory_manager& memoryInterface() const
1083 return m_memory_interface;
1086 template<bool t_is_primitive>
1087 [[nodiscard]] bool _equals(const Buffer& buffer) const
1091 return compare(buffer) == 0;
1095 for (t_index_type i = 0; i < size(); i++)
1097 if (get(i) != buffer.get(i))
1104 t_memory_manager m_memory_interface;