/* * * Copyright (C) 2024 Brett Terpstra * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef BLT_ARRAY_H #define BLT_ARRAY_H #include #include #include #include #include #include #include "logging.h" namespace blt { template struct metadata_template_t; template<> struct metadata_template_t { // size in number of elements! blt::size_t size; explicit metadata_template_t(blt::size_t size): size(size) {} }; template struct metadata_template_t { Extra extra; // size in number of elements! blt::size_t size; explicit metadata_template_t(blt::size_t size): size(size) {} }; /** * @tparam T type to store inside * @tparam Extra any extra data to store. void will result in zero size increase. */ template class array { public: using iterator = blt::ptr_iterator; using const_iterator = blt::ptr_iterator; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; private: using metadata_t = metadata_template_t; metadata_t metadata; static constexpr blt::size_t ALIGNMENT = std::max(sizeof(metadata_t), alignof(T)); inline T* _data() { return reinterpret_cast(reinterpret_cast(this) + ALIGNMENT); } /** * constructs an array out of a block of memory of size bytes * @param size number of bytes available in the memory allocated to this array. */ explicit array(blt::size_t size): metadata((size - sizeof(metadata)) / sizeof(T)) {} public: inline static array* construct(void* ptr, blt::size_t size) { auto aligned_ptr = std::align(alignof(array), sizeof(array), ptr, size); return new(aligned_ptr) array{size}; } array(const array&) = delete; array(array&&) = delete; array& operator=(const array&) = delete; array& operator=(array&&) = delete; inline T& operator[](blt::size_t index) { return _data()[index]; } inline const T& operator[](blt::size_t index) const { return _data()[index]; } [[nodiscard]] inline T& at(blt::size_t index) { if (index > size()) throw std::runtime_error("Index " + std::to_string(index) += " is outside the bounds of this array!"); return _data()[index]; } [[nodiscard]] inline const T& at(blt::size_t index) const { if (index > size()) throw std::runtime_error("Index " + std::to_string(index) += " is outside the bounds of this array!"); return _data()[index]; } [[nodiscard]] inline T* data() { return _data(); } [[nodiscard]] inline T* data() const { return _data(); } [[nodiscard]] inline blt::size_t size() const { return metadata.size; } [[nodiscard]] inline blt::size_t size_bytes() const { return (metadata.size * sizeof(T)) + sizeof(metadata); } constexpr inline T* operator*() { return data(); } constexpr inline T& front() { return *_data(); } constexpr inline const T& front() const { return *data(); } constexpr inline T& back() { return data()[size() - 1]; } constexpr inline const T& back() const { return data()[size() - 1]; } constexpr inline iterator begin() const noexcept { return data(); } constexpr inline iterator end() const noexcept { return data() + size(); } constexpr inline const_iterator cbegin() const noexcept { return data(); } constexpr inline const_iterator cend() const noexcept { return data() + size(); } constexpr inline reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; } constexpr inline reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; } constexpr inline const_iterator crbegin() const noexcept { return const_reverse_iterator{cend()}; } constexpr inline reverse_iterator crend() const noexcept { return reverse_iterator{cbegin()}; } constexpr inline metadata_t& get_metadata() { return metadata; } constexpr inline const metadata_t& get_metadata() const { return metadata; } ~array() = default; }; } #endif //BLT_ARRAY_H