diff options
Diffstat (limited to 'chromium/base/containers/checked_iterators.h')
-rw-r--r-- | chromium/base/containers/checked_iterators.h | 276 |
1 files changed, 79 insertions, 197 deletions
diff --git a/chromium/base/containers/checked_iterators.h b/chromium/base/containers/checked_iterators.h index b7eb7b4c7a9..bf3d6949371 100644 --- a/chromium/base/containers/checked_iterators.h +++ b/chromium/base/containers/checked_iterators.h @@ -7,6 +7,7 @@ #include <iterator> #include <memory> +#include <type_traits> #include "base/containers/util.h" #include "base/logging.h" @@ -14,234 +15,106 @@ namespace base { template <typename T> -class CheckedRandomAccessConstIterator; - -template <typename T> -class CheckedRandomAccessIterator { +class CheckedContiguousIterator { public: using difference_type = std::ptrdiff_t; - using value_type = typename std::iterator_traits<T*>::value_type; + using value_type = std::remove_cv_t<T>; using pointer = T*; using reference = T&; using iterator_category = std::random_access_iterator_tag; - friend class CheckedRandomAccessConstIterator<T>; + // Required for converting constructor below. + template <typename U> + friend class CheckedContiguousIterator; - CheckedRandomAccessIterator() = default; - CheckedRandomAccessIterator(T* start, const T* end) - : CheckedRandomAccessIterator(start, start, end) {} - CheckedRandomAccessIterator(T* start, T* current, const T* end) + constexpr CheckedContiguousIterator() = default; + constexpr CheckedContiguousIterator(T* start, const T* end) + : CheckedContiguousIterator(start, start, end) {} + constexpr CheckedContiguousIterator(const T* start, T* current, const T* end) : start_(start), current_(current), end_(end) { - CHECK(start <= current); - CHECK(current <= end); + CHECK_LE(start, current); + CHECK_LE(current, end); } - CheckedRandomAccessIterator(const CheckedRandomAccessIterator& other) = + constexpr CheckedContiguousIterator(const CheckedContiguousIterator& other) = default; - ~CheckedRandomAccessIterator() = default; - - CheckedRandomAccessIterator& operator=( - const CheckedRandomAccessIterator& other) = default; - - bool operator==(const CheckedRandomAccessIterator& other) const { - CheckComparable(other); - return current_ == other.current_; - } - - bool operator!=(const CheckedRandomAccessIterator& other) const { - CheckComparable(other); - return current_ != other.current_; - } - - bool operator<(const CheckedRandomAccessIterator& other) const { - CheckComparable(other); - return current_ < other.current_; - } - - bool operator<=(const CheckedRandomAccessIterator& other) const { - CheckComparable(other); - return current_ <= other.current_; - } - - CheckedRandomAccessIterator& operator++() { - CHECK(current_ != end_); - ++current_; - return *this; - } - - CheckedRandomAccessIterator operator++(int) { - CheckedRandomAccessIterator old = *this; - ++*this; - return old; - } - - CheckedRandomAccessIterator& operator--() { - CHECK(current_ != start_); - --current_; - return *this; - } - - CheckedRandomAccessIterator& operator--(int) { - CheckedRandomAccessIterator old = *this; - --*this; - return old; - } - - CheckedRandomAccessIterator& operator+=(difference_type rhs) { - if (rhs > 0) { - CHECK_LE(rhs, end_ - current_); - } else { - CHECK_LE(-rhs, current_ - start_); - } - current_ += rhs; - return *this; - } - - CheckedRandomAccessIterator operator+(difference_type rhs) const { - CheckedRandomAccessIterator it = *this; - it += rhs; - return it; - } - - CheckedRandomAccessIterator& operator-=(difference_type rhs) { - if (rhs < 0) { - CHECK_LE(rhs, end_ - current_); - } else { - CHECK_LE(-rhs, current_ - start_); - } - current_ -= rhs; - return *this; - } - - CheckedRandomAccessIterator operator-(difference_type rhs) const { - CheckedRandomAccessIterator it = *this; - it -= rhs; - return it; - } - - friend difference_type operator-(const CheckedRandomAccessIterator& lhs, - const CheckedRandomAccessIterator& rhs) { - CHECK(lhs.start_ == rhs.start_); - CHECK(lhs.end_ == rhs.end_); - return lhs.current_ - rhs.current_; - } - - reference operator*() const { - CHECK(current_ != end_); - return *current_; - } - - pointer operator->() const { - CHECK(current_ != end_); - return current_; - } - - static bool IsRangeMoveSafe(const CheckedRandomAccessIterator& from_begin, - const CheckedRandomAccessIterator& from_end, - const CheckedRandomAccessIterator& to) - WARN_UNUSED_RESULT { - if (from_end < from_begin) - return false; - const auto from_begin_uintptr = get_uintptr(from_begin.current_); - const auto from_end_uintptr = get_uintptr(from_end.current_); - const auto to_begin_uintptr = get_uintptr(to.current_); - const auto to_end_uintptr = - get_uintptr((to + std::distance(from_begin, from_end)).current_); - - return to_begin_uintptr >= from_end_uintptr || - to_end_uintptr <= from_begin_uintptr; - } - - private: - void CheckComparable(const CheckedRandomAccessIterator& other) const { - CHECK_EQ(start_, other.start_); - CHECK_EQ(end_, other.end_); - } - - const T* start_ = nullptr; - T* current_ = nullptr; - const T* end_ = nullptr; -}; - -template <typename T> -class CheckedRandomAccessConstIterator { - public: - using difference_type = std::ptrdiff_t; - using value_type = typename std::iterator_traits<T*>::value_type; - using pointer = const T*; - using reference = const T&; - using iterator_category = std::random_access_iterator_tag; - CheckedRandomAccessConstIterator() = default; - CheckedRandomAccessConstIterator(T* start, const T* end) - : CheckedRandomAccessConstIterator(start, start, end) {} - CheckedRandomAccessConstIterator(T* start, T* current, const T* end) - : start_(start), current_(current), end_(end) { - CHECK(start <= current); - CHECK(current <= end); - } - CheckedRandomAccessConstIterator( - const CheckedRandomAccessConstIterator& other) = default; - CheckedRandomAccessConstIterator(const CheckedRandomAccessIterator<T>& other) + // Converting constructor allowing conversions like CRAI<T> to CRAI<const T>, + // but disallowing CRAI<const T> to CRAI<T> or CRAI<Derived> to CRAI<Base>, + // which are unsafe. Furthermore, this is the same condition as used by the + // converting constructors of std::span<T> and std::unique_ptr<T[]>. + // See https://wg21.link/n4042 for details. + template < + typename U, + std::enable_if_t<std::is_convertible<U (*)[], T (*)[]>::value>* = nullptr> + constexpr CheckedContiguousIterator(const CheckedContiguousIterator<U>& other) : start_(other.start_), current_(other.current_), end_(other.end_) { // We explicitly don't delegate to the 3-argument constructor here. Its // CHECKs would be redundant, since we expect |other| to maintain its own // invariant. However, DCHECKs never hurt anybody. Presumably. - DCHECK(other.start_ <= other.current_); - DCHECK(other.current_ <= other.end_); + DCHECK_LE(other.start_, other.current_); + DCHECK_LE(other.current_, other.end_); } - ~CheckedRandomAccessConstIterator() = default; - CheckedRandomAccessConstIterator& operator=( - const CheckedRandomAccessConstIterator& other) = default; + ~CheckedContiguousIterator() = default; - CheckedRandomAccessConstIterator& operator=( - CheckedRandomAccessConstIterator& other) = default; + constexpr CheckedContiguousIterator& operator=( + const CheckedContiguousIterator& other) = default; - bool operator==(const CheckedRandomAccessConstIterator& other) const { + constexpr bool operator==(const CheckedContiguousIterator& other) const { CheckComparable(other); return current_ == other.current_; } - bool operator!=(const CheckedRandomAccessConstIterator& other) const { + constexpr bool operator!=(const CheckedContiguousIterator& other) const { CheckComparable(other); return current_ != other.current_; } - bool operator<(const CheckedRandomAccessConstIterator& other) const { + constexpr bool operator<(const CheckedContiguousIterator& other) const { CheckComparable(other); return current_ < other.current_; } - bool operator<=(const CheckedRandomAccessConstIterator& other) const { + constexpr bool operator<=(const CheckedContiguousIterator& other) const { CheckComparable(other); return current_ <= other.current_; } - CheckedRandomAccessConstIterator& operator++() { - CHECK(current_ != end_); + constexpr bool operator>(const CheckedContiguousIterator& other) const { + CheckComparable(other); + return current_ > other.current_; + } + + constexpr bool operator>=(const CheckedContiguousIterator& other) const { + CheckComparable(other); + return current_ >= other.current_; + } + + constexpr CheckedContiguousIterator& operator++() { + CHECK_NE(current_, end_); ++current_; return *this; } - CheckedRandomAccessConstIterator operator++(int) { - CheckedRandomAccessConstIterator old = *this; + constexpr CheckedContiguousIterator operator++(int) { + CheckedContiguousIterator old = *this; ++*this; return old; } - CheckedRandomAccessConstIterator& operator--() { - CHECK(current_ != start_); + constexpr CheckedContiguousIterator& operator--() { + CHECK_NE(current_, start_); --current_; return *this; } - CheckedRandomAccessConstIterator& operator--(int) { - CheckedRandomAccessConstIterator old = *this; + constexpr CheckedContiguousIterator& operator--(int) { + CheckedContiguousIterator old = *this; --*this; return old; } - CheckedRandomAccessConstIterator& operator+=(difference_type rhs) { + constexpr CheckedContiguousIterator& operator+=(difference_type rhs) { if (rhs > 0) { CHECK_LE(rhs, end_ - current_); } else { @@ -251,13 +124,13 @@ class CheckedRandomAccessConstIterator { return *this; } - CheckedRandomAccessConstIterator operator+(difference_type rhs) const { - CheckedRandomAccessConstIterator it = *this; + constexpr CheckedContiguousIterator operator+(difference_type rhs) const { + CheckedContiguousIterator it = *this; it += rhs; return it; } - CheckedRandomAccessConstIterator& operator-=(difference_type rhs) { + constexpr CheckedContiguousIterator& operator-=(difference_type rhs) { if (rhs < 0) { CHECK_LE(rhs, end_ - current_); } else { @@ -267,34 +140,40 @@ class CheckedRandomAccessConstIterator { return *this; } - CheckedRandomAccessConstIterator operator-(difference_type rhs) const { - CheckedRandomAccessConstIterator it = *this; + constexpr CheckedContiguousIterator operator-(difference_type rhs) const { + CheckedContiguousIterator it = *this; it -= rhs; return it; } - friend difference_type operator-( - const CheckedRandomAccessConstIterator& lhs, - const CheckedRandomAccessConstIterator& rhs) { - CHECK(lhs.start_ == rhs.start_); - CHECK(lhs.end_ == rhs.end_); + constexpr friend difference_type operator-( + const CheckedContiguousIterator& lhs, + const CheckedContiguousIterator& rhs) { + CHECK_EQ(lhs.start_, rhs.start_); + CHECK_EQ(lhs.end_, rhs.end_); return lhs.current_ - rhs.current_; } - reference operator*() const { - CHECK(current_ != end_); + constexpr reference operator*() const { + CHECK_NE(current_, end_); return *current_; } - pointer operator->() const { - CHECK(current_ != end_); + constexpr pointer operator->() const { + CHECK_NE(current_, end_); return current_; } - static bool IsRangeMoveSafe( - const CheckedRandomAccessConstIterator& from_begin, - const CheckedRandomAccessConstIterator& from_end, - const CheckedRandomAccessConstIterator& to) WARN_UNUSED_RESULT { + constexpr reference operator[](difference_type rhs) const { + CHECK_GE(rhs, 0); + CHECK_LT(rhs, end_ - current_); + return current_[rhs]; + } + + static bool IsRangeMoveSafe(const CheckedContiguousIterator& from_begin, + const CheckedContiguousIterator& from_end, + const CheckedContiguousIterator& to) + WARN_UNUSED_RESULT { if (from_end < from_begin) return false; const auto from_begin_uintptr = get_uintptr(from_begin.current_); @@ -308,16 +187,19 @@ class CheckedRandomAccessConstIterator { } private: - void CheckComparable(const CheckedRandomAccessConstIterator& other) const { + constexpr void CheckComparable(const CheckedContiguousIterator& other) const { CHECK_EQ(start_, other.start_); CHECK_EQ(end_, other.end_); } const T* start_ = nullptr; - const T* current_ = nullptr; + T* current_ = nullptr; const T* end_ = nullptr; }; +template <typename T> +using CheckedContiguousConstIterator = CheckedContiguousIterator<const T>; + } // namespace base #endif // BASE_CONTAINERS_CHECKED_ITERATORS_H_ |