#ifndef SDV_SEQUENCE_INL #define SDV_SEQUENCE_INL #ifndef SDV_SEQUENCE_H #error Do not include "sequence.inl" directly. Include "sequence.h" instead! #endif //!defined SDV_SEQUENCE_H namespace sdv { template inline sequence::sequence() noexcept {} template sequence::~sequence() { clear(); } template inline sequence::sequence(size_t nCount, const T& rtValue) : sequence() { insert(begin(), nCount, rtValue); } template inline sequence::sequence(size_t nCount) : sequence() { T t{}; insert(begin(), nCount, t); } template template inline sequence::sequence(TIterator itFirst, TIterator itLast) : sequence() { insert(begin(), itFirst, itLast); } template inline sequence::sequence(const sequence& rseq) : sequence() { if (!rseq.empty()) { resize(rseq.size()); if (m_ptrData) std::copy_n(rseq.data(), std::min(rseq.size(), size()), m_ptrData.get()); } } /// @cond DOXYGEN_IGNORE template template inline sequence::sequence(const sequence& rseq) : sequence() { if (!rseq.empty()) { resize(rseq.size()); if (m_ptrData) std::copy_n(rseq.data(), std::min(rseq.size(), size()), m_ptrData.get()); } } /// @endcond template inline sequence::sequence(sequence&& rseq) noexcept : sequence() { m_ptrData = std::move(rseq.m_ptrData); } /// @cond DOXYGEN_IGNORE template template inline sequence::sequence(sequence&& rseq) noexcept : sequence() { m_ptrData = std::move(rseq.buffer()); } /// @endcond template inline sequence::sequence(std::vector& rvec) : sequence() { if (!rvec.empty()) { resize(rvec.size()); if (m_ptrData) std::copy_n(rvec.data(), std::min(rvec.size(), size()), m_ptrData.get()); } } template inline sequence::sequence(std::initializer_list ilist) : sequence() { insert(begin(), ilist); } template inline sequence& sequence::operator=(const sequence& rseq) { clear(); if (!rseq.empty()) { resize(rseq.size()); if (m_ptrData) std::copy_n(rseq.data(), std::min(rseq.size(), size()), m_ptrData.get()); } return *this; } /// @cond DOXYGEN_IGNORE template template inline sequence& sequence::operator=(const sequence& rseq) { clear(); if (!rseq.empty()) { resize(rseq.size()); if (m_ptrData) std::copy_n(rseq.data(), std::min(rseq.size(), size()), m_ptrData.get()); } return *this; } /// @endcond /// @cond DOXYGEN_IGNORE template template inline sequence& sequence::operator=(sequence&& rseq) noexcept { clear(); m_ptrData = std::move(rseq.buffer()); return *this; } /// @endcond template inline sequence& sequence::operator=(sequence&& rseq) noexcept { clear(); m_ptrData = std::move(rseq.m_ptrData); return *this; } template inline sequence& sequence::operator=(const std::vector& rvec) { clear(); if (!rvec.empty()) { resize(rvec.size()); if (m_ptrData) std::copy_n(rvec.data(), std::min(rvec.size(), size()), m_ptrData.get()); } return *this; } template inline sequence& sequence::operator=(std::initializer_list ilist) { clear(); insert(begin(), ilist); return *this; } template inline void sequence::assign(size_t nCount, const T& rtValue) { clear(); insert(begin(), nCount, rtValue); } template template inline void sequence::assign(TIterator itFirst, TIterator itLast) { clear(); insert(begin(), itFirst, itLast); } template inline void sequence::assign(std::initializer_list ilist) { clear(); insert(begin(), ilist); } template inline typename sequence::reference sequence::at(size_t nPos) { if (nPos >= size()) { XIndexOutOfRange exception; exception.uiIndex = static_cast(nPos); exception.uiSize = static_cast(size()); throw exception; } return m_ptrData[nPos]; } template inline typename sequence::const_reference sequence::at(size_t nPos) const { if (nPos >= size()) { XIndexOutOfRange exception; exception.uiIndex = static_cast(nPos); exception.uiSize = static_cast(size()); throw exception; } return m_ptrData[nPos]; } template inline typename sequence::reference sequence::operator[](size_t nPos) { if (nPos >= size()) { XIndexOutOfRange exception; exception.uiIndex = static_cast(nPos); exception.uiSize = static_cast(size()); throw exception; } return m_ptrData[nPos]; } template inline typename sequence::const_reference sequence::operator[](size_t nPos) const { if (nPos >= size()) { XIndexOutOfRange exception; exception.uiIndex = static_cast(nPos); exception.uiSize = static_cast(size()); throw exception; } return m_ptrData[nPos]; } template inline T& sequence::front() { if (!size()) { XIndexOutOfRange exception; exception.uiIndex = static_cast(0); exception.uiSize = static_cast(size()); throw exception; } return m_ptrData[0]; } template inline const T& sequence::front() const { if (!size()) { XIndexOutOfRange exception; exception.uiIndex = static_cast(0); exception.uiSize = static_cast(size()); throw exception; } return m_ptrData[0]; } template inline T& sequence::back() { if (!size()) { XIndexOutOfRange exception; exception.uiIndex = static_cast(0); exception.uiSize = static_cast(size()); throw exception; } return m_ptrData[size() - 1]; } template inline const T& sequence::back() const { if (!size()) { XIndexOutOfRange exception; exception.uiIndex = static_cast(0); exception.uiSize = static_cast(size()); throw exception; } return m_ptrData[size() - 1]; } template inline sequence::operator std::vector() const { std::vector vec; if (size()) { try { vec.resize(size()); } catch (const std::bad_alloc&) { core::XAllocFailed exception; exception.uiSize = static_cast(size() * sizeof(T)); throw exception; } std::copy_n(data(), std::min(size(), vec.size()), &vec.front()); } return vec; } template inline const T* sequence::data() const noexcept { return m_ptrData.get(); } template inline pointer& sequence::buffer() noexcept { return m_ptrData; } template inline typename sequence::iterator sequence::begin() noexcept { return iterator(this); } template inline typename sequence::const_iterator sequence::begin() const noexcept { return iterator(this); } template inline typename sequence::const_iterator sequence::cbegin() const noexcept { return const_iterator(this); } template inline typename sequence::reverse_iterator sequence::rbegin() noexcept { return reverse_iterator(this); } template inline typename sequence::const_reverse_iterator sequence::rbegin() const noexcept { return reverse_iterator(this); } template inline typename sequence::const_reverse_iterator sequence::crbegin() const noexcept { return const_reverse_iterator(this); } template inline typename sequence::iterator sequence::end() noexcept { iterator it(this); it += std::numeric_limits::max(); return it; } template inline typename sequence::const_iterator sequence::end() const noexcept { iterator it(this); it += std::numeric_limits::max(); return it; } template inline typename sequence::const_iterator sequence::cend() const noexcept { const_iterator it(this); it += std::numeric_limits::max(); return it; } template inline typename sequence::reverse_iterator sequence::rend() noexcept { reverse_iterator it(this); it += std::numeric_limits::max(); return it; } template inline typename sequence::const_reverse_iterator sequence::rend() const noexcept { reverse_iterator it(this); it += std::numeric_limits::max(); return it; } template inline typename sequence::const_reverse_iterator sequence::crend() const noexcept { const_reverse_iterator it(this); it += std::numeric_limits::max(); return it; } template inline bool sequence::empty() const { return !size(); } template inline size_t sequence::size() const { return m_ptrData.size(); } template inline size_t sequence::length() const { return m_ptrData.size(); } template inline void sequence::reserve(size_t nNewCap /*= 0*/) { if (nNewCap > size()) resize(nNewCap); } template inline size_t sequence::capacity() const noexcept { return m_ptrData.capacity(); } template inline void sequence::shrink_to_fit() { // Do nothing... } template inline void sequence::clear() { m_ptrData.reset(); } template inline typename sequence::iterator sequence::insert(const_iterator itPos, const T& rtValue) { return insert(itPos, static_cast(1), rtValue); } template inline typename sequence::iterator sequence::insert(const_iterator itPos, T&& rtValue) { T t{}; insert(itPos, static_cast(1), t); iterator it = itPos; *it = std::move(rtValue); return it; } template inline typename sequence::iterator sequence::insert(const_iterator itPos, size_t nCount, const T& rtValue) { if (!itPos.is_valid(*this)) throw XInvalidIterator(); // Determine location size_t nIndex = 0; if (itPos == cend()) nIndex = size(); else if (!empty()) nIndex = &itPos[0] - data(); // Calculate count size_t nCountTemp = nCount; size_t nCurrentLen = size(); if (nFixedSize && nCurrentLen + nCountTemp > nFixedSize) nCountTemp = nFixedSize - nCurrentLen; if (!nCountTemp) return iterator(itPos);; // Allocate space for a new sequence. m_ptrData.resize(nCurrentLen + nCountTemp); // Copy the part following the index. if (nIndex < nCurrentLen) std::copy_backward(data() + nIndex, data() + nCurrentLen, m_ptrData.get() + nCurrentLen + nCountTemp); // Insert the values if (nCountTemp) std::fill_n(m_ptrData.get() + std::min(nIndex, nCurrentLen), nCountTemp, rtValue); return iterator(itPos); } template template inline typename sequence::iterator sequence::insert(const_iterator itPos, TIterator itFirst, TIterator itLast) { if (!itPos.is_valid(*this)) throw XInvalidIterator(); // Count the amount of entries to insert size_t nCount = 0; for (TIterator itIndex = itFirst; itIndex != itLast; itIndex++) nCount++; // Determine location size_t nIndex = 0; if (itPos == cend()) nIndex = size(); else if (!empty()) nIndex = &itPos[0] - data(); // Calculate count size_t nCountTemp = nCount; size_t nCurrentLen = size(); if (nFixedSize && nCurrentLen + nCountTemp > nFixedSize) nCountTemp = nFixedSize - nCurrentLen; if (!nCountTemp) return iterator(itPos);; // Allocate space for a new sequence. m_ptrData.resize(nCurrentLen + nCountTemp); // Copy the part following the index. if (nIndex < nCurrentLen) std::copy_backward(data() + nIndex, data() + nCurrentLen, m_ptrData.get() + nCurrentLen + nCountTemp); // Copy the data for (TIterator itIndex = itFirst; itIndex != itLast; itIndex++) at(nIndex++) = *itIndex; return iterator(itPos); } template inline typename sequence::iterator sequence::insert(const_iterator itPos, std::initializer_list ilist) { if (!itPos.is_valid(*this)) throw XInvalidIterator(); return insert(itPos, ilist.begin(), ilist.end()); } template inline typename sequence::iterator sequence::erase(iterator itPos) { erase(itPos, itPos + 1); return itPos; } template inline typename sequence::iterator sequence::erase(const_iterator itPos) { erase(itPos, itPos + 1); return itPos; } template inline typename sequence::iterator sequence::erase(iterator itFirst, iterator itLast) { erase(const_iterator(itFirst), const_iterator(itLast)); return itFirst; } template inline typename sequence::iterator sequence::erase(const_iterator itFirst, const_iterator itLast) { if (!itFirst.is_valid(*this)) throw XInvalidIterator(); if (!itLast.is_valid(*this)) throw XInvalidIterator(); if (empty()) return cbegin(); // Nothing to do if (itFirst == cend()) return cbegin(); // Nothing to do if (itFirst == itLast) return itFirst; // Nothing to do // Determine location size_t nIndex = &itFirst[0] - data(); size_t nCount = itLast == cend() ? (size() - nIndex) : (&itLast[0] - &itFirst[0]); // Copy any leftover characters if (nCount < size() && nIndex + nCount < size()) { std::copy_n(m_ptrData.get() + nIndex + nCount, size() - nIndex - nCount, m_ptrData.get() + nIndex); resize(size() - nCount); } else resize(nIndex); return itFirst; } template inline void sequence::push_back(const T& rtValue) { insert(end(), rtValue); } template inline void sequence::push_back(T&& rtValue) { insert(end(), std::move(rtValue)); } template inline void sequence::pop_back() { if (empty()) return; // Nothing to do erase(cend() - 1); } template inline void sequence::resize(size_t nCount) { T t{}; resize(nCount, t); } template inline void sequence::resize(size_t nCount, const value_type& rtValue) { if (!nCount) clear(); else { size_t nCurrentLen = size(); m_ptrData.resize(nCount); // False positive of CppCheck - condition is not always true. Suppress warning. // cppcheck-suppress knownConditionTrueFalse if (size() > nCurrentLen) std::fill_n(m_ptrData.get() + nCurrentLen, size() - nCurrentLen, rtValue); } } /// @cond DOXYGEN_IGNORE template template inline void sequence::swap(sequence& rseq) noexcept { sequence seqTemp = std::move(rseq); rseq = std::move(*this); operator=(std::move(seqTemp)); } /// @endcond template inline void swap(sequence& rseqLeft, sequence& rseqRight) noexcept { rseqLeft.swap(rseqRight); } template inline bool operator==(const sequence& rseqLeft, const sequence& rseqRight) { if (rseqLeft.size() != rseqRight.size()) return false; for (size_t nIndex = 0; nIndex < rseqLeft.size(); nIndex++) if (rseqLeft[nIndex] != rseqRight[nIndex]) return false; return true; } template inline bool operator!=(const sequence& rseqLeft, const sequence& rseqRight) { return !operator==(rseqLeft, rseqRight); } template inline bool operator<(const sequence& rseqLeft, const sequence& rseqRight) { for (size_t nIndex = 0; nIndex < std::min(rseqLeft.size(), rseqRight.size()); nIndex++) { if (rseqLeft[nIndex] < rseqRight[nIndex]) return true; if (rseqLeft[nIndex] > rseqRight[nIndex]) return false; } return rseqLeft.size() < rseqRight.size(); } template inline bool operator<=(const sequence& rseqLeft, const sequence& rseqRight) { for (size_t nIndex = 0; nIndex < std::min(rseqLeft.size(), rseqRight.size()); nIndex++) { if (rseqLeft[nIndex] < rseqRight[nIndex]) return true; if (rseqLeft[nIndex] > rseqRight[nIndex]) return false; } return rseqLeft.size() <= rseqRight.size(); } template inline bool operator>(const sequence& rseqLeft, const sequence& rseqRight) { for (size_t nIndex = 0; nIndex < std::min(rseqLeft.size(), rseqRight.size()); nIndex++) { if (rseqLeft[nIndex] < rseqRight[nIndex]) return false; if (rseqLeft[nIndex] > rseqRight[nIndex]) return true; } return rseqLeft.size() > rseqRight.size(); } template inline bool operator>=(const sequence& rseqLeft, const sequence& rseqRight) { for (size_t nIndex = 0; nIndex < std::min(rseqLeft.size(), rseqRight.size()); nIndex++) { if (rseqLeft[nIndex] < rseqRight[nIndex]) return false; if (rseqLeft[nIndex] > rseqRight[nIndex]) return true; } return rseqLeft.size() >= rseqRight.size(); } } // namespace sdv #endif // !defined SDV_SEQUENCE_INL