From 43a97878ce14b72f0981164f87f2e35e14151312 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:22:09 +0200 Subject: Adding upstream version 110.0.1. Signed-off-by: Daniel Baumann --- xpcom/ds/ArrayIterator.h | 165 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 xpcom/ds/ArrayIterator.h (limited to 'xpcom/ds/ArrayIterator.h') diff --git a/xpcom/ds/ArrayIterator.h b/xpcom/ds/ArrayIterator.h new file mode 100644 index 0000000000..cc6c8d1cb4 --- /dev/null +++ b/xpcom/ds/ArrayIterator.h @@ -0,0 +1,165 @@ +/* -*- 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 +#include + +namespace mozilla { + +namespace detail { +template +struct AddInnerConst; + +template +struct AddInnerConst { + using Type = const T&; +}; + +template +struct AddInnerConst { + using Type = const T*; +}; + +template +using AddInnerConstT = typename AddInnerConst::Type; +} // namespace detail + +// 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 ArrayIterator { + public: + typedef ArrayType array_type; + typedef ArrayIterator iterator_type; + typedef typename array_type::index_type index_type; + typedef std::remove_reference_t value_type; + typedef ptrdiff_t difference_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef std::random_access_iterator_tag iterator_category; + typedef ArrayIterator, ArrayType> + const_iterator_type; + + 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; + } + + constexpr operator const_iterator_type() const { + return mArray ? const_iterator_type{*mArray, mIndex} + : const_iterator_type{}; + } + + 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(&mArray->ElementAt(mIndex)); + } + Element operator*() const { + return const_cast(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(mIndex) - + static_cast(aOther.mIndex); + } + + Element operator[](difference_type aIndex) const { + return *this->operator+(aIndex); + } + + constexpr const array_type* GetArray() const { return mArray; } + + constexpr index_type GetIndex() const { return mIndex; } +}; + +} // namespace mozilla + +#endif // mozilla_ArrayIterator_h -- cgit v1.2.3