spank-olm

WIP Do not look
git clone git://archive.git.mtrnord.blog/MTRNord/spank-olm.git
Log | Files | Refs | README | LICENSE

list.hpp (7887B)


      1 #pragma once
      2 #include <cstddef>
      3 #include <iostream>
      4 #include <utility>
      5 #include <memory>
      6 
      7 namespace spank_olm
      8 {
      9     // Possibly should be replaced by implace_vector. For example https://godbolt.org/z/5P78aG5xE
     10 
     11     /**
     12      * \brief A fixed-size array implementation.
     13      *
     14      * \tparam T The type of elements stored in the array.
     15      * \tparam max_size The maximum number of elements the array can hold.
     16      */
     17     template <typename T, std::size_t max_size>
     18     class FixedSizeArray
     19     {
     20     public:
     21         /**
     22          * \brief Constructs an empty FixedSizeArray.
     23          */
     24         FixedSizeArray() : current_size(0)
     25         {
     26             data = std::make_unique<T*[]>(max_size + 1);
     27         }
     28 
     29         /**
     30          * \brief Copy constructor.
     31          *
     32          * \param other The FixedSizeArray to copy from.
     33          */
     34         FixedSizeArray(const FixedSizeArray& other)
     35             : current_size(other.current_size)
     36         {
     37             data = std::make_unique<T*[]>(max_size + 1);
     38             for (std::size_t i = 0; i < other.current_size; ++i)
     39             {
     40                 data[i] = new T(*other.data[i]);
     41             }
     42         }
     43 
     44 
     45         /**
     46          * \brief Destroys the FixedSizeArray and frees allocated memory.
     47          */
     48         ~FixedSizeArray()
     49         {
     50             clear();
     51         }
     52 
     53         // Error codes
     54         enum ErrorCode
     55         {
     56             SUCCESS = 0, ///< Operation was successful.
     57             INDEX_OUT_OF_RANGE = 1 ///< Index was out of range.
     58         };
     59 
     60         /**
     61          * \brief Inserts a value at the beginning of the array.
     62          *
     63          * \param value The value to insert.
     64          * \return ErrorCode indicating the result of the operation.
     65          */
     66         constexpr ErrorCode insert(const T& value)
     67         {
     68             return insert_at(0, value);
     69         }
     70 
     71         /**
     72          * \brief Inserts a value at a specified index in the array.
     73          *
     74          * \param index The index at which to insert the value.
     75          * \param value The value to insert.
     76          * \return ErrorCode indicating the result of the operation.
     77          */
     78         constexpr ErrorCode insert_at(std::size_t index, const T& value)
     79         {
     80             if (index > current_size)
     81             {
     82                 return INDEX_OUT_OF_RANGE;
     83             }
     84             if (current_size < max_size)
     85             {
     86                 // Shift elements to the right
     87                 for (std::size_t i = current_size; i > index; --i)
     88                 {
     89                     data[i] = std::move(data[i - 1]);
     90                 }
     91                 data[index] = new T(value);
     92                 ++current_size;
     93             }
     94             else
     95             {
     96                 // Drop the last element and shift others to the right
     97                 delete data[max_size - 1];
     98                 for (std::size_t i = max_size - 1; i > index; --i)
     99                 {
    100                     data[i] = std::move(data[i - 1]);
    101                 }
    102                 data[index] = new T(value);
    103             }
    104 
    105             return SUCCESS;
    106         }
    107 
    108         /**
    109          * \brief Erases the element at a specified index.
    110          *
    111          * \param index_given The index of the element to erase.
    112          * \return ErrorCode indicating the result of the operation.
    113          */
    114         constexpr ErrorCode erase_at(const std::size_t index_given)
    115         {
    116             // The list behaves reversed to the array, so we need to reverse the index
    117             const std::size_t index = current_size - index_given - 1;
    118 
    119             if (index >= current_size)
    120             {
    121                 return INDEX_OUT_OF_RANGE;
    122             }
    123             delete data[index];
    124             for (std::size_t i = index; i < current_size - 1; ++i)
    125             {
    126                 data[i] = std::move(data[i + 1]);
    127             }
    128             --current_size;
    129             return SUCCESS;
    130         }
    131 
    132         /**
    133          * \brief Erases the element at the specified pointer position.
    134          *
    135          * \param ptr The pointer to the element to erase.
    136          * \return ErrorCode indicating the result of the operation.
    137          */
    138         constexpr ErrorCode erase(T* const ptr)
    139         {
    140             for (std::size_t i = 0; i < current_size; ++i)
    141             {
    142                 if (data[i] == ptr)
    143                 {
    144                     return erase_at(i);
    145                 }
    146             }
    147             return INDEX_OUT_OF_RANGE;
    148         }
    149 
    150         /**
    151          * \brief Accesses the element at a specified index.
    152          *
    153          * \param index The index of the element to access.
    154          * \return A reference to the element at the specified index.
    155          */
    156         constexpr T& operator[](std::size_t index)
    157         {
    158             return *data[index];
    159         }
    160 
    161         /**
    162          * \brief Accesses the element at a specified index (const version).
    163          *
    164          * \param index The index of the element to access.
    165          * \return A const reference to the element at the specified index.
    166          */
    167         constexpr const T& operator[](std::size_t index) const
    168         {
    169             return *data[index];
    170         }
    171 
    172         /**
    173          * \brief Assigns the contents of another FixedSizeArray to this one.
    174          *
    175          * \param other The FixedSizeArray to copy from.
    176          * \return A reference to this FixedSizeArray.
    177          */
    178         constexpr FixedSizeArray& operator=(const FixedSizeArray& other)
    179         {
    180             if (this != &other)
    181             {
    182                 clear();
    183                 data = std::make_unique<T*[]>(max_size);
    184                 for (std::size_t i = 0; i < other.current_size; ++i)
    185                 {
    186                     data[i] = new T(*other.data[i]);
    187                 }
    188                 current_size = other.current_size;
    189             }
    190             return *this;
    191         }
    192 
    193         /**
    194          * \brief Returns the number of elements in the array.
    195          *
    196          * \return The number of elements in the array.
    197          */
    198         [[nodiscard]] constexpr std::size_t size() const
    199         {
    200             return current_size;
    201         }
    202 
    203         /**
    204          * \brief Checks if the array is empty.
    205          *
    206          * \return True if the array is empty, false otherwise.
    207          */
    208         [[nodiscard]] constexpr bool empty() const
    209         {
    210             return current_size == 0;
    211         }
    212 
    213         // Iterator support
    214         using iterator = T**;
    215         using const_iterator = const T**;
    216 
    217         /**
    218          * \brief Returns an iterator to the beginning of the array.
    219          *
    220          * \return An iterator to the beginning of the array.
    221          */
    222         constexpr iterator begin() { return data.get(); }
    223 
    224         /**
    225          * \brief Returns a const iterator to the beginning of the array.
    226          *
    227          * \return A const iterator to the beginning of the array.
    228          */
    229         constexpr const_iterator begin() const { return const_cast<const_iterator>(data.get()); }
    230 
    231         /**
    232          * \brief Returns an iterator to the end of the array.
    233          *
    234          * \return An iterator to the end of the array.
    235          */
    236         constexpr iterator end() { return data.get() + current_size; }
    237 
    238         /**
    239          * \brief Returns a const iterator to the end of the array.
    240          *
    241          * \return A const iterator to the end of the array.
    242          */
    243         constexpr const_iterator end() const { return const_cast<const_iterator>(data.get() + current_size); }
    244 
    245     private:
    246         /**
    247          * \brief Clears the array and frees allocated memory.
    248          */
    249         void clear()
    250         {
    251             for (std::size_t i = 0; i < current_size; ++i)
    252             {
    253                 delete data[i];
    254             }
    255             current_size = 0;
    256         }
    257 
    258         std::unique_ptr<T*[]> data; ///< Pointer to the array data.
    259         std::size_t current_size; ///< The current number of elements in the array.
    260     };
    261 }