AUI Framework  develop
Cross-platform base for C++ UI apps
Loading...
Searching...
No Matches
AMap.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#pragma once
   13#include <map>
   14#include <unordered_map>
   15#include "AUI/Core.h"
   16#include "AException.h"
   17#include <AUI/Common/AVector.h>
   18#include <AUI/Traits/containers.h>
   19#include <AUI/Reflect/AClass.h>
   20#include "AContainerPrototypes.h"
   21
   26template <class KeyType, class ValueType, class Parent>
   27class ABaseMap: public Parent
   28{
   29public:
   30    using iterator = typename Parent::iterator;
   31    using const_iterator = typename Parent::const_iterator;
   32
   33    using Parent::Parent;
   34
   35    ValueType& operator[](KeyType&& k)
   36    {
   37        return Parent::operator[](std::move(k));
   38    }
   39
   40    ValueType& operator[](const KeyType& k)
   41    {
   42        return Parent::operator[](k);
   43    }
   44
   45    const ValueType& operator[](KeyType&& k) const
   46    {
   47        return Parent::at(std::move(k));
   48    }
   49
   50    const ValueType& operator[](const KeyType& k) const
   51    {
   52        return Parent::at(k);
   53    }
   54
   55    // ================
   56
   57    struct contains_iterator
   58    {
   59    private:
   60        iterator mIterator;
   61        bool mValid;
   62        
   63    public:
   64        contains_iterator(const iterator& p, bool valid):
   65            mIterator(p),
   66            mValid(valid)
   67        {
   68            
   69        }
   70        contains_iterator(const contains_iterator& c):
   71            mIterator(c.mIterator),
   72            mValid(c.mValid)
   73        {
   74            
   75        }
   76
   77        operator bool() const noexcept {
   78            return mValid;
   79        }
   80
   81        iterator operator->() const noexcept
   82        {
   83            return mIterator;
   84        }
   85        iterator operator*() const noexcept
   86        {
   87            return mIterator;
   88        }
   89    };
   90    struct const_contains_iterator
   91    {
   92    private:
   93        const_iterator mIterator;
   94        bool mValid;
   95
   96    public:
   97        const_contains_iterator(const const_iterator& p, bool valid):
   98            mIterator(p),
   99            mValid(valid)
  100        {
  101
  102        }
  103        const_contains_iterator(const const_contains_iterator& c):
  104            mIterator(c.mIterator),
  105            mValid(c.mValid)
  106        {
  107
  108        }
  109
  110        operator bool() const noexcept {
  111            return mValid;
  112        }
  113
  114        const_iterator operator->() const noexcept
  115        {
  116            return mIterator;
  117        }
  118        const_iterator operator*() const noexcept
  119        {
  120            return mIterator;
  121        }
  122    };
  123
  124    ValueType& at(const KeyType& key) {
  125        auto it = Parent::find(key);
  126        if (it == Parent::end())
  127            throw AException("no such element: " + AClass<KeyType>::toString(key));
  128        return it->second;
  129    }
  130    const ValueType& at(const KeyType& key) const {
  131        auto it = Parent::find(key);
  132        if (it == Parent::end())
  133            throw AException("no such element: " + AClass<KeyType>::toString(key));
  134        return it->second;
  135    }
  136
  137    [[nodiscard]]
  138    const_contains_iterator contains(const KeyType& key) const noexcept
  139    {
  140        auto it = Parent::find(key);
  141        return const_contains_iterator(it, it != Parent::end());
  142    }
  143
  144    [[nodiscard]]
  145    contains_iterator contains(const KeyType& key) noexcept
  146    {
  147        auto it = Parent::find(key);
  148        return contains_iterator(it, it != Parent::end());
  149    }
  150
  151    [[nodiscard]]
  152    AOptional<ValueType> optional(const KeyType& key) const noexcept {
  153        auto it = Parent::find(key);
  154        if (it == Parent::end()) {
  155            return std::nullopt;
  156        }
  157        return it->second;
  158    }
  159
  160    AVector<KeyType> keyVector() {
  161        AVector<KeyType> r;
  162        r.reserve(Parent::size());
  163        for (auto& p : *this) {
  164            r << p.first;
  165        }
  166        return r;
  167    }
  168    AVector<ValueType> valueVector() {
  169        AVector<ValueType> r;
  170        r.reserve(Parent::size());
  171        for (auto& p : *this) {
  172            r << p.second;
  173        }
  174        return r;
  175    }
  176
  184    template<typename Factory>
  185    ValueType& getOrInsert(const KeyType& keyType, Factory&& factory) noexcept(noexcept(factory())) {
  186        static_assert(std::is_constructible_v<ValueType>, "ValueType is expected to be default-constructible");
  187        auto[it, isElementCreated] = Parent::insert(typename Parent::value_type(keyType, ValueType{}));
  188        static_assert(std::is_same_v<decltype(it), typename Parent::iterator>, "govno");
  189        if (isElementCreated) {
  190            it->second = factory();
  191        }
  192        return it->second;
  193    }
  194
  195    template<typename BinaryOperation>
  196    auto toVector(BinaryOperation&& transformer) const -> AVector<decltype(transformer(std::declval<KeyType>(), std::declval<ValueType>()))> {
  197        AVector<decltype(transformer(std::declval<KeyType>(), std::declval<ValueType>()))> result;
  198        result.reserve(Parent::size());
  199        std::transform(Parent::begin(), Parent::end(), std::back_inserter(result), [transformer = std::forward<BinaryOperation>(transformer)](const typename Parent::value_type& p){
  200            return transformer(p.first, p.second);
  201        });
  202        return result;
  203    }
  204
  205    AVector<std::tuple<KeyType, ValueType>> toVector() const {
  206        return toVector([](const KeyType& k, const ValueType& v) {
  207            return std::make_tuple(k, v);
  208        });
  209    }
  210};
  211
  216template <class KeyType, class ValueType, class Predicate, class Allocator>
  217class AMap: public ABaseMap<KeyType, ValueType, std::map<KeyType, ValueType, Predicate, Allocator>>
  218{
  220
  221    using parent::parent;
  222};
  223
  228template <class KeyType, class ValueType, class Hasher, class Comparer, class Allocator>
  229class AUnorderedMap: public ABaseMap<KeyType, ValueType, std::unordered_map<KeyType, ValueType, Hasher, Comparer, Allocator>>
  230{
  232
  233    using parent::parent;
  234};
  235
  236template<typename Iterator, typename UnaryOperation>
  237inline auto aui::container::to_map(Iterator begin,
  238                                   Iterator end,
  239                                   UnaryOperation&& transformer) {
  240    AMap<decltype(transformer(*begin).first),
  241         decltype(transformer(*begin).second)> result;
  242
  243    for (auto it = begin; it != end; ++it) {
  244        auto[key, value] = transformer(*it);
  245        result[std::move(key)] = std::move(value);
  246    }
  247    return result;
  248}
  249
  250template<typename Iterator, typename UnaryOperation>
  251inline auto aui::container::to_unordered_map(Iterator begin,
  252                                             Iterator end,
  253                                             UnaryOperation&& transformer) {
  254    AUnorderedMap<decltype(transformer(*begin).first),
  255                  decltype(transformer(*begin).second)> result;
  256
  257    for (auto it = begin; it != end; ++it) {
  258        auto[key, value] = transformer(*it);
  259        result[std::move(key)] = std::move(value);
  260    }
  261    return result;
  262}
Base class for maps with AUI extensions.
Definition AMap.h:28
ValueType & getOrInsert(const KeyType &keyType, Factory &&factory) noexcept(noexcept(factory()))
Definition AMap.h:185
Abstract AUI exception.
Definition AException.h:28
A std::map with AUI extensions.
Definition AMap.h:218
A std::unordered_map with AUI extensions.
Definition AMap.h:230
A std::vector with AUI extensions.
Definition AVector.h:39
StoredType & first() noexcept
Definition AVector.h:229
Definition Factory.h:18
auto to_unordered_map(Iterator begin, Iterator end, UnaryOperation &&transformer)
Transforms sequence to unordered_map.
Definition AMap.h:251
auto to_map(Iterator begin, Iterator end, UnaryOperation &&transformer)
Transforms sequence to map.
Definition AMap.h:237
Definition AMap.h:58