1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 // Common iterator implementation for array classes e.g. nsTArray.
9 #ifndef mozilla_ArrayIterator_h
10 #define mozilla_ArrayIterator_h
14 #include "mozilla/TypeTraits.h"
23 struct AddInnerConst
<T
&> {
24 using Type
= const T
&;
28 struct AddInnerConst
<T
*> {
29 using Type
= const T
*;
33 using AddInnerConstT
= typename AddInnerConst
<T
>::Type
;
36 // We have implemented a custom iterator class for array rather than using
37 // raw pointers into the backing storage to improve the safety of C++11-style
38 // range based iteration in the presence of array mutation, or script execution
41 // Mutating an array which is being iterated is still wrong, and will either
42 // cause elements to be missed or firefox to crash, but will not trigger memory
43 // safety problems due to the release-mode bounds checking found in ElementAt.
45 // Dereferencing this iterator returns type Element. When Element is a reference
46 // type, this iterator implements the full standard random access iterator spec,
47 // and can be treated in many ways as though it is a pointer. Otherwise, it is
48 // just enough to be used in range-based for loop.
49 template <class Element
, class ArrayType
>
52 typedef ArrayType array_type
;
53 typedef ArrayIterator
<Element
, ArrayType
> iterator_type
;
54 typedef typename
array_type::index_type index_type
;
55 typedef typename RemoveReference
<Element
>::Type value_type
;
56 typedef ptrdiff_t difference_type
;
57 typedef value_type
* pointer
;
58 typedef value_type
& reference
;
59 typedef std::random_access_iterator_tag iterator_category
;
60 typedef ArrayIterator
<detail::AddInnerConstT
<Element
>, ArrayType
>
64 const array_type
* mArray
;
68 ArrayIterator() : mArray(nullptr), mIndex(0) {}
69 ArrayIterator(const iterator_type
& aOther
)
70 : mArray(aOther
.mArray
), mIndex(aOther
.mIndex
) {}
71 ArrayIterator(const array_type
& aArray
, index_type aIndex
)
72 : mArray(&aArray
), mIndex(aIndex
) {}
74 iterator_type
& operator=(const iterator_type
& aOther
) {
75 mArray
= aOther
.mArray
;
76 mIndex
= aOther
.mIndex
;
80 constexpr operator const_iterator_type() const {
81 return mArray
? const_iterator_type
{*mArray
, mIndex
}
82 : const_iterator_type
{};
85 bool operator==(const iterator_type
& aRhs
) const {
86 return mIndex
== aRhs
.mIndex
;
88 bool operator!=(const iterator_type
& aRhs
) const { return !(*this == aRhs
); }
89 bool operator<(const iterator_type
& aRhs
) const {
90 return mIndex
< aRhs
.mIndex
;
92 bool operator>(const iterator_type
& aRhs
) const {
93 return mIndex
> aRhs
.mIndex
;
95 bool operator<=(const iterator_type
& aRhs
) const {
96 return mIndex
<= aRhs
.mIndex
;
98 bool operator>=(const iterator_type
& aRhs
) const {
99 return mIndex
>= aRhs
.mIndex
;
102 // These operators depend on the release mode bounds checks in
103 // ArrayIterator::ElementAt for safety.
104 value_type
* operator->() const {
105 return const_cast<value_type
*>(&mArray
->ElementAt(mIndex
));
107 Element
operator*() const {
108 return const_cast<Element
>(mArray
->ElementAt(mIndex
));
111 iterator_type
& operator++() {
115 iterator_type
operator++(int) {
116 iterator_type it
= *this;
120 iterator_type
& operator--() {
124 iterator_type
operator--(int) {
125 iterator_type it
= *this;
130 iterator_type
& operator+=(difference_type aDiff
) {
134 iterator_type
& operator-=(difference_type aDiff
) {
139 iterator_type
operator+(difference_type aDiff
) const {
140 iterator_type it
= *this;
144 iterator_type
operator-(difference_type aDiff
) const {
145 iterator_type it
= *this;
150 difference_type
operator-(const iterator_type
& aOther
) const {
151 return static_cast<difference_type
>(mIndex
) -
152 static_cast<difference_type
>(aOther
.mIndex
);
155 Element
operator[](difference_type aIndex
) const {
156 return *this->operator+(aIndex
);
159 constexpr const array_type
* GetArray() const { return mArray
; }
161 constexpr index_type
GetIndex() const { return mIndex
; }
164 } // namespace mozilla
166 #endif // mozilla_ArrayIterator_h