AUI Framework  master
Cross-platform base for C++ UI apps
Loading...
Searching...
No Matches
containers.h
    1/*
    2 * AUI Framework - Declarative UI toolkit for modern C++20
    3 * Copyright (C) 2020-2025 Alex2772 and Contributors
    4 *
    5 * SPDX-License-Identifier: MPL-2.0
    6 *
    7 * This Source Code Form is subject to the terms of the Mozilla Public
    8 * License, v. 2.0. If a copy of the MPL was not distributed with this
    9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
   10 */
   11
   12//
   13// Created by Alex2772 on 11/28/2021.
   14//
   15
   16#pragma once
   17
   18#include <cstdint>
   19#include <cstddef>
   20#include <cmath>
   21#include <iterator>
   22#include <algorithm>
   23#include <cassert>
   24#include <AUI/Common/AOptional.h>
   25#include <AUI/Traits/iterators.h>
   26
   27
   28namespace aui::container {
   29
   30    namespace vector_impl { // basic vector implementation
   31        template<typename T, typename OtherIterator>
   32        auto insert_no_growth(T*& vectorEnd, T* at, OtherIterator begin, OtherIterator end) {
   33            auto distance = std::distance(begin, end);
   34
   35            aui::range insertTargetRange(at, at + distance);
   36
   37            // shift elements to the right
   38            aui::range shiftRange(at, vectorEnd);
   39            if (!shiftRange.empty()) {
   40                auto shiftFrom = std::prev(shiftRange.end());
   41                auto shiftTo = shiftFrom + distance;
   42                for (; shiftFrom >= shiftRange.begin(); --shiftFrom, --shiftTo) {
   43                    if (shiftTo >= vectorEnd) {
   44                        new (shiftTo) T(std::move(*shiftFrom));
   45                    } else {
   46                        *shiftTo = std::move(*shiftFrom);
   47                    }
   48                }
   49            }
   50
   51            auto it = at;
   52            for (; it < vectorEnd && begin != end; ++it, ++begin) {
   53                *it = *begin;
   54            }
   55
   56            for (; begin != end; ++it, ++begin) {
   57                new (it) T(*begin);
   58            }
   59
   60            vectorEnd += distance;
   61            return at;
   62        }
   63
   64        template<typename T, typename OtherIterator>
   65        auto erase(T* vectorBegin, T*& vectorEnd, OtherIterator begin, OtherIterator end) {
   66            if (begin == end) {
   67                return std::prev(vectorEnd);
   68            }
   69
   70            auto eraseIt = begin;
   71            auto remainingValueIt = end;
   72
   73            // move values to the left of erase range
   74            for (; remainingValueIt != vectorEnd; ++eraseIt, ++remainingValueIt) {
   75                *eraseIt = std::move(*remainingValueIt);
   76            }
   77            // destruct remaining values
   78            std::size_t destructedValuesCounter = 0;
   79            for (; eraseIt != vectorEnd; ++eraseIt, ++destructedValuesCounter) {
   80                eraseIt->~T();
   81            }
   82            vectorEnd -= destructedValuesCounter;
   83            return vectorBegin;
   84        }
   85    }
   86
   97    template<typename Container>
   98    void remove_at(Container& c, size_t index) noexcept {
   99        AUI_ASSERTX(c.size() > index, "index out of bounds");
  100        c.erase(c.begin() + index);
  101    }
  102
  110    template<typename Container>
  111    [[nodiscard]]
  112    AOptional<size_t> index_of(const Container& c, const typename Container::const_reference value) noexcept {
  113        auto it = std::find(c.begin(), c.end(), value);
  114        if (it == c.end()) return std::nullopt;
  115        return it - c.begin();
  116    }
  117
  122    template<typename Container>
  123    [[nodiscard]]
  124    bool contains(const Container& c, const typename Container::const_reference value) noexcept {
  125        return std::find(c.begin(), c.end(), value) != c.end();
  126    }
  127
  132    template<typename Iterator>
  133    [[nodiscard]]
  134    bool contains(Iterator begin, Iterator end, const typename std::iterator_traits<Iterator>::value_type& value) noexcept {
  135        return std::find(begin, end, value) != end;
  136    }
  137
  142    template<typename Container>
  143    void remove_all(Container& container, typename Container::const_reference value) noexcept {
  144        container.erase(std::remove_if(container.begin(), container.end(), [&](typename Container::const_reference probe)
  145        {
  146            return value == probe;
  147        }), container.end());
  148    }
  149
  150
  158    template<typename Container, typename T, typename Projection>
  159    void remove_all(Container& container, const T& value, const Projection& projection) noexcept {
  160        container.erase(std::remove_if(container.begin(), container.end(), [&](typename Container::const_reference probe)
  161        {
  162            return value == std::invoke(projection, probe);
  163        }), container.end());
  164    }
  165
  171    template<typename Container>
  172    AOptional<std::size_t> remove_first(Container& container, typename Container::const_reference value) noexcept {
  173        for (auto it = container.begin(); it != container.end(); ++it) {
  174            if (*it == value) {
  175                auto index = std::distance(container.begin(), it);
  176                container.erase(it);
  177                return index;
  178            }
  179        }
  180        return {};
  181    }
  182
  187    template<typename Iterator, typename UnaryOperation>
  188    [[nodiscard]]
  189    auto to_map(Iterator begin, Iterator end, UnaryOperation&& transformer); // implemented in AMap.h
  190
  195    template<typename Iterator, typename UnaryOperation>
  196    [[nodiscard]]
  197    auto to_unordered_map(Iterator begin, Iterator end, UnaryOperation&& transformer); // implemented in AUnorderedMap.h
  198
  203    template<typename LContainer, typename RContainer>
  204    [[nodiscard]]
  205    bool is_subset(LContainer& l, RContainer& r) noexcept {
  206        for (auto& i : r)
  207        {
  208            if (!l.contains(i))
  209            {
  210                return false;
  211            }
  212        }
  213        return true;
  214    }
  215}
  216
  217namespace aui {
  225template<typename Container>
  226[[nodiscard]]
  227AOptional<size_t> indexOf(const Container& c, const typename Container::const_reference value) noexcept {
  228    return aui::container::index_of(c, value);
  229}
  230}
Utility wrapper implementing the stack-allocated (fast) optional idiom.
Definition AOptional.h:33
bool is_subset(LContainer &l, RContainer &r) noexcept
Definition containers.h:205
AOptional< size_t > index_of(const Container &c, const typename Container::const_reference value) noexcept
Finds the index of the first occurrence of the value.
Definition containers.h:112
AOptional< size_t > indexOf(const Container &c, const typename Container::const_reference value) noexcept
Finds the index of the first occurrence of the value.
Definition containers.h:227
bool contains(const Container &c, const typename Container::const_reference value) noexcept
Definition containers.h:124
auto to_unordered_map(Iterator begin, Iterator end, UnaryOperation &&transformer)
Transforms sequence to unordered_map.
Definition AMap.h:251
AOptional< std::size_t > remove_first(Container &container, typename Container::const_reference value) noexcept
Removes first occurrence of value.
Definition containers.h:172
auto to_map(Iterator begin, Iterator end, UnaryOperation &&transformer)
Transforms sequence to map.
Definition AMap.h:237
void remove_at(Container &c, size_t index) noexcept
Removes element at the specified index.
Definition containers.h:98
void remove_all(Container &container, typename Container::const_reference value) noexcept
Removes all occurrences of value.
Definition containers.h:143
#define AUI_ASSERTX(condition, what)
Asserts that the passed condition evaluates to true. Adds extra message string.
Definition Assert.h:74