Bug 1295611 - Add mozilla::Span. r=froydnj,gerv.

MozReview-Commit-ID: HGNDClVctbE
This commit is contained in:
Henri Sivonen 2017-02-16 11:43:50 +02:00
parent 3905bf8fc4
commit c514501f1a
10 changed files with 3386 additions and 0 deletions

View file

@ -238,6 +238,19 @@ AssertedCast(const From aFrom)
return static_cast<To>(aFrom);
}
/**
* Cast a value of integral type |From| to a value of integral type |To|,
* release asserting that the cast will be a safe cast per C++ (that is, that
* |to| is in the range of values permitted for the type |From|).
*/
template<typename To, typename From>
inline To
ReleaseAssertedCast(const From aFrom)
{
MOZ_RELEASE_ASSERT((detail::IsInBounds<From, To>(aFrom)));
return static_cast<To>(aFrom);
}
} // namespace mozilla
#endif /* mozilla_Casting_h */

View file

@ -9,6 +9,7 @@
#include "mozilla/RangedPtr.h"
#include "mozilla/TypeTraits.h"
#include "mozilla/Span.h"
#include <stddef.h>
@ -44,6 +45,19 @@ public:
mEnd(aOther.mEnd)
{}
MOZ_IMPLICIT Range(Span<T> aSpan)
: Range(aSpan.Elements(), aSpan.Length())
{
}
template<typename U,
class = typename EnableIf<IsConvertible<U (*)[], T (*)[]>::value,
int>::Type>
MOZ_IMPLICIT Range(const Span<U>& aSpan)
: Range(aSpan.Elements(), aSpan.Length())
{
}
RangedPtr<T> begin() const { return mStart; }
RangedPtr<T> end() const { return mEnd; }
size_t length() const { return mEnd - mStart; }
@ -51,8 +65,26 @@ public:
T& operator[](size_t aOffset) const { return mStart[aOffset]; }
explicit operator bool() const { return mStart != nullptr; }
operator Span<T>() { return Span<T>(mStart.get(), length()); }
operator Span<const T>() const { return Span<T>(mStart.get(), length()); }
};
template<class T>
Span<T>
MakeSpan(Range<T>& aRange)
{
return aRange;
}
template<class T>
Span<const T>
MakeSpan(const Range<T>& aRange)
{
return aRange;
}
} // namespace mozilla
#endif /* mozilla_Range_h */

1041
mfbt/Span.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -82,6 +82,7 @@ EXPORTS.mozilla = [
'SegmentedVector.h',
'SHA1.h',
'SizePrintfMacros.h',
'Span.h',
'SplayTree.h',
'Sprintf.h',
'StaticAnalysisFunctions.h',

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,15 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
UNIFIED_SOURCES += [
'TestSpan.cpp',
]
#LOCAL_INCLUDES += [
# '../../base',
#]
FINAL_LIBRARY = 'xul-gtest'

View file

@ -4,6 +4,11 @@
# 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/.
if not CONFIG['JS_STANDALONE']:
TEST_DIRS += [
'gtest',
]
CppUnitTests([
'TestArray',
'TestArrayUtils',

View file

@ -101,6 +101,7 @@
<li><a href="about:license#gears">Google Gears License</a></li>
<li><a href="about:license#gears-istumbler">Google Gears/iStumbler License</a></li>
<li><a href="about:license#vp8">Google VP8 License</a></li>
<li><a href="about:license#gsl">GSL License</a></li>
<li><a href="about:license#gyp">gyp License</a></li>
<li><a href="about:license#halloc">halloc License</a></li>
<li><a href="about:license#harfbuzz">HarfBuzz License</a></li>
@ -3415,6 +3416,38 @@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</pre>
<hr>
<h1><a id="gsl"></a>GSL License</h1>
<p>This license applies to <span class="path">mfbt/Span.h</span> and
<span class="path">mfbt/tests/gtest/TestSpan.cpp</span>.</p>
<!-- https://github.com/Microsoft/GSL/blob/3819df6e378ffccf0e29465afe99c3b324c2aa70/LICENSE -->
<pre>
Copyright (c) 2015 Microsoft Corporation. All rights reserved.
This code is licensed under the MIT License (MIT).
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
</pre>
<hr>
<h1><a id="gyp"></a>gyp License</h1>

View file

@ -19,6 +19,7 @@
#include "mozilla/Move.h"
#include "mozilla/ReverseIterator.h"
#include "mozilla/TypeTraits.h"
#include "mozilla/Span.h"
#include <string.h>
@ -1116,6 +1117,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
//
@ -1340,6 +1353,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>
@ -1351,6 +1374,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>
@ -1403,6 +1435,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>
@ -1414,6 +1455,14 @@ public:
return InsertElementsAt<Item, Allocator, FallibleAlloc>(aIndex, aArray);
}
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 without copy-constructing. This is useful to avoid
// temporaries.
// @return A pointer to the newly inserted element, or null on OOM.
@ -1548,6 +1597,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());
}
template<class Item, size_t Length, typename ActualAlloc = Alloc>
elem_type* AppendElements(const mozilla::Array<Item, Length>& aArray)
{
@ -1564,6 +1620,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>
@ -2397,6 +2462,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

View file

@ -9,6 +9,8 @@
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/IntegerTypeTraits.h"
#include "mozilla/Span.h"
#ifndef MOZILLA_INTERNAL_API
#error "Using XPCOM strings is limited to code linked into libxul."
@ -922,6 +924,68 @@ public:
}
#endif
/**
* Span integration
*/
operator mozilla::Span<char_type>()
{
return mozilla::MakeSpan(BeginWriting(), Length());
}
operator mozilla::Span<const char_type>() const
{
return mozilla::MakeSpan(BeginReading(), Length());
}
void Append(mozilla::Span<const char_type> aSpan)
{
auto len = aSpan.Length();
MOZ_RELEASE_ASSERT(len <= mozilla::MaxValue<size_type>::value);
Append(aSpan.Elements(), len);
}
MOZ_MUST_USE bool Append(mozilla::Span<const char_type> aSpan,
const fallible_t& aFallible)
{
auto len = aSpan.Length();
if (len > mozilla::MaxValue<size_type>::value) {
return false;
}
return Append(aSpan.Elements(), len, aFallible);
}
#if !defined(CharT_is_PRUnichar)
operator mozilla::Span<uint8_t>()
{
return mozilla::MakeSpan(reinterpret_cast<uint8_t*>(BeginWriting()),
Length());
}
operator mozilla::Span<const uint8_t>() const
{
return mozilla::MakeSpan(reinterpret_cast<const uint8_t*>(BeginReading()),
Length());
}
void Append(mozilla::Span<const uint8_t> aSpan)
{
auto len = aSpan.Length();
MOZ_RELEASE_ASSERT(len <= mozilla::MaxValue<size_type>::value);
Append(reinterpret_cast<const char*>(aSpan.Elements()), len);
}
MOZ_MUST_USE bool Append(mozilla::Span<const uint8_t> aSpan,
const fallible_t& aFallible)
{
auto len = aSpan.Length();
if (len > mozilla::MaxValue<size_type>::value) {
return false;
}
return Append(
reinterpret_cast<const char*>(aSpan.Elements()), len, aFallible);
}
#endif
/**
* string data is never null, but can be marked void. if true, the
@ -1272,3 +1336,22 @@ public:
return mArray[index];
}
};
/**
* Span integration
*/
namespace mozilla {
inline Span<CharT>
MakeSpan(nsTSubstring_CharT& aString)
{
return aString;
}
inline Span<const CharT>
MakeSpan(const nsTSubstring_CharT& aString)
{
return aString;
}
} // namespace mozilla