DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (409f3966645a)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 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