diff options
Diffstat (limited to 'xpcom/glue/nsTArray.h')
-rw-r--r-- | xpcom/glue/nsTArray.h | 126 |
1 files changed, 112 insertions, 14 deletions
diff --git a/xpcom/glue/nsTArray.h b/xpcom/glue/nsTArray.h index ca74a41f7..82586a79a 100644 --- a/xpcom/glue/nsTArray.h +++ b/xpcom/glue/nsTArray.h @@ -12,6 +12,7 @@ #include "mozilla/Assertions.h" #include "mozilla/Attributes.h" #include "mozilla/BinarySearch.h" +#include "mozilla/CheckedInt.h" #include "mozilla/fallible.h" #include "mozilla/Function.h" #include "mozilla/MathAlgorithms.h" @@ -19,6 +20,7 @@ #include "mozilla/Move.h" #include "mozilla/ReverseIterator.h" #include "mozilla/TypeTraits.h" +#include "mozilla/Span.h" #include <string.h> @@ -420,6 +422,17 @@ protected: typename ActualAlloc::ResultTypeProxy EnsureCapacity(size_type aCapacity, size_type aElemSize); + // Extend the storage to accommodate aCount extra elements. + // @param aLength The current size of the array. + // @param aCount The number of elements to add. + // @param aElemSize The size of an array element. + // @return False if insufficient memory is available or the new length + // would overflow; true otherwise. + template<typename ActualAlloc> + typename ActualAlloc::ResultTypeProxy ExtendCapacity(size_type aLength, + size_type aCount, + size_type aElemSize); + // Tries to resize the storage to the minimum required amount. If this fails, // the array is left as-is. // @param aElemSize The size of an array element. @@ -461,8 +474,9 @@ protected: // @param aElementSize the size of an array element. // @param aElemAlign the alignment in bytes of an array element. template<typename ActualAlloc> - bool InsertSlotsAt(index_type aIndex, size_type aCount, - size_type aElementSize, size_t aElemAlign); + typename ActualAlloc::ResultTypeProxy + InsertSlotsAt(index_type aIndex, size_type aCount, + size_type aElementSize, size_t aElemAlign); template<typename ActualAlloc, class Allocator> typename ActualAlloc::ResultTypeProxy @@ -1112,6 +1126,18 @@ public: const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } const_reverse_iterator crend() const { return rend(); } + // Span integration + + operator mozilla::Span<elem_type>() + { + return mozilla::Span<elem_type>(Elements(), Length()); + } + + operator mozilla::Span<const elem_type>() const + { + return mozilla::Span<const elem_type>(Elements(), Length()); + } + // // Search methods // @@ -1336,6 +1362,16 @@ protected: return ReplaceElementsAt<Item, ActualAlloc>( aStart, aCount, aArray.Elements(), aArray.Length()); } + + template<class Item, typename ActualAlloc = Alloc> + elem_type* ReplaceElementsAt(index_type aStart, + size_type aCount, + mozilla::Span<const Item> aSpan) + { + return ReplaceElementsAt<Item, ActualAlloc>( + aStart, aCount, aSpan.Elements(), aSpan.Length()); + } + public: template<class Item> @@ -1347,6 +1383,15 @@ public: return ReplaceElementsAt<Item, FallibleAlloc>(aStart, aCount, aArray); } + template<class Item> + MOZ_MUST_USE elem_type* ReplaceElementsAt(index_type aStart, + size_type aCount, + mozilla::Span<const Item> aSpan, + const mozilla::fallible_t&) + { + return ReplaceElementsAt<Item, FallibleAlloc>(aStart, aCount, aSpan); + } + // A variation on the ReplaceElementsAt method defined above. protected: template<class Item, typename ActualAlloc = Alloc> @@ -1399,6 +1444,15 @@ protected: return ReplaceElementsAt<Item, ActualAlloc>( aIndex, 0, aArray.Elements(), aArray.Length()); } + + template<class Item, typename ActualAlloc = Alloc> + elem_type* InsertElementsAt(index_type aIndex, + mozilla::Span<const Item> aSpan) + { + return ReplaceElementsAt<Item, ActualAlloc>( + aIndex, 0, aSpan.Elements(), aSpan.Length()); + } + public: template<class Item, class Allocator> @@ -1425,6 +1479,14 @@ public: return InsertElementAt<FallibleAlloc>(aIndex); } + template<class Item> + MOZ_MUST_USE elem_type* InsertElementsAt(index_type aIndex, + mozilla::Span<const Item> aSpan, + const mozilla::fallible_t&) + { + return InsertElementsAt<Item, FallibleAlloc>(aIndex, aSpan); + } + // Insert a new element, move constructing if possible. protected: template<class Item, typename ActualAlloc = Alloc> @@ -1526,6 +1588,13 @@ protected: template<class Item, typename ActualAlloc = Alloc> elem_type* AppendElements(const Item* aArray, size_type aArrayLen); + template<class Item, typename ActualAlloc = Alloc> + elem_type* AppendElements(mozilla::Span<const Item> aSpan) + { + return AppendElements<Item, FallibleAlloc>(aSpan.Elements(), + aSpan.Length()); + } + public: template<class Item> @@ -1536,6 +1605,15 @@ public: return AppendElements<Item, FallibleAlloc>(aArray, aArrayLen); } + template<class Item> + /* MOZ_MUST_USE */ + elem_type* AppendElements(mozilla::Span<const Item> aSpan, + const mozilla::fallible_t&) + { + return AppendElements<Item, FallibleAlloc>(aSpan.Elements(), + aSpan.Length()); + } + // A variation on the AppendElements method defined above. protected: template<class Item, class Allocator, typename ActualAlloc = Alloc> @@ -1590,8 +1668,8 @@ public: protected: template<typename ActualAlloc = Alloc> elem_type* AppendElements(size_type aCount) { - if (!ActualAlloc::Successful(this->template EnsureCapacity<ActualAlloc>( - Length() + aCount, sizeof(elem_type)))) { + if (!ActualAlloc::Successful(this->template ExtendCapacity<ActualAlloc>( + Length(), aCount, sizeof(elem_type)))) { return nullptr; } elem_type* elems = Elements() + Length(); @@ -1807,9 +1885,8 @@ protected: template<typename ActualAlloc = Alloc> elem_type* InsertElementsAt(index_type aIndex, size_type aCount) { - if (!base_type::template InsertSlotsAt<ActualAlloc>(aIndex, aCount, - sizeof(elem_type), - MOZ_ALIGNOF(elem_type))) { + if (!ActualAlloc::Successful(this->template InsertSlotsAt<ActualAlloc>( + aIndex, aCount, sizeof(elem_type), MOZ_ALIGNOF(elem_type)))) { return nullptr; } @@ -1982,9 +2059,8 @@ auto nsTArray_Impl<E, Alloc>::InsertElementsAt(index_type aIndex, size_type aCount, const Item& aItem) -> elem_type* { - if (!base_type::template InsertSlotsAt<ActualAlloc>(aIndex, aCount, - sizeof(elem_type), - MOZ_ALIGNOF(elem_type))) { + if (!ActualAlloc::Successful(this->template InsertSlotsAt<ActualAlloc>( + aIndex, aCount, sizeof(elem_type), MOZ_ALIGNOF(elem_type)))) { return nullptr; } @@ -2003,6 +2079,7 @@ template<typename ActualAlloc> auto nsTArray_Impl<E, Alloc>::InsertElementAt(index_type aIndex) -> elem_type* { + // Length() + 1 is guaranteed to not overflow, so EnsureCapacity is OK. if (!ActualAlloc::Successful(this->template EnsureCapacity<ActualAlloc>( Length() + 1, sizeof(elem_type)))) { return nullptr; @@ -2019,6 +2096,7 @@ template<class Item, typename ActualAlloc> auto nsTArray_Impl<E, Alloc>::InsertElementAt(index_type aIndex, Item&& aItem) -> elem_type* { + // Length() + 1 is guaranteed to not overflow, so EnsureCapacity is OK. if (!ActualAlloc::Successful(this->template EnsureCapacity<ActualAlloc>( Length() + 1, sizeof(elem_type)))) { return nullptr; @@ -2035,8 +2113,8 @@ template<class Item, typename ActualAlloc> auto nsTArray_Impl<E, Alloc>::AppendElements(const Item* aArray, size_type aArrayLen) -> elem_type* { - if (!ActualAlloc::Successful(this->template EnsureCapacity<ActualAlloc>( - Length() + aArrayLen, sizeof(elem_type)))) { + if (!ActualAlloc::Successful(this->template ExtendCapacity<ActualAlloc>( + Length(), aArrayLen, sizeof(elem_type)))) { return nullptr; } index_type len = Length(); @@ -2058,8 +2136,8 @@ nsTArray_Impl<E, Alloc>::AppendElements(nsTArray_Impl<Item, Allocator>&& aArray) index_type len = Length(); index_type otherLen = aArray.Length(); - if (!Alloc::Successful(this->template EnsureCapacity<Alloc>( - len + otherLen, sizeof(elem_type)))) { + if (!Alloc::Successful(this->template ExtendCapacity<Alloc>( + len, otherLen, sizeof(elem_type)))) { return nullptr; } copy_type::MoveNonOverlappingRegion(Elements() + len, aArray.Elements(), otherLen, @@ -2075,6 +2153,7 @@ template<class Item, typename ActualAlloc> auto nsTArray_Impl<E, Alloc>::AppendElement(Item&& aItem) -> elem_type* { + // Length() + 1 is guaranteed to not overflow, so EnsureCapacity is OK. if (!ActualAlloc::Successful(this->template EnsureCapacity<ActualAlloc>( Length() + 1, sizeof(elem_type)))) { return nullptr; @@ -2347,6 +2426,25 @@ struct nsTArray_CopyChooser<AutoTArray<E, N>> typedef nsTArray_CopyWithConstructors<AutoTArray<E, N>> Type; }; +// Span integration +namespace mozilla { + +template<class ElementType, class TArrayAlloc> +Span<ElementType> +MakeSpan(nsTArray_Impl<ElementType, TArrayAlloc>& aTArray) +{ + return aTArray; +} + +template<class ElementType, class TArrayAlloc> +Span<const ElementType> +MakeSpan(const nsTArray_Impl<ElementType, TArrayAlloc>& aTArray) +{ + return aTArray; +} + +} // namespace mozilla + // Assert that AutoTArray doesn't have any extra padding inside. // // It's important that the data stored in this auto array takes up a multiple of |