|  | // Copyright 2018 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef BASE_CONTAINERS_CHECKED_ITERATORS_H_ | 
|  | #define BASE_CONTAINERS_CHECKED_ITERATORS_H_ | 
|  |  | 
|  | #include <iterator> | 
|  | #include <memory> | 
|  |  | 
|  | #include "base/logging.h" | 
|  |  | 
|  | namespace base { | 
|  |  | 
|  | template <typename T> | 
|  | class CheckedRandomAccessConstIterator; | 
|  |  | 
|  | template <typename T> | 
|  | class CheckedRandomAccessIterator { | 
|  | public: | 
|  | using difference_type = std::ptrdiff_t; | 
|  | using value_type = typename std::iterator_traits<T*>::value_type; | 
|  | using pointer = T*; | 
|  | using reference = T&; | 
|  | using iterator_category = std::random_access_iterator_tag; | 
|  |  | 
|  | friend class CheckedRandomAccessConstIterator<T>; | 
|  |  | 
|  | CheckedRandomAccessIterator() = default; | 
|  | CheckedRandomAccessIterator(T* start, const T* end) | 
|  | : CheckedRandomAccessIterator(start, start, end) {} | 
|  | CheckedRandomAccessIterator(T* start, T* current, const T* end) | 
|  | : start_(start), current_(current), end_(end) { | 
|  | CHECK(start <= current); | 
|  | CHECK(current <= end); | 
|  | } | 
|  | CheckedRandomAccessIterator(const CheckedRandomAccessIterator& other) = | 
|  | default; | 
|  | ~CheckedRandomAccessIterator() = default; | 
|  |  | 
|  | CheckedRandomAccessIterator& operator=( | 
|  | const CheckedRandomAccessIterator& other) = default; | 
|  |  | 
|  | bool operator==(const CheckedRandomAccessIterator& other) const { | 
|  | CHECK_EQ(start_, other.start_); | 
|  | CHECK_EQ(end_, other.end_); | 
|  | return current_ == other.current_; | 
|  | } | 
|  |  | 
|  | bool operator!=(const CheckedRandomAccessIterator& other) const { | 
|  | CHECK_EQ(start_, other.start_); | 
|  | CHECK_EQ(end_, other.end_); | 
|  | return current_ != other.current_; | 
|  | } | 
|  |  | 
|  | bool operator<(const CheckedRandomAccessIterator& other) const { | 
|  | CHECK_EQ(start_, other.start_); | 
|  | CHECK_EQ(end_, other.end_); | 
|  | 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_; | 
|  | } | 
|  |  | 
|  | private: | 
|  | 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) | 
|  | : 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_); | 
|  | } | 
|  | ~CheckedRandomAccessConstIterator() = default; | 
|  |  | 
|  | // MSVC doesn't like these unnecessary default declarations somehow. | 
|  | #if !SB_IS(COMPILER_MSVC) | 
|  | CheckedRandomAccessConstIterator& operator=( | 
|  | const CheckedRandomAccessConstIterator& other) = default; | 
|  |  | 
|  | CheckedRandomAccessConstIterator& operator=( | 
|  | CheckedRandomAccessConstIterator& other) = default; | 
|  | #endif | 
|  |  | 
|  | bool operator==(const CheckedRandomAccessConstIterator& other) const { | 
|  | CHECK_EQ(start_, other.start_); | 
|  | CHECK_EQ(end_, other.end_); | 
|  | return current_ == other.current_; | 
|  | } | 
|  |  | 
|  | bool operator!=(const CheckedRandomAccessConstIterator& other) const { | 
|  | CHECK_EQ(start_, other.start_); | 
|  | CHECK_EQ(end_, other.end_); | 
|  | return current_ != other.current_; | 
|  | } | 
|  |  | 
|  | bool operator<(const CheckedRandomAccessConstIterator& other) const { | 
|  | CHECK_EQ(start_, other.start_); | 
|  | CHECK_EQ(end_, other.end_); | 
|  | return current_ < other.current_; | 
|  | } | 
|  |  | 
|  | CheckedRandomAccessConstIterator& operator++() { | 
|  | CHECK(current_ != end_); | 
|  | ++current_; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | CheckedRandomAccessConstIterator operator++(int) { | 
|  | CheckedRandomAccessConstIterator old = *this; | 
|  | ++*this; | 
|  | return old; | 
|  | } | 
|  |  | 
|  | CheckedRandomAccessConstIterator& operator--() { | 
|  | CHECK(current_ != start_); | 
|  | --current_; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | CheckedRandomAccessConstIterator& operator--(int) { | 
|  | CheckedRandomAccessConstIterator old = *this; | 
|  | --*this; | 
|  | return old; | 
|  | } | 
|  |  | 
|  | CheckedRandomAccessConstIterator& operator+=(difference_type rhs) { | 
|  | if (rhs > 0) { | 
|  | CHECK_LE(rhs, end_ - current_); | 
|  | } else { | 
|  | CHECK_LE(-rhs, current_ - start_); | 
|  | } | 
|  | current_ += rhs; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | CheckedRandomAccessConstIterator operator+(difference_type rhs) const { | 
|  | CheckedRandomAccessConstIterator it = *this; | 
|  | it += rhs; | 
|  | return it; | 
|  | } | 
|  |  | 
|  | CheckedRandomAccessConstIterator& operator-=(difference_type rhs) { | 
|  | if (rhs < 0) { | 
|  | CHECK_LE(rhs, end_ - current_); | 
|  | } else { | 
|  | CHECK_LE(-rhs, current_ - start_); | 
|  | } | 
|  | current_ -= rhs; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | CheckedRandomAccessConstIterator operator-(difference_type rhs) const { | 
|  | CheckedRandomAccessConstIterator 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_); | 
|  | return lhs.current_ - rhs.current_; | 
|  | } | 
|  |  | 
|  | reference operator*() const { | 
|  | CHECK(current_ != end_); | 
|  | return *current_; | 
|  | } | 
|  |  | 
|  | pointer operator->() const { | 
|  | CHECK(current_ != end_); | 
|  | return current_; | 
|  | } | 
|  |  | 
|  | private: | 
|  | const T* start_ = nullptr; | 
|  | const T* current_ = nullptr; | 
|  | const T* end_ = nullptr; | 
|  | }; | 
|  |  | 
|  | }  // namespace base | 
|  |  | 
|  | #endif  // BASE_CONTAINERS_CHECKED_ITERATORS_H_ |