1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP___ITERATOR_WRAP_ITER_H
11#define _LIBCPP___ITERATOR_WRAP_ITER_H
12
13#include <__config>
14#include <__debug>
15#include <__iterator/iterator_traits.h>
16#include <__memory/addressof.h>
17#include <__memory/pointer_traits.h>
18#include <__type_traits/enable_if.h>
19#include <__type_traits/is_convertible.h>
20
21#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
22#  pragma GCC system_header
23#endif
24
25_LIBCPP_BEGIN_NAMESPACE_STD
26
27template <class _Iter>
28class __wrap_iter
29{
30public:
31    typedef _Iter                                                      iterator_type;
32    typedef typename iterator_traits<iterator_type>::value_type        value_type;
33    typedef typename iterator_traits<iterator_type>::difference_type   difference_type;
34    typedef typename iterator_traits<iterator_type>::pointer           pointer;
35    typedef typename iterator_traits<iterator_type>::reference         reference;
36    typedef typename iterator_traits<iterator_type>::iterator_category iterator_category;
37#if _LIBCPP_STD_VER > 17
38    typedef contiguous_iterator_tag                                    iterator_concept;
39#endif
40
41private:
42    iterator_type __i_;
43public:
44    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter() _NOEXCEPT
45                : __i_()
46    {
47        _VSTD::__debug_db_insert_i(this);
48    }
49    template <class _Up> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
50        __wrap_iter(const __wrap_iter<_Up>& __u,
51            typename enable_if<is_convertible<_Up, iterator_type>::value>::type* = nullptr) _NOEXCEPT
52            : __i_(__u.base())
53    {
54#ifdef _LIBCPP_ENABLE_DEBUG_MODE
55      if (!__libcpp_is_constant_evaluated())
56        __get_db()->__iterator_copy(this, _VSTD::addressof(__u));
57#endif
58    }
59#ifdef _LIBCPP_ENABLE_DEBUG_MODE
60    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
61    __wrap_iter(const __wrap_iter& __x)
62        : __i_(__x.base())
63    {
64      if (!__libcpp_is_constant_evaluated())
65        __get_db()->__iterator_copy(this, _VSTD::addressof(__x));
66    }
67    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
68    __wrap_iter& operator=(const __wrap_iter& __x)
69    {
70        if (this != _VSTD::addressof(__x))
71        {
72            if (!__libcpp_is_constant_evaluated())
73                __get_db()->__iterator_copy(this, _VSTD::addressof(__x));
74            __i_ = __x.__i_;
75        }
76        return *this;
77    }
78    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
79    ~__wrap_iter()
80    {
81      if (!__libcpp_is_constant_evaluated())
82        __get_db()->__erase_i(this);
83    }
84#endif
85    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator*() const _NOEXCEPT
86    {
87        _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
88                             "Attempted to dereference a non-dereferenceable iterator");
89        return *__i_;
90    }
91    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pointer operator->() const _NOEXCEPT
92    {
93        _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
94                             "Attempted to dereference a non-dereferenceable iterator");
95        return _VSTD::__to_address(__i_);
96    }
97    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter& operator++() _NOEXCEPT
98    {
99        _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
100                             "Attempted to increment a non-incrementable iterator");
101        ++__i_;
102        return *this;
103    }
104    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter  operator++(int) _NOEXCEPT
105        {__wrap_iter __tmp(*this); ++(*this); return __tmp;}
106
107    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter& operator--() _NOEXCEPT
108    {
109        _LIBCPP_DEBUG_ASSERT(__get_const_db()->__decrementable(this),
110                             "Attempted to decrement a non-decrementable iterator");
111        --__i_;
112        return *this;
113    }
114    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter  operator--(int) _NOEXCEPT
115        {__wrap_iter __tmp(*this); --(*this); return __tmp;}
116    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter  operator+ (difference_type __n) const _NOEXCEPT
117        {__wrap_iter __w(*this); __w += __n; return __w;}
118    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter& operator+=(difference_type __n) _NOEXCEPT
119    {
120        _LIBCPP_DEBUG_ASSERT(__get_const_db()->__addable(this, __n),
121                             "Attempted to add/subtract an iterator outside its valid range");
122        __i_ += __n;
123        return *this;
124    }
125    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter  operator- (difference_type __n) const _NOEXCEPT
126        {return *this + (-__n);}
127    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter& operator-=(difference_type __n) _NOEXCEPT
128        {*this += -__n; return *this;}
129    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference    operator[](difference_type __n) const _NOEXCEPT
130    {
131        _LIBCPP_DEBUG_ASSERT(__get_const_db()->__subscriptable(this, __n),
132                             "Attempted to subscript an iterator outside its valid range");
133        return __i_[__n];
134    }
135
136    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 iterator_type base() const _NOEXCEPT {return __i_;}
137
138private:
139    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
140    explicit __wrap_iter(const void* __p, iterator_type __x) _NOEXCEPT : __i_(__x)
141    {
142        (void)__p;
143#ifdef _LIBCPP_ENABLE_DEBUG_MODE
144      if (!__libcpp_is_constant_evaluated())
145        __get_db()->__insert_ic(this, __p);
146#endif
147    }
148
149    template <class _Up> friend class __wrap_iter;
150    template <class _CharT, class _Traits, class _Alloc> friend class basic_string;
151    template <class _Tp, class _Alloc> friend class _LIBCPP_TEMPLATE_VIS vector;
152    template <class _Tp, size_t> friend class _LIBCPP_TEMPLATE_VIS span;
153};
154
155template <class _Iter1>
156_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
157bool operator==(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT
158{
159    return __x.base() == __y.base();
160}
161
162template <class _Iter1, class _Iter2>
163_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
164bool operator==(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
165{
166    return __x.base() == __y.base();
167}
168
169template <class _Iter1>
170_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
171bool operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT
172{
173    _LIBCPP_DEBUG_ASSERT(__get_const_db()->__less_than_comparable(_VSTD::addressof(__x), _VSTD::addressof(__y)),
174                         "Attempted to compare incomparable iterators");
175    return __x.base() < __y.base();
176}
177
178template <class _Iter1, class _Iter2>
179_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
180bool operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
181{
182    _LIBCPP_DEBUG_ASSERT(__get_const_db()->__less_than_comparable(&__x, &__y),
183                         "Attempted to compare incomparable iterators");
184    return __x.base() < __y.base();
185}
186
187template <class _Iter1>
188_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
189bool operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT
190{
191    return !(__x == __y);
192}
193
194template <class _Iter1, class _Iter2>
195_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
196bool operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
197{
198    return !(__x == __y);
199}
200
201template <class _Iter1>
202_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
203bool operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT
204{
205    return __y < __x;
206}
207
208template <class _Iter1, class _Iter2>
209_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
210bool operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
211{
212    return __y < __x;
213}
214
215template <class _Iter1>
216_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
217bool operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT
218{
219    return !(__x < __y);
220}
221
222template <class _Iter1, class _Iter2>
223_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
224bool operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
225{
226    return !(__x < __y);
227}
228
229template <class _Iter1>
230_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
231bool operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT
232{
233    return !(__y < __x);
234}
235
236template <class _Iter1, class _Iter2>
237_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
238bool operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
239{
240    return !(__y < __x);
241}
242
243template <class _Iter1, class _Iter2>
244_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
245#ifndef _LIBCPP_CXX03_LANG
246auto operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
247    -> decltype(__x.base() - __y.base())
248#else
249typename __wrap_iter<_Iter1>::difference_type
250operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
251#endif // C++03
252{
253    _LIBCPP_DEBUG_ASSERT(__get_const_db()->__less_than_comparable(_VSTD::addressof(__x), _VSTD::addressof(__y)),
254                         "Attempted to subtract incompatible iterators");
255    return __x.base() - __y.base();
256}
257
258template <class _Iter1>
259_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
260__wrap_iter<_Iter1> operator+(typename __wrap_iter<_Iter1>::difference_type __n, __wrap_iter<_Iter1> __x) _NOEXCEPT
261{
262    __x += __n;
263    return __x;
264}
265
266#if _LIBCPP_STD_VER <= 17
267template <class _It>
268struct __is_cpp17_contiguous_iterator<__wrap_iter<_It> > : true_type {};
269#endif
270
271template <class _It>
272struct _LIBCPP_TEMPLATE_VIS pointer_traits<__wrap_iter<_It> >
273{
274    typedef __wrap_iter<_It> pointer;
275    typedef typename pointer_traits<_It>::element_type element_type;
276    typedef typename pointer_traits<_It>::difference_type difference_type;
277
278    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
279    static element_type *to_address(pointer __w) _NOEXCEPT {
280        return _VSTD::__to_address(__w.base());
281    }
282};
283
284_LIBCPP_END_NAMESPACE_STD
285
286#endif // _LIBCPP___ITERATOR_WRAP_ITER_H
287