gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

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:
Msource/baseLib/hybridcontainer.h | 242++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
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); }