1//===-- Standalone implementation of iterator -------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_ITERATOR_H
10#define LLVM_LIBC_SRC___SUPPORT_CPP_ITERATOR_H
11
12#include "hdr/types/size_t.h"
13#include "src/__support/CPP/type_traits/enable_if.h"
14#include "src/__support/CPP/type_traits/is_convertible.h"
15#include "src/__support/CPP/type_traits/is_same.h"
16#include "src/__support/macros/attributes.h"
17#include "src/__support/macros/config.h"
18
19namespace LIBC_NAMESPACE_DECL {
20namespace cpp {
21
22struct input_iterator_tag {};
23struct random_access_iterator_tag : input_iterator_tag {};
24
25template <typename T> struct iterator_traits;
26template <typename T> struct iterator_traits<T *> {
27 using reference = T &;
28 using iterator_category = random_access_iterator_tag;
29 using value_type = T;
30};
31
32template <typename Iter> class reverse_iterator {
33 Iter current;
34
35public:
36 using reference = typename iterator_traits<Iter>::reference;
37 using value_type = typename iterator_traits<Iter>::value_type;
38 using iterator_type = Iter;
39
40 LIBC_INLINE reverse_iterator() : current() {}
41 LIBC_INLINE constexpr explicit reverse_iterator(Iter it) : current(it) {}
42
43 template <typename Other,
44 cpp::enable_if_t<!cpp::is_same_v<Iter, Other> &&
45 cpp::is_convertible_v<const Other &, Iter>,
46 int> = 0>
47 LIBC_INLINE constexpr explicit reverse_iterator(const Other &it)
48 : current(it) {}
49
50 LIBC_INLINE friend constexpr bool operator==(const reverse_iterator &lhs,
51 const reverse_iterator &rhs) {
52 return lhs.base() == rhs.base();
53 }
54
55 LIBC_INLINE friend constexpr bool operator!=(const reverse_iterator &lhs,
56 const reverse_iterator &rhs) {
57 return lhs.base() != rhs.base();
58 }
59
60 LIBC_INLINE friend constexpr bool operator<(const reverse_iterator &lhs,
61 const reverse_iterator &rhs) {
62 return lhs.base() > rhs.base();
63 }
64
65 LIBC_INLINE friend constexpr bool operator<=(const reverse_iterator &lhs,
66 const reverse_iterator &rhs) {
67 return lhs.base() >= rhs.base();
68 }
69
70 LIBC_INLINE friend constexpr bool operator>(const reverse_iterator &lhs,
71 const reverse_iterator &rhs) {
72 return lhs.base() < rhs.base();
73 }
74
75 LIBC_INLINE friend constexpr bool operator>=(const reverse_iterator &lhs,
76 const reverse_iterator &rhs) {
77 return lhs.base() <= rhs.base();
78 }
79
80 LIBC_INLINE constexpr iterator_type base() const { return current; }
81
82 LIBC_INLINE constexpr reference operator*() const {
83 Iter tmp = current;
84 return *--tmp;
85 }
86 LIBC_INLINE constexpr reverse_iterator operator--() {
87 ++current;
88 return *this;
89 }
90 LIBC_INLINE constexpr reverse_iterator &operator++() {
91 --current;
92 return *this;
93 }
94 LIBC_INLINE constexpr reverse_iterator operator++(int) {
95 reverse_iterator tmp(*this);
96 --current;
97 return tmp;
98 }
99};
100
101namespace cpp_internal {
102
103template <typename It>
104LIBC_INLINE constexpr size_t distance(It first, It last,
105 random_access_iterator_tag) {
106 return last - first;
107}
108
109template <typename It>
110LIBC_INLINE constexpr auto distance(It first, It last, input_iterator_tag) {
111 size_t n = 0;
112 for (; first != last; ++first) {
113 ++n;
114 }
115 return n;
116}
117
118} // namespace cpp_internal
119
120template <typename It> LIBC_INLINE constexpr auto distance(It first, It last) {
121 return cpp_internal::distance(
122 first, last, typename iterator_traits<It>::iterator_category{});
123}
124
125} // namespace cpp
126} // namespace LIBC_NAMESPACE_DECL
127
128#endif // LLVM_LIBC_SRC___SUPPORT_CPP_ITERATOR_H
129