1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_Range_h
8 #define mozilla_Range_h
10 #include "mozilla/RangedPtr.h"
11 #include "mozilla/Span.h"
14 #include <type_traits>
18 // Range<T> is a tuple containing a pointer and a length.
24 // Reassignment of RangedPtrs is so (subtly) restrictive that we just make
26 const RangedPtr
<T
> mStart
;
27 const RangedPtr
<T
> mEnd
;
30 Range() : mStart(nullptr, 0), mEnd(nullptr, 0) {}
31 Range(T
* aPtr
, size_t aLength
)
32 : mStart(aPtr
, aPtr
, aPtr
+ aLength
),
33 mEnd(aPtr
+ aLength
, aPtr
, aPtr
+ aLength
) {
35 MOZ_ASSERT_DEBUG_OR_FUZZING(
36 !aLength
, "Range does not support nullptr with non-zero length.");
37 // ...because merely having a pointer to `nullptr + 1` is undefined
38 // behavior. UBSAN catches this as of clang-10.
41 Range(const RangedPtr
<T
>& aStart
, const RangedPtr
<T
>& aEnd
)
42 : mStart(aStart
.get(), aStart
.get(), aEnd
.get()),
43 mEnd(aEnd
.get(), aStart
.get(), aEnd
.get()) {
44 // Only accept two RangedPtrs within the same range.
45 aStart
.checkIdenticalRange(aEnd
);
46 MOZ_ASSERT_DEBUG_OR_FUZZING(aStart
<= aEnd
);
49 template <typename U
, class = std::enable_if_t
<
50 std::is_convertible_v
<U (*)[], T (*)[]>, int>>
51 MOZ_IMPLICIT
Range(const Range
<U
>& aOther
)
52 : mStart(aOther
.mStart
), mEnd(aOther
.mEnd
) {}
54 MOZ_IMPLICIT
Range(Span
<T
> aSpan
) : Range(aSpan
.Elements(), aSpan
.Length()) {}
56 template <typename U
, class = std::enable_if_t
<
57 std::is_convertible_v
<U (*)[], T (*)[]>, int>>
58 MOZ_IMPLICIT
Range(const Span
<U
>& aSpan
)
59 : Range(aSpan
.Elements(), aSpan
.Length()) {}
61 RangedPtr
<T
> begin() const { return mStart
; }
62 RangedPtr
<T
> end() const { return mEnd
; }
63 size_t length() const { return mEnd
- mStart
; }
65 T
& operator[](size_t aOffset
) const { return mStart
[aOffset
]; }
67 explicit operator bool() const { return mStart
!= nullptr; }
69 operator Span
<T
>() { return Span
<T
>(mStart
.get(), length()); }
71 operator Span
<const T
>() const { return Span
<T
>(mStart
.get(), length()); }
75 Span(Range
<T
>&) -> Span
<T
>;
78 Span(const Range
<T
>&) -> Span
<const T
>;
80 } // namespace mozilla
82 #endif /* mozilla_Range_h */