Line data Source code
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/. */
6 :
7 : // Common iterator implementation for array classes e.g. nsTArray.
8 :
9 : #ifndef mozilla_ArrayIterator_h
10 : #define mozilla_ArrayIterator_h
11 :
12 : #include <iterator>
13 :
14 : #include "mozilla/TypeTraits.h"
15 :
16 : namespace mozilla {
17 :
18 : // We have implemented a custom iterator class for array rather than using
19 : // raw pointers into the backing storage to improve the safety of C++11-style
20 : // range based iteration in the presence of array mutation, or script execution
21 : // (bug 1299489).
22 : //
23 : // Mutating an array which is being iterated is still wrong, and will either
24 : // cause elements to be missed or firefox to crash, but will not trigger memory
25 : // safety problems due to the release-mode bounds checking found in ElementAt.
26 : //
27 : // Dereferencing this iterator returns type Element. When Element is a reference
28 : // type, this iterator implements the full standard random access iterator spec,
29 : // and can be treated in many ways as though it is a pointer. Otherwise, it is
30 : // just enough to be used in range-based for loop.
31 : template<class Element, class ArrayType>
32 : class ArrayIterator
33 : {
34 : public:
35 : typedef ArrayType array_type;
36 : typedef ArrayIterator<Element, ArrayType> iterator_type;
37 : typedef typename array_type::index_type index_type;
38 : typedef typename RemoveReference<Element>::Type value_type;
39 : typedef ptrdiff_t difference_type;
40 : typedef value_type* pointer;
41 : typedef value_type& reference;
42 : typedef std::random_access_iterator_tag iterator_category;
43 :
44 : private:
45 : const array_type* mArray;
46 : index_type mIndex;
47 :
48 : public:
49 : ArrayIterator() : mArray(nullptr), mIndex(0) {}
50 51626 : ArrayIterator(const iterator_type& aOther)
51 51626 : : mArray(aOther.mArray), mIndex(aOther.mIndex) {}
52 74902 : ArrayIterator(const array_type& aArray, index_type aIndex)
53 74902 : : mArray(&aArray), mIndex(aIndex) {}
54 :
55 47 : iterator_type& operator=(const iterator_type& aOther) {
56 47 : mArray = aOther.mArray;
57 47 : mIndex = aOther.mIndex;
58 47 : return *this;
59 : }
60 :
61 67290 : bool operator==(const iterator_type& aRhs) const {
62 67290 : return mIndex == aRhs.mIndex;
63 : }
64 65139 : bool operator!=(const iterator_type& aRhs) const {
65 65139 : return !(*this == aRhs);
66 : }
67 37 : bool operator<(const iterator_type& aRhs) const {
68 37 : return mIndex < aRhs.mIndex;
69 : }
70 : bool operator>(const iterator_type& aRhs) const {
71 : return mIndex > aRhs.mIndex;
72 : }
73 : bool operator<=(const iterator_type& aRhs) const {
74 : return mIndex <= aRhs.mIndex;
75 : }
76 3 : bool operator>=(const iterator_type& aRhs) const {
77 3 : return mIndex >= aRhs.mIndex;
78 : }
79 :
80 : // These operators depend on the release mode bounds checks in
81 : // ArrayIterator::ElementAt for safety.
82 933 : value_type* operator->() const {
83 933 : return const_cast<value_type*>(&mArray->ElementAt(mIndex));
84 : }
85 40407 : Element operator*() const {
86 40407 : return const_cast<Element>(mArray->ElementAt(mIndex));
87 : }
88 :
89 29680 : iterator_type& operator++() {
90 29680 : ++mIndex;
91 29680 : return *this;
92 : }
93 1853 : iterator_type operator++(int) {
94 1853 : iterator_type it = *this;
95 1853 : ++*this;
96 1853 : return it;
97 : }
98 4230 : iterator_type& operator--() {
99 4230 : --mIndex;
100 4230 : return *this;
101 : }
102 0 : iterator_type operator--(int) {
103 0 : iterator_type it = *this;
104 0 : --*this;
105 0 : return it;
106 : }
107 :
108 7127 : iterator_type& operator+=(difference_type aDiff) {
109 7127 : mIndex += aDiff;
110 7127 : return *this;
111 : }
112 308 : iterator_type& operator-=(difference_type aDiff) {
113 308 : mIndex -= aDiff;
114 308 : return *this;
115 : }
116 :
117 7127 : iterator_type operator+(difference_type aDiff) const {
118 7127 : iterator_type it = *this;
119 7127 : it += aDiff;
120 7127 : return it;
121 : }
122 308 : iterator_type operator-(difference_type aDiff) const {
123 308 : iterator_type it = *this;
124 308 : it -= aDiff;
125 308 : return it;
126 : }
127 :
128 4557 : difference_type operator-(const iterator_type& aOther) const {
129 4557 : return static_cast<difference_type>(mIndex) -
130 4557 : static_cast<difference_type>(aOther.mIndex);
131 : }
132 :
133 : Element operator[](difference_type aIndex) const {
134 : return *this->operator+(aIndex);
135 : }
136 : };
137 :
138 : } // namespace mozilla
139 :
140 : #endif // mozilla_ArrayIterator_h
|