// Copyright (C) 2017 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp // I'm not proud of those five following lines but ti's hard to do with another way now #ifdef NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION #define NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION_DEFINED #else #define NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION #endif #include #include #include #include #include #include #include namespace Nz { /*! * \ingroup core * \class Nz::StackVector * \brief Core class that represents a stack-allocated (if alloca is present) vector, that is with a capacity different from its size */ template StackVector::StackVector(T* stackMemory, std::size_t capacity) : m_capacity(capacity), m_size(0), m_ptr(stackMemory) { } template StackVector::~StackVector() { clear(); #ifndef NAZARA_ALLOCA_SUPPORT OperatorDelete(m_ptr); #endif } template typename StackVector::reference StackVector::back() { assert(m_size != 0); return m_ptr[m_size - 1]; } template typename StackVector::const_reference StackVector::back() const { assert(m_size != 0); return m_ptr[m_size - 1]; } template typename StackVector::iterator StackVector::begin() noexcept { return iterator(&m_ptr[0]); } template typename StackVector::const_iterator StackVector::begin() const noexcept { return const_iterator(&m_ptr[0]); } template typename StackVector::size_type StackVector::capacity() const noexcept { return m_capacity; } template void StackVector::clear() noexcept { resize(0); } template typename StackVector::const_iterator StackVector::cbegin() const noexcept { return const_iterator(&m_ptr[0]); } template typename StackVector::const_iterator StackVector::cend() const noexcept { return const_iterator(&m_ptr[m_size]); } template typename StackVector::const_reverse_iterator StackVector::crbegin() const noexcept { return const_reverse_iterator(&m_ptr[m_size]); } template typename StackVector::const_reverse_iterator StackVector::crend() const noexcept { return const_reverse_iterator(&m_ptr[0]); } template T* StackVector::data() noexcept { return m_ptr; } template const T* StackVector::data() const noexcept { return m_ptr; } template template typename StackVector::iterator StackVector::emplace(const_iterator pos, Args&& ...args) { assert(m_size < m_capacity); assert(pos >= begin() && pos <= end()); std::size_t index = std::distance(begin(), pos); if (pos < end()) { iterator lastElement = end() - 1; PlacementNew(&m_ptr[m_size], std::move(*lastElement)); if (&m_ptr[index] < lastElement) std::move(&m_ptr[index], lastElement, &m_ptr[index + 1]); } m_size++; return PlacementNew(&m_ptr[index], std::forward(args)...); } template template typename StackVector::reference Nz::StackVector::emplace_back(Args&&... args) { assert(m_size < m_capacity); return *PlacementNew(&m_ptr[m_size++], std::forward(args)...); } template bool StackVector::empty() const noexcept { return m_size == 0; } template typename StackVector::iterator StackVector::end() noexcept { return iterator(&m_ptr[m_size]); } template typename StackVector::const_iterator StackVector::end() const noexcept { return const_iterator(&m_ptr[m_size]); } template typename StackVector::iterator StackVector::erase(const_iterator pos) { assert(pos < end()); std::size_t index = std::distance(begin(), pos); std::move(pos + 1, end(), pos); pop_back(); return iterator(&m_ptr[index]); } template typename StackVector::iterator StackVector::erase(const_iterator first, const_iterator last) { if (first == last) return first; assert(first < last); assert(first >= begin() && last <= end()); std::size_t index = std::distance(begin(), first); std::move(last, end(), first); resize(size() - (last - first)); return iterator(&m_ptr[index]); } template typename StackVector::reference StackVector::front() noexcept { return m_ptr[0]; } template typename StackVector::const_reference StackVector::front() const noexcept { return m_ptr[0]; } template typename StackVector::iterator StackVector::insert(const_iterator pos, const T& value) { return emplace(pos, value); } template typename StackVector::iterator StackVector::insert(const_iterator pos, T&& value) { return emplace(pos, std::move(value)); } template typename StackVector::size_type StackVector::max_size() const noexcept { return capacity(); } template typename StackVector::reference StackVector::push_back(const T& value) noexcept(std::is_nothrow_copy_constructible::value) { assert(m_size < m_capacity); return *PlacementNew(&m_ptr[m_size++], value); } template typename StackVector::reference StackVector::push_back(T&& value) noexcept(std::is_nothrow_move_constructible::value) { assert(m_size < m_capacity); return *PlacementNew(&m_ptr[m_size++], std::move(value)); } template void StackVector::pop_back() { assert(!empty()); PlacementDestroy(&m_ptr[--m_size]); } template void StackVector::resize(size_type count) { assert(count < m_capacity); if (count > m_size) { for (std::size_t i = m_size; i < count; ++i) PlacementNew(&m_ptr[i]); m_size = count; } else if (count < m_size) { for (std::size_t i = count; i < m_size; ++i) PlacementDestroy(&m_ptr[i]); m_size = count; } } template void StackVector::resize(size_type count, const value_type& value) { assert(count < m_capacity); if (count > m_size) { for (std::size_t i = m_size; i < count; ++i) PlacementNew(&m_ptr[i], value); m_size = count; } else if (count < m_size) { for (std::size_t i = count; i < m_size; ++i) PlacementDestroy(&m_ptr[i]); m_size = count; } } template typename StackVector::reverse_iterator StackVector::rbegin() noexcept { return reverse_iterator(&m_ptr[m_size]); } template typename StackVector::const_reverse_iterator StackVector::rbegin() const noexcept { return reverse_iterator(&m_ptr[m_size]); } template typename StackVector::reverse_iterator StackVector::rend() noexcept { return reverse_iterator(&m_ptr[0]); } template typename StackVector::const_reverse_iterator StackVector::rend() const noexcept { return reverse_iterator(&m_ptr[0]); } template typename StackVector::size_type StackVector::size() const noexcept { return m_size; } template typename StackVector::reference StackVector::operator[](size_type pos) { assert(pos < m_size); return m_ptr[pos]; } template typename StackVector::const_reference StackVector::operator[](size_type pos) const { assert(pos < m_size); return m_ptr[pos]; } } #include // If we have defined the constant, then we have to undefine it (to avoid bloating in the engine) #ifndef NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION_DEFINED #undef NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION #endif