Bug 1342303 part 1 - Make nsTArrayIterator an independent class. r?erahm
MozReview-Commit-ID: LbkIGEH0Irl
new file mode 100644
--- /dev/null
+++ b/xpcom/ds/ArrayIterator.h
@@ -0,0 +1,140 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Common iterator implementation for array classes e.g. nsTArray.
+
+#ifndef mozilla_ArrayIterator_h
+#define mozilla_ArrayIterator_h
+
+#include <iterator>
+
+#include "mozilla/TypeTraits.h"
+
+namespace mozilla {
+
+// We have implemented a custom iterator class for array rather than using
+// raw pointers into the backing storage to improve the safety of C++11-style
+// range based iteration in the presence of array mutation, or script execution
+// (bug 1299489).
+//
+// Mutating an array which is being iterated is still wrong, and will either
+// cause elements to be missed or firefox to crash, but will not trigger memory
+// safety problems due to the release-mode bounds checking found in ElementAt.
+//
+// Dereferencing this iterator returns type Element. When Element is a reference
+// type, this iterator implements the full standard random access iterator spec,
+// and can be treated in many ways as though it is a pointer. Otherwise, it is
+// just enough to be used in range-based for loop.
+template<class Element, class ArrayType>
+class ArrayIterator
+{
+public:
+ typedef ArrayType array_type;
+ typedef ArrayIterator<Element, ArrayType> iterator_type;
+ typedef typename array_type::index_type index_type;
+ typedef typename RemoveReference<Element>::Type value_type;
+ typedef ptrdiff_t difference_type;
+ typedef value_type* pointer;
+ typedef value_type& reference;
+ typedef std::random_access_iterator_tag iterator_category;
+
+private:
+ const array_type* mArray;
+ index_type mIndex;
+
+public:
+ ArrayIterator() : mArray(nullptr), mIndex(0) {}
+ ArrayIterator(const iterator_type& aOther)
+ : mArray(aOther.mArray), mIndex(aOther.mIndex) {}
+ ArrayIterator(const array_type& aArray, index_type aIndex)
+ : mArray(&aArray), mIndex(aIndex) {}
+
+ iterator_type& operator=(const iterator_type& aOther) {
+ mArray = aOther.mArray;
+ mIndex = aOther.mIndex;
+ return *this;
+ }
+
+ bool operator==(const iterator_type& aRhs) const {
+ return mIndex == aRhs.mIndex;
+ }
+ bool operator!=(const iterator_type& aRhs) const {
+ return !(*this == aRhs);
+ }
+ bool operator<(const iterator_type& aRhs) const {
+ return mIndex < aRhs.mIndex;
+ }
+ bool operator>(const iterator_type& aRhs) const {
+ return mIndex > aRhs.mIndex;
+ }
+ bool operator<=(const iterator_type& aRhs) const {
+ return mIndex <= aRhs.mIndex;
+ }
+ bool operator>=(const iterator_type& aRhs) const {
+ return mIndex >= aRhs.mIndex;
+ }
+
+ // These operators depend on the release mode bounds checks in
+ // ArrayIterator::ElementAt for safety.
+ value_type* operator->() const {
+ return const_cast<value_type*>(&mArray->ElementAt(mIndex));
+ }
+ Element operator*() const {
+ return const_cast<Element>(mArray->ElementAt(mIndex));
+ }
+
+ iterator_type& operator++() {
+ ++mIndex;
+ return *this;
+ }
+ iterator_type operator++(int) {
+ iterator_type it = *this;
+ ++*this;
+ return it;
+ }
+ iterator_type& operator--() {
+ --mIndex;
+ return *this;
+ }
+ iterator_type operator--(int) {
+ iterator_type it = *this;
+ --*this;
+ return it;
+ }
+
+ iterator_type& operator+=(difference_type aDiff) {
+ mIndex += aDiff;
+ return *this;
+ }
+ iterator_type& operator-=(difference_type aDiff) {
+ mIndex -= aDiff;
+ return *this;
+ }
+
+ iterator_type operator+(difference_type aDiff) const {
+ iterator_type it = *this;
+ it += aDiff;
+ return it;
+ }
+ iterator_type operator-(difference_type aDiff) const {
+ iterator_type it = *this;
+ it -= aDiff;
+ return it;
+ }
+
+ difference_type operator-(const iterator_type& aOther) const {
+ return static_cast<difference_type>(mIndex) -
+ static_cast<difference_type>(aOther.mIndex);
+ }
+
+ Element operator[](difference_type aIndex) const {
+ return *this->operator+(aIndex);
+ }
+};
+
+} // namespace mozilla
+
+#endif // mozilla_ArrayIterator_h
--- a/xpcom/ds/moz.build
+++ b/xpcom/ds/moz.build
@@ -78,16 +78,17 @@ EXPORTS += [
'nsTObserverArray.h',
'nsTPriorityQueue.h',
'nsVariant.h',
'nsWhitespaceTokenizer.h',
'PLDHashTable.h',
]
EXPORTS.mozilla += [
+ 'ArrayIterator.h',
'IncrementalTokenizer.h',
'Observer.h',
'StickyTimeDuration.h',
'Tokenizer.h',
]
UNIFIED_SOURCES += [
'IncrementalTokenizer.cpp',
--- a/xpcom/ds/nsTArray.h
+++ b/xpcom/ds/nsTArray.h
@@ -4,16 +4,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsTArray_h__
#define nsTArray_h__
#include "nsTArrayForwardDeclare.h"
#include "mozilla/Alignment.h"
+#include "mozilla/ArrayIterator.h"
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/BinarySearch.h"
#include "mozilla/fallible.h"
#include "mozilla/MathAlgorithms.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Move.h"
#include "mozilla/ReverseIterator.h"
@@ -26,17 +27,16 @@
#include "nscore.h"
#include "nsQuickSort.h"
#include "nsDebug.h"
#include "nsISupportsImpl.h"
#include "nsRegionFwd.h"
#include <functional>
#include <initializer_list>
#include <new>
-#include <iterator>
namespace JS {
template<class T>
class Heap;
} /* namespace JS */
class nsRegion;
namespace mozilla {
@@ -352,134 +352,16 @@ struct nsTArray_SafeElementAtHelper<mozi
{
if (aIndex < static_cast<const Derived*>(this)->Length()) {
return static_cast<const Derived*>(this)->ElementAt(aIndex);
}
return nullptr;
}
};
-// We have implemented a custom iterator class for nsTArray rather than using
-// raw pointers into the backing storage to improve the safety of C++11-style
-// range based iteration in the presence of array mutation, or script execution
-// (bug 1299489).
-//
-// Mutating an array which is being iterated is still wrong, and will either
-// cause elements to be missed or firefox to crash, but will not trigger memory
-// safety problems due to the release-mode bounds checking found in ElementAt.
-//
-// This iterator implements the full standard random access iterator spec, and
-// can be treated in may ways as though it is a pointer.
-template<class Element>
-class nsTArrayIterator
-{
-public:
- typedef nsTArray<typename mozilla::RemoveConst<Element>::Type> array_type;
- typedef nsTArrayIterator<Element> iterator_type;
- typedef typename array_type::index_type index_type;
- typedef Element value_type;
- typedef ptrdiff_t difference_type;
- typedef value_type* pointer;
- typedef value_type& reference;
- typedef std::random_access_iterator_tag iterator_category;
-
-private:
- const array_type* mArray;
- index_type mIndex;
-
-public:
- nsTArrayIterator() : mArray(nullptr), mIndex(0) {}
- nsTArrayIterator(const iterator_type& aOther)
- : mArray(aOther.mArray), mIndex(aOther.mIndex) {}
- nsTArrayIterator(const array_type& aArray, index_type aIndex)
- : mArray(&aArray), mIndex(aIndex) {}
-
- iterator_type& operator=(const iterator_type& aOther) {
- mArray = aOther.mArray;
- mIndex = aOther.mIndex;
- return *this;
- }
-
- bool operator==(const iterator_type& aRhs) const {
- return mIndex == aRhs.mIndex;
- }
- bool operator!=(const iterator_type& aRhs) const {
- return !(*this == aRhs);
- }
- bool operator<(const iterator_type& aRhs) const {
- return mIndex < aRhs.mIndex;
- }
- bool operator>(const iterator_type& aRhs) const {
- return mIndex > aRhs.mIndex;
- }
- bool operator<=(const iterator_type& aRhs) const {
- return mIndex <= aRhs.mIndex;
- }
- bool operator>=(const iterator_type& aRhs) const {
- return mIndex >= aRhs.mIndex;
- }
-
- // These operators depend on the release mode bounds checks in
- // nsTArray::ElementAt for safety.
- value_type* operator->() const {
- return const_cast<value_type*>(&(*mArray)[mIndex]);
- }
- value_type& operator*() const {
- return const_cast<value_type&>((*mArray)[mIndex]);
- }
-
- iterator_type& operator++() {
- ++mIndex;
- return *this;
- }
- iterator_type operator++(int) {
- iterator_type it = *this;
- ++*this;
- return it;
- }
- iterator_type& operator--() {
- --mIndex;
- return *this;
- }
- iterator_type operator--(int) {
- iterator_type it = *this;
- --*this;
- return it;
- }
-
- iterator_type& operator+=(difference_type aDiff) {
- mIndex += aDiff;
- return *this;
- }
- iterator_type& operator-=(difference_type aDiff) {
- mIndex -= aDiff;
- return *this;
- }
-
- iterator_type operator+(difference_type aDiff) const {
- iterator_type it = *this;
- it += aDiff;
- return it;
- }
- iterator_type operator-(difference_type aDiff) const {
- iterator_type it = *this;
- it -= aDiff;
- return it;
- }
-
- difference_type operator-(const iterator_type& aOther) const {
- return static_cast<difference_type>(mIndex) -
- static_cast<difference_type>(aOther.mIndex);
- }
-
- value_type& operator[](difference_type aIndex) const {
- return *this->operator+(aIndex);
- }
-};
-
// Servo bindings.
extern "C" void Gecko_EnsureTArrayCapacity(void* aArray,
size_t aCapacity,
size_t aElementSize);
extern "C" void Gecko_ClearPODTArray(void* aArray,
size_t aElementSize,
size_t aElementAlign);
@@ -973,18 +855,18 @@ public:
typedef typename nsTArray_CopyChooser<E>::Type copy_type;
typedef nsTArray_base<Alloc, copy_type> base_type;
typedef typename base_type::size_type size_type;
typedef typename base_type::index_type index_type;
typedef E elem_type;
typedef nsTArray_Impl<E, Alloc> self_type;
typedef nsTArrayElementTraits<E> elem_traits;
typedef nsTArray_SafeElementAtHelper<E, self_type> safeelementat_helper_type;
- typedef nsTArrayIterator<elem_type> iterator;
- typedef nsTArrayIterator<const elem_type> const_iterator;
+ typedef mozilla::ArrayIterator<elem_type&, nsTArray<E>> iterator;
+ typedef mozilla::ArrayIterator<const elem_type&, nsTArray<E>> const_iterator;
typedef mozilla::ReverseIterator<iterator> reverse_iterator;
typedef mozilla::ReverseIterator<const_iterator> const_reverse_iterator;
using safeelementat_helper_type::SafeElementAt;
using base_type::EmptyHdr;
// A special value that is used to indicate an invalid or unknown index
// into the array.