commit b022b84866bcc11cfed4a6748fb9cd6030cbd904
parent f0202a0f3c2de18642da5027901f4dc80e149fd7
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date: Sat, 16 Nov 2024 15:44:14 +0100
add more functionality to hybrid container
Diffstat:
1 file changed, 221 insertions(+), 21 deletions(-)
diff --git a/source/baseLib/hybridcontainer.h b/source/baseLib/hybridcontainer.h
@@ -2,6 +2,10 @@
#include <vector>
#include <array>
+#include <stdexcept>
+#include <initializer_list>
+#include <type_traits>
+#include <algorithm>
namespace baseLib
{
@@ -11,7 +15,10 @@ namespace baseLib
static_assert(MaxFixedSize > 0, "MaxFixedSize must be greater than 0");
public:
- HybridContainer() {}
+ using Iterator = T*;
+ using ConstIterator = const T*;
+
+ HybridContainer() = default;
HybridContainer(HybridContainer&& _source) noexcept
: m_array(std::move(_source.m_array))
@@ -38,6 +45,18 @@ namespace baseLib
m_vector.assign(_list);
}
+ explicit HybridContainer(const std::vector<T>& _list) : m_size(_list.size()), m_useArray(_list.size() <= MaxFixedSize)
+ {
+ if(m_useArray)
+ std::copy(_list.begin(), _list.end(), m_array.begin());
+ else
+ m_vector = _list;
+ }
+
+ HybridContainer(std::vector<T>&& _list) : m_size(_list.size()), m_useArray(false), m_vector(std::move(_list))
+ {
+ }
+
~HybridContainer() = default;
template<typename U>
@@ -101,52 +120,218 @@ namespace baseLib
return m_vector.back();
}
- T& operator[](const size_t _index)
+ bool empty() const
+ {
+ return m_size == 0;
+ }
+
+ size_t size() const
+ {
+ return m_size;
+ }
+
+ void clear()
+ {
+ m_size = 0;
+ m_useArray = true;
+ }
+
+ ConstIterator begin() const
{
if (m_useArray)
+ return m_array.data();
+ return m_vector.data();
+ }
+
+ Iterator begin()
+ {
+ if (m_useArray)
+ return m_array.data();
+ return m_vector.data();
+ }
+
+ ConstIterator end() const { return begin() + m_size; }
+ Iterator end() { return begin() + m_size; }
+
+ void swap(HybridContainer& _other) noexcept
+ {
+ std::swap(m_array, _other.m_array);
+ std::swap(m_size, _other.m_size);
+ std::swap(m_useArray, _other.m_useArray);
+ std::swap(m_vector, _other.m_vector);
+ }
+
+ void swap(std::vector<T>& _other) noexcept
+ {
+ _other.swap(m_vector);
+
+ if (m_useArray && m_size)
+ _other.assign(m_array.begin(), m_array.begin() + m_size);
+
+ m_useArray = false;
+ m_size = m_vector.size();
+ }
+
+ template<typename U>
+ void append(const U& _data)
+ {
+ if (_data.size() + size() > MaxFixedSize)
{
- if (_index >= m_size)
+ switchToVector();
+ m_vector.insert(m_vector.end(), _data.begin(), _data.end());
+ }
+ else if (!m_useArray)
+ {
+ m_vector.insert(m_vector.end(), _data.begin(), _data.end());
+ }
+ else
+ {
+ std::copy(_data.begin(), _data.end(), m_array.begin() + m_size);
+ }
+
+ m_size += _data.size();
+ }
+
+ void assign(const T* _data, const size_t _size)
+ {
+ if (_size > MaxFixedSize)
+ {
+ switchToVector();
+ m_vector.assign(_data, _data + _size);
+ }
+ else if (!m_useArray)
+ {
+ m_vector.assign(_data, _data + _size);
+ }
+ else
+ {
+ std::copy(_data, _data + _size, m_array.begin());
+ }
+ m_size = _size;
+ }
+
+ template<size_t Size> void assign(const std::array<T, Size>& _data) { assign(_data.begin(), _data.end()); }
+ void assign(const std::vector<T>& _data) { assign(_data.begin(), _data.end()); }
+ void assign(const std::initializer_list<T>& _data) { assign(_data.begin(), _data.end()); }
+ void assign(ConstIterator _first, ConstIterator _last) { assign(_first, _last - _first); }
+
+ void erase(const ConstIterator _first, const ConstIterator _last)
+ {
+ if (_first < begin() || _last > end())
+ throw std::out_of_range("Iterator out of range");
+
+ const auto offset = _first - begin();
+ const auto count = _last - _first;
+
+ if (m_useArray)
+ {
+ std::copy(_last, end(), begin() + offset);
+ m_size -= count;
+ return;
+ }
+
+ m_vector.erase(m_vector.begin() + offset, m_vector.begin() + offset + count);
+ m_size = m_vector.size();
+ }
+
+ void erase(const ConstIterator _position) { erase(_position, _position + 1); }
+
+ void insert(const ConstIterator _position, const T& _value)
+ {
+ if (_position < begin() || _position > end())
+ throw std::out_of_range("Iterator out of range");
+
+ const auto offset = _position - begin();
+
+ if (m_useArray)
+ {
+ if (m_size == MaxFixedSize)
{
- throw std::out_of_range("Index out of range");
+ switchToVector();
+ }
+ else
+ {
+ std::copy_backward(begin() + offset, end(), end() + 1);
+ m_array[offset] = _value;
+ ++m_size;
+ return;
}
- return m_array[_index];
}
- return m_vector[_index];
+ m_vector.insert(m_vector.begin() + offset, _value);
+ ++m_size;
}
- const T& operator[](const size_t _index) const
+ template<typename Iter>
+ void insert(const ConstIterator _position, Iter _first, Iter _last)
{
- return const_cast<HybridContainer*>(this)->operator[](_index);
- }
+ if (_position < begin() || _position > end())
+ throw std::out_of_range("Iterator out of range");
- bool empty() const
+ const auto offset = _position - begin();
+
+ if (m_useArray)
+ {
+ if (m_size + (_last - _first) > MaxFixedSize)
+ {
+ switchToVector();
+ }
+ else
+ {
+ const auto count = _last - _first;
+ std::copy_backward(begin() + offset, end(), end() + count);
+ std::copy(_first, _last, begin() + offset);
+ m_size += count;
+ return;
+ }
+ }
+
+ m_vector.insert(m_vector.begin() + offset, _first, _last);
+ m_size = m_vector.size();
+ }
+
+ void reserve(size_t _size, const bool _switchToVectorIfNeeded = false)
{
- return m_size == 0;
+ if (_size < MaxFixedSize)
+ return;
+
+ if (m_useArray && !_switchToVectorIfNeeded)
+ return;
+
+ switchToVector();
+ m_vector.reserve(_size);
}
- size_t size() const
+ const T* data() const
{
- return m_size;
+ if (m_useArray)
+ return m_array.data();
+ return m_vector.data();
}
- void clear()
+ T* data()
{
- m_size = 0;
- m_useArray = true;
+ if (m_useArray)
+ return m_array.data();
+ return m_vector.data();
}
- auto begin() const
+ T& operator[](const size_t _index)
{
if (m_useArray)
- return &m_array[0];
+ {
+ if (_index >= m_size)
+ throw std::out_of_range("Index out of range");
- return &m_vector[0];
+ return m_array[_index];
+ }
+
+ return m_vector[_index];
}
- auto end() const
+ const T& operator[](const size_t _index) const
{
- return begin() + m_size;
+ return const_cast<HybridContainer*>(this)->operator[](_index);
}
HybridContainer& operator=(const HybridContainer& _source)
@@ -264,9 +449,24 @@ namespace baseLib
return *this;
}
+ void resize(size_t _size)
+ {
+ if (_size <= MaxFixedSize)
+ {
+ for (size_t i=m_size; i<_size; ++i)
+ m_array[i] = T();
+ m_size = _size;
+ return;
+ }
+ m_vector.resize(_size);
+ m_size = _size;
+ }
+
private:
void switchToVector()
{
+ if (!m_useArray)
+ return;
m_useArray = false;
m_vector.assign(m_array.begin(), m_array.begin() + m_size);
}