1*6777b538SAndroid Build Coastguard Worker // Copyright 2018 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_CONTAINERS_CHECKED_ITERATORS_H_ 6*6777b538SAndroid Build Coastguard Worker #define BASE_CONTAINERS_CHECKED_ITERATORS_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <concepts> 9*6777b538SAndroid Build Coastguard Worker #include <iterator> 10*6777b538SAndroid Build Coastguard Worker #include <memory> 11*6777b538SAndroid Build Coastguard Worker #include <type_traits> 12*6777b538SAndroid Build Coastguard Worker 13*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h" 14*6777b538SAndroid Build Coastguard Worker #include "base/compiler_specific.h" 15*6777b538SAndroid Build Coastguard Worker #include "base/containers/util.h" 16*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr_exclusion.h" 17*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h" 18*6777b538SAndroid Build Coastguard Worker 19*6777b538SAndroid Build Coastguard Worker namespace base { 20*6777b538SAndroid Build Coastguard Worker 21*6777b538SAndroid Build Coastguard Worker template <typename T> 22*6777b538SAndroid Build Coastguard Worker class CheckedContiguousIterator { 23*6777b538SAndroid Build Coastguard Worker public: 24*6777b538SAndroid Build Coastguard Worker using difference_type = std::ptrdiff_t; 25*6777b538SAndroid Build Coastguard Worker using value_type = std::remove_cv_t<T>; 26*6777b538SAndroid Build Coastguard Worker using pointer = T*; 27*6777b538SAndroid Build Coastguard Worker using reference = T&; 28*6777b538SAndroid Build Coastguard Worker using iterator_category = std::contiguous_iterator_tag; 29*6777b538SAndroid Build Coastguard Worker using iterator_concept = std::contiguous_iterator_tag; 30*6777b538SAndroid Build Coastguard Worker 31*6777b538SAndroid Build Coastguard Worker // Required for converting constructor below. 32*6777b538SAndroid Build Coastguard Worker template <typename U> 33*6777b538SAndroid Build Coastguard Worker friend class CheckedContiguousIterator; 34*6777b538SAndroid Build Coastguard Worker 35*6777b538SAndroid Build Coastguard Worker // Required to be able to get to the underlying pointer without triggering 36*6777b538SAndroid Build Coastguard Worker // CHECK failures. 37*6777b538SAndroid Build Coastguard Worker template <typename Ptr> 38*6777b538SAndroid Build Coastguard Worker friend struct std::pointer_traits; 39*6777b538SAndroid Build Coastguard Worker 40*6777b538SAndroid Build Coastguard Worker constexpr CheckedContiguousIterator() = default; 41*6777b538SAndroid Build Coastguard Worker CheckedContiguousIterator(T * start,const T * end)42*6777b538SAndroid Build Coastguard Worker UNSAFE_BUFFER_USAGE constexpr CheckedContiguousIterator(T* start, 43*6777b538SAndroid Build Coastguard Worker const T* end) 44*6777b538SAndroid Build Coastguard Worker : CheckedContiguousIterator(start, start, end) {} 45*6777b538SAndroid Build Coastguard Worker CheckedContiguousIterator(const T * start,T * current,const T * end)46*6777b538SAndroid Build Coastguard Worker UNSAFE_BUFFER_USAGE constexpr CheckedContiguousIterator(const T* start, 47*6777b538SAndroid Build Coastguard Worker T* current, 48*6777b538SAndroid Build Coastguard Worker const T* end) 49*6777b538SAndroid Build Coastguard Worker : start_(start), current_(current), end_(end) { 50*6777b538SAndroid Build Coastguard Worker CHECK_LE(start, current); 51*6777b538SAndroid Build Coastguard Worker CHECK_LE(current, end); 52*6777b538SAndroid Build Coastguard Worker } 53*6777b538SAndroid Build Coastguard Worker 54*6777b538SAndroid Build Coastguard Worker constexpr CheckedContiguousIterator(const CheckedContiguousIterator& other) = 55*6777b538SAndroid Build Coastguard Worker default; 56*6777b538SAndroid Build Coastguard Worker 57*6777b538SAndroid Build Coastguard Worker // Converting constructor allowing conversions like CCI<T> to CCI<const T>, 58*6777b538SAndroid Build Coastguard Worker // but disallowing CCI<const T> to CCI<T> or CCI<Derived> to CCI<Base>, which 59*6777b538SAndroid Build Coastguard Worker // are unsafe. Furthermore, this is the same condition as used by the 60*6777b538SAndroid Build Coastguard Worker // converting constructors of std::span<T> and std::unique_ptr<T[]>. 61*6777b538SAndroid Build Coastguard Worker // See https://wg21.link/n4042 for details. 62*6777b538SAndroid Build Coastguard Worker template <typename U> CheckedContiguousIterator(const CheckedContiguousIterator<U> & other)63*6777b538SAndroid Build Coastguard Worker constexpr CheckedContiguousIterator(const CheckedContiguousIterator<U>& other) 64*6777b538SAndroid Build Coastguard Worker requires(std::convertible_to<U (*)[], T (*)[]>) 65*6777b538SAndroid Build Coastguard Worker : start_(other.start_), current_(other.current_), end_(other.end_) { 66*6777b538SAndroid Build Coastguard Worker // We explicitly don't delegate to the 3-argument constructor here. Its 67*6777b538SAndroid Build Coastguard Worker // CHECKs would be redundant, since we expect |other| to maintain its own 68*6777b538SAndroid Build Coastguard Worker // invariant. However, DCHECKs never hurt anybody. Presumably. 69*6777b538SAndroid Build Coastguard Worker DCHECK_LE(other.start_, other.current_); 70*6777b538SAndroid Build Coastguard Worker DCHECK_LE(other.current_, other.end_); 71*6777b538SAndroid Build Coastguard Worker } 72*6777b538SAndroid Build Coastguard Worker 73*6777b538SAndroid Build Coastguard Worker ~CheckedContiguousIterator() = default; 74*6777b538SAndroid Build Coastguard Worker 75*6777b538SAndroid Build Coastguard Worker constexpr CheckedContiguousIterator& operator=( 76*6777b538SAndroid Build Coastguard Worker const CheckedContiguousIterator& other) = default; 77*6777b538SAndroid Build Coastguard Worker 78*6777b538SAndroid Build Coastguard Worker friend constexpr bool operator==(const CheckedContiguousIterator& lhs, 79*6777b538SAndroid Build Coastguard Worker const CheckedContiguousIterator& rhs) { 80*6777b538SAndroid Build Coastguard Worker lhs.CheckComparable(rhs); 81*6777b538SAndroid Build Coastguard Worker return lhs.current_ == rhs.current_; 82*6777b538SAndroid Build Coastguard Worker } 83*6777b538SAndroid Build Coastguard Worker 84*6777b538SAndroid Build Coastguard Worker friend constexpr auto operator<=>(const CheckedContiguousIterator& lhs, 85*6777b538SAndroid Build Coastguard Worker const CheckedContiguousIterator& rhs) { 86*6777b538SAndroid Build Coastguard Worker lhs.CheckComparable(rhs); 87*6777b538SAndroid Build Coastguard Worker return lhs.current_ <=> rhs.current_; 88*6777b538SAndroid Build Coastguard Worker } 89*6777b538SAndroid Build Coastguard Worker 90*6777b538SAndroid Build Coastguard Worker constexpr CheckedContiguousIterator& operator++() { 91*6777b538SAndroid Build Coastguard Worker CHECK_NE(current_, end_); 92*6777b538SAndroid Build Coastguard Worker ++current_; 93*6777b538SAndroid Build Coastguard Worker return *this; 94*6777b538SAndroid Build Coastguard Worker } 95*6777b538SAndroid Build Coastguard Worker 96*6777b538SAndroid Build Coastguard Worker constexpr CheckedContiguousIterator operator++(int) { 97*6777b538SAndroid Build Coastguard Worker CheckedContiguousIterator old = *this; 98*6777b538SAndroid Build Coastguard Worker ++*this; 99*6777b538SAndroid Build Coastguard Worker return old; 100*6777b538SAndroid Build Coastguard Worker } 101*6777b538SAndroid Build Coastguard Worker 102*6777b538SAndroid Build Coastguard Worker constexpr CheckedContiguousIterator& operator--() { 103*6777b538SAndroid Build Coastguard Worker CHECK_NE(current_, start_); 104*6777b538SAndroid Build Coastguard Worker --current_; 105*6777b538SAndroid Build Coastguard Worker return *this; 106*6777b538SAndroid Build Coastguard Worker } 107*6777b538SAndroid Build Coastguard Worker 108*6777b538SAndroid Build Coastguard Worker constexpr CheckedContiguousIterator operator--(int) { 109*6777b538SAndroid Build Coastguard Worker CheckedContiguousIterator old = *this; 110*6777b538SAndroid Build Coastguard Worker --*this; 111*6777b538SAndroid Build Coastguard Worker return old; 112*6777b538SAndroid Build Coastguard Worker } 113*6777b538SAndroid Build Coastguard Worker 114*6777b538SAndroid Build Coastguard Worker constexpr CheckedContiguousIterator& operator+=(difference_type rhs) { 115*6777b538SAndroid Build Coastguard Worker if (rhs > 0) { 116*6777b538SAndroid Build Coastguard Worker CHECK_LE(rhs, end_ - current_); 117*6777b538SAndroid Build Coastguard Worker } else { 118*6777b538SAndroid Build Coastguard Worker CHECK_LE(-rhs, current_ - start_); 119*6777b538SAndroid Build Coastguard Worker } 120*6777b538SAndroid Build Coastguard Worker current_ += rhs; 121*6777b538SAndroid Build Coastguard Worker return *this; 122*6777b538SAndroid Build Coastguard Worker } 123*6777b538SAndroid Build Coastguard Worker 124*6777b538SAndroid Build Coastguard Worker constexpr CheckedContiguousIterator operator+(difference_type rhs) const { 125*6777b538SAndroid Build Coastguard Worker CheckedContiguousIterator it = *this; 126*6777b538SAndroid Build Coastguard Worker it += rhs; 127*6777b538SAndroid Build Coastguard Worker return it; 128*6777b538SAndroid Build Coastguard Worker } 129*6777b538SAndroid Build Coastguard Worker 130*6777b538SAndroid Build Coastguard Worker constexpr friend CheckedContiguousIterator operator+( 131*6777b538SAndroid Build Coastguard Worker difference_type lhs, 132*6777b538SAndroid Build Coastguard Worker const CheckedContiguousIterator& rhs) { 133*6777b538SAndroid Build Coastguard Worker return rhs + lhs; 134*6777b538SAndroid Build Coastguard Worker } 135*6777b538SAndroid Build Coastguard Worker 136*6777b538SAndroid Build Coastguard Worker constexpr CheckedContiguousIterator& operator-=(difference_type rhs) { 137*6777b538SAndroid Build Coastguard Worker if (rhs < 0) { 138*6777b538SAndroid Build Coastguard Worker CHECK_LE(-rhs, end_ - current_); 139*6777b538SAndroid Build Coastguard Worker } else { 140*6777b538SAndroid Build Coastguard Worker CHECK_LE(rhs, current_ - start_); 141*6777b538SAndroid Build Coastguard Worker } 142*6777b538SAndroid Build Coastguard Worker current_ -= rhs; 143*6777b538SAndroid Build Coastguard Worker return *this; 144*6777b538SAndroid Build Coastguard Worker } 145*6777b538SAndroid Build Coastguard Worker 146*6777b538SAndroid Build Coastguard Worker constexpr CheckedContiguousIterator operator-(difference_type rhs) const { 147*6777b538SAndroid Build Coastguard Worker CheckedContiguousIterator it = *this; 148*6777b538SAndroid Build Coastguard Worker it -= rhs; 149*6777b538SAndroid Build Coastguard Worker return it; 150*6777b538SAndroid Build Coastguard Worker } 151*6777b538SAndroid Build Coastguard Worker 152*6777b538SAndroid Build Coastguard Worker constexpr friend difference_type operator-( 153*6777b538SAndroid Build Coastguard Worker const CheckedContiguousIterator& lhs, 154*6777b538SAndroid Build Coastguard Worker const CheckedContiguousIterator& rhs) { 155*6777b538SAndroid Build Coastguard Worker lhs.CheckComparable(rhs); 156*6777b538SAndroid Build Coastguard Worker return lhs.current_ - rhs.current_; 157*6777b538SAndroid Build Coastguard Worker } 158*6777b538SAndroid Build Coastguard Worker 159*6777b538SAndroid Build Coastguard Worker constexpr reference operator*() const { 160*6777b538SAndroid Build Coastguard Worker CHECK_NE(current_, end_); 161*6777b538SAndroid Build Coastguard Worker return *current_; 162*6777b538SAndroid Build Coastguard Worker } 163*6777b538SAndroid Build Coastguard Worker 164*6777b538SAndroid Build Coastguard Worker constexpr pointer operator->() const { 165*6777b538SAndroid Build Coastguard Worker CHECK_NE(current_, end_); 166*6777b538SAndroid Build Coastguard Worker return current_; 167*6777b538SAndroid Build Coastguard Worker } 168*6777b538SAndroid Build Coastguard Worker 169*6777b538SAndroid Build Coastguard Worker constexpr reference operator[](difference_type rhs) const { 170*6777b538SAndroid Build Coastguard Worker CHECK_GE(rhs, 0); 171*6777b538SAndroid Build Coastguard Worker CHECK_LT(rhs, end_ - current_); 172*6777b538SAndroid Build Coastguard Worker return current_[rhs]; 173*6777b538SAndroid Build Coastguard Worker } 174*6777b538SAndroid Build Coastguard Worker IsRangeMoveSafe(const CheckedContiguousIterator & from_begin,const CheckedContiguousIterator & from_end,const CheckedContiguousIterator & to)175*6777b538SAndroid Build Coastguard Worker [[nodiscard]] static bool IsRangeMoveSafe( 176*6777b538SAndroid Build Coastguard Worker const CheckedContiguousIterator& from_begin, 177*6777b538SAndroid Build Coastguard Worker const CheckedContiguousIterator& from_end, 178*6777b538SAndroid Build Coastguard Worker const CheckedContiguousIterator& to) { 179*6777b538SAndroid Build Coastguard Worker if (from_end < from_begin) 180*6777b538SAndroid Build Coastguard Worker return false; 181*6777b538SAndroid Build Coastguard Worker const auto from_begin_uintptr = get_uintptr(from_begin.current_); 182*6777b538SAndroid Build Coastguard Worker const auto from_end_uintptr = get_uintptr(from_end.current_); 183*6777b538SAndroid Build Coastguard Worker const auto to_begin_uintptr = get_uintptr(to.current_); 184*6777b538SAndroid Build Coastguard Worker const auto to_end_uintptr = 185*6777b538SAndroid Build Coastguard Worker get_uintptr((to + std::distance(from_begin, from_end)).current_); 186*6777b538SAndroid Build Coastguard Worker 187*6777b538SAndroid Build Coastguard Worker return to_begin_uintptr >= from_end_uintptr || 188*6777b538SAndroid Build Coastguard Worker to_end_uintptr <= from_begin_uintptr; 189*6777b538SAndroid Build Coastguard Worker } 190*6777b538SAndroid Build Coastguard Worker 191*6777b538SAndroid Build Coastguard Worker private: CheckComparable(const CheckedContiguousIterator & other)192*6777b538SAndroid Build Coastguard Worker constexpr void CheckComparable(const CheckedContiguousIterator& other) const { 193*6777b538SAndroid Build Coastguard Worker CHECK_EQ(start_, other.start_); 194*6777b538SAndroid Build Coastguard Worker CHECK_EQ(end_, other.end_); 195*6777b538SAndroid Build Coastguard Worker } 196*6777b538SAndroid Build Coastguard Worker 197*6777b538SAndroid Build Coastguard Worker // RAW_PTR_EXCLUSION: The embedding class is stack-scoped. 198*6777b538SAndroid Build Coastguard Worker RAW_PTR_EXCLUSION const T* start_ = nullptr; 199*6777b538SAndroid Build Coastguard Worker RAW_PTR_EXCLUSION T* current_ = nullptr; 200*6777b538SAndroid Build Coastguard Worker RAW_PTR_EXCLUSION const T* end_ = nullptr; 201*6777b538SAndroid Build Coastguard Worker }; 202*6777b538SAndroid Build Coastguard Worker 203*6777b538SAndroid Build Coastguard Worker template <typename T> 204*6777b538SAndroid Build Coastguard Worker using CheckedContiguousConstIterator = CheckedContiguousIterator<const T>; 205*6777b538SAndroid Build Coastguard Worker 206*6777b538SAndroid Build Coastguard Worker } // namespace base 207*6777b538SAndroid Build Coastguard Worker 208*6777b538SAndroid Build Coastguard Worker // Specialize std::pointer_traits so that we can obtain the underlying raw 209*6777b538SAndroid Build Coastguard Worker // pointer without resulting in CHECK failures. The important bit is the 210*6777b538SAndroid Build Coastguard Worker // `to_address(pointer)` overload, which is the standard blessed way to 211*6777b538SAndroid Build Coastguard Worker // customize `std::to_address(pointer)` in C++20 [1]. 212*6777b538SAndroid Build Coastguard Worker // 213*6777b538SAndroid Build Coastguard Worker // [1] https://wg21.link/pointer.traits.optmem 214*6777b538SAndroid Build Coastguard Worker 215*6777b538SAndroid Build Coastguard Worker template <typename T> 216*6777b538SAndroid Build Coastguard Worker struct std::pointer_traits<::base::CheckedContiguousIterator<T>> { 217*6777b538SAndroid Build Coastguard Worker using pointer = ::base::CheckedContiguousIterator<T>; 218*6777b538SAndroid Build Coastguard Worker using element_type = T; 219*6777b538SAndroid Build Coastguard Worker using difference_type = ptrdiff_t; 220*6777b538SAndroid Build Coastguard Worker 221*6777b538SAndroid Build Coastguard Worker template <typename U> 222*6777b538SAndroid Build Coastguard Worker using rebind = ::base::CheckedContiguousIterator<U>; 223*6777b538SAndroid Build Coastguard Worker 224*6777b538SAndroid Build Coastguard Worker static constexpr pointer pointer_to(element_type& r) noexcept { 225*6777b538SAndroid Build Coastguard Worker return pointer(&r, &r); 226*6777b538SAndroid Build Coastguard Worker } 227*6777b538SAndroid Build Coastguard Worker 228*6777b538SAndroid Build Coastguard Worker static constexpr element_type* to_address(pointer p) noexcept { 229*6777b538SAndroid Build Coastguard Worker return p.current_; 230*6777b538SAndroid Build Coastguard Worker } 231*6777b538SAndroid Build Coastguard Worker }; 232*6777b538SAndroid Build Coastguard Worker 233*6777b538SAndroid Build Coastguard Worker #endif // BASE_CONTAINERS_CHECKED_ITERATORS_H_ 234