/* * libfud * Copyright 2024 Dominick Allen * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef FUD_FIXED_VECTOR_HPP #define FUD_FIXED_VECTOR_HPP #include "fud_assert.hpp" #include "fud_config.hpp" #include "fud_option.hpp" #include "fud_span.hpp" #include namespace fud { template class FixedVector { static_assert(Size > 0); using ValueType = T; private: T m_data[Size]; // NOLINT(cppcoreguidelines-avoid-c-arrays) size_t m_length; public: [[nodiscard]] constexpr size_t size() const { return Size; } constexpr T* data() noexcept { return m_data; } constexpr const T* data() const noexcept { return m_data; } constexpr T* begin() noexcept { return m_data; } constexpr const T* begin() const noexcept { return m_data; } constexpr T* end() noexcept { return m_data + Size; } constexpr const T* end() const noexcept { return m_data + Size; } constexpr T& operator[](size_t index) { if constexpr (fudBoundsChecking) { fudAssert(m_data != nullptr); fudAssert(index < m_length); } return m_data[index]; } constexpr const T& operator[](size_t index) const { if constexpr (fudBoundsChecking) { fudAssert(m_data != nullptr); fudAssert(index < m_length); } return m_data[index]; } constexpr bool operator==(const FixedVector&) const noexcept = default; constexpr auto operator<=>(const FixedVector& other) const noexcept = default; Span span() { return Span{data(), Size}; } FudStatus resize(size_t count) { if (count == m_length) { return FudStatus::Success; } if (count < m_length) { m_length = count; return FudStatus::Success; } for (size_t index = m_length; index < count; ++index) { m_data = std::move(T()); } m_length = count; return FudStatus::Success; } FudStatus clear() { m_length = 0; return FudStatus::Success; } constexpr Option front() { if (m_length > 0) { return m_data[0]; } return NullOpt; } constexpr Option front() const { if (m_length > 0) { return m_data[0]; } return NullOpt; } constexpr Option back() { if (m_length > 0) { return m_data[m_length - 1]; } return NullOpt; } constexpr Option back() const { if (m_length > 0) { return m_data[m_length - 1]; } return NullOpt; } FudStatus pushBack(const T& value) { if (m_length == Size) { return FudStatus::Full; } m_data[m_length] = value; m_length++; return FudStatus::Success; } FudStatus pushBack(T&& value) { if (m_length == Size) { return FudStatus::Full; } m_data[m_length] = std::move(value); m_length++; return FudStatus::Success; } Result popBack() { if (m_data == nullptr) { return FudStatus::ObjectInvalid; } if (m_length == 0) { return FudStatus::Empty; } auto result{std::move(m_data[m_length - 1])}; m_length--; return result; } FudStatus eraseBack() { if (m_data == nullptr) { return FudStatus::ObjectInvalid; } if (m_length == 0) { return FudStatus::Empty; } m_length--; return FudStatus::Success; } FudStatus insert(size_t index, const T& value) { if (index > m_length) { return FudStatus::IndexInvalid; } if (index == m_length) { return pushBack(value); } if (m_length == Size) { return FudStatus::Full; } m_data[m_length] = std::move(m_data[m_length - 1]); for (size_t backIndex = m_length - 1; backIndex > index; --backIndex) { m_data[backIndex] = std::move(m_data[backIndex - 1]); } m_data[index] = value; m_length++; return FudStatus::Success; } FudStatus insert(size_t index, T&& value) { if (index > m_length) { return FudStatus::IndexInvalid; } if (index == m_length) { return pushBack(std::move(value)); } if (m_length == Size) { return FudStatus::Full; } m_data[m_length] = std::move(m_data[m_length - 1]); for (size_t backIndex = m_length - 1; backIndex > index; --backIndex) { m_data[backIndex] = std::move(m_data[backIndex - 1]); } m_data[index] = std::move(value); m_length++; return FudStatus::Success; } FudStatus erase(size_t index) { if (index >= m_length) { return FudStatus::IndexInvalid; } for (size_t fwdIndex = index; fwdIndex + 1 < m_length; fwdIndex++) { m_data[fwdIndex] = std::move(m_data[fwdIndex + 1]); } m_length--; return FudStatus::Success; } private: FudStatus cleanup() noexcept { auto status = clear(); m_length = 0; return status; } }; } // namespace fud #endif