aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/utils/ranges.h
blob: 8b574e08d6f30c7587984513c521ec066fe840b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0

#pragma once

#if __cplusplus >= 202002L
#include <ranges>

namespace Utils {

namespace ranges {
using std::ranges::reverse_view;
}

namespace views {
using std::views::reverse;
}

} // namespace Utils
#else
#include <stdexcept>

namespace Utils {

namespace ranges {

template <typename Container>
class reverse_view
{
public:
    using value_type = typename Container::value_type;
    using size_type = typename Container::size_type;
    using Type = value_type;
    using pointer = Type *;
    using const_pointer = const Type *;
    using reference = Type &;
    using const_reference = const Type &;

    using reverse_iterator = typename Container::iterator;
    using iterator = std::reverse_iterator<reverse_iterator>;

    using const_reverse_iterator = typename Container::const_iterator;
    using const_iterator = std::reverse_iterator<const_reverse_iterator>;

    using Iterator = iterator;
    using ConstIterator = const_iterator;

    reverse_view(const Container &k) : d(&k) {}

    const_reverse_iterator rbegin() const noexcept { return d->begin(); }
    const_reverse_iterator rend() const noexcept { return d->end(); }
    const_reverse_iterator crbegin() const noexcept { return d->begin(); }
    const_reverse_iterator crend() const noexcept { return d->end(); }

    const_iterator begin() const noexcept { return const_iterator(rend()); }
    const_iterator end() const noexcept { return const_iterator(rbegin()); }
    const_iterator cbegin() const noexcept { return const_iterator(rend()); }
    const_iterator cend() const noexcept { return const_iterator(rbegin()); }
    const_iterator constBegin() const noexcept { return const_iterator(rend()); }
    const_iterator constEnd() const noexcept { return const_iterator(rbegin()); }

    const_reference front() const noexcept { return *cbegin(); }
    const_reference back() const noexcept { return *crbegin(); }

    [[nodiscard]] size_type size() const noexcept { return d->size(); }
    [[nodiscard]] bool empty() const noexcept { return d->size() == 0; }
    explicit operator bool() const { return d->size(); }

    const_reference operator[](size_type idx) const
    {
        if (idx < size())
            return *(begin() + idx);

        throw std::out_of_range("bad index in reverse side");
    }

private:
    const Container *d;
};
} // namespace ranges

namespace views {

constexpr struct {} reverse;

template <typename T>
inline ranges::reverse_view<T> operator|(const T &container, const decltype(reverse)&)
{
    return ranges::reverse_view(container);
}

} // namsepace views
} // namespace Utils

#endif