1*635a8641SAndroid Build Coastguard Worker // Copyright 2017 The Chromium Authors. All rights reserved. 2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file. 4*635a8641SAndroid Build Coastguard Worker 5*635a8641SAndroid Build Coastguard Worker #ifndef BASE_CONTAINERS_SPAN_H_ 6*635a8641SAndroid Build Coastguard Worker #define BASE_CONTAINERS_SPAN_H_ 7*635a8641SAndroid Build Coastguard Worker 8*635a8641SAndroid Build Coastguard Worker #include <stddef.h> 9*635a8641SAndroid Build Coastguard Worker 10*635a8641SAndroid Build Coastguard Worker #include <algorithm> 11*635a8641SAndroid Build Coastguard Worker #include <array> 12*635a8641SAndroid Build Coastguard Worker #include <iterator> 13*635a8641SAndroid Build Coastguard Worker #include <type_traits> 14*635a8641SAndroid Build Coastguard Worker #include <utility> 15*635a8641SAndroid Build Coastguard Worker 16*635a8641SAndroid Build Coastguard Worker #include "base/logging.h" 17*635a8641SAndroid Build Coastguard Worker #include "base/stl_util.h" 18*635a8641SAndroid Build Coastguard Worker 19*635a8641SAndroid Build Coastguard Worker namespace base { 20*635a8641SAndroid Build Coastguard Worker 21*635a8641SAndroid Build Coastguard Worker // [views.constants] 22*635a8641SAndroid Build Coastguard Worker constexpr size_t dynamic_extent = static_cast<size_t>(-1); 23*635a8641SAndroid Build Coastguard Worker 24*635a8641SAndroid Build Coastguard Worker template <typename T, size_t Extent = dynamic_extent> 25*635a8641SAndroid Build Coastguard Worker class span; 26*635a8641SAndroid Build Coastguard Worker 27*635a8641SAndroid Build Coastguard Worker namespace internal { 28*635a8641SAndroid Build Coastguard Worker 29*635a8641SAndroid Build Coastguard Worker template <typename T> 30*635a8641SAndroid Build Coastguard Worker struct IsSpanImpl : std::false_type {}; 31*635a8641SAndroid Build Coastguard Worker 32*635a8641SAndroid Build Coastguard Worker template <typename T, size_t Extent> 33*635a8641SAndroid Build Coastguard Worker struct IsSpanImpl<span<T, Extent>> : std::true_type {}; 34*635a8641SAndroid Build Coastguard Worker 35*635a8641SAndroid Build Coastguard Worker template <typename T> 36*635a8641SAndroid Build Coastguard Worker using IsSpan = IsSpanImpl<std::decay_t<T>>; 37*635a8641SAndroid Build Coastguard Worker 38*635a8641SAndroid Build Coastguard Worker template <typename T> 39*635a8641SAndroid Build Coastguard Worker struct IsStdArrayImpl : std::false_type {}; 40*635a8641SAndroid Build Coastguard Worker 41*635a8641SAndroid Build Coastguard Worker template <typename T, size_t N> 42*635a8641SAndroid Build Coastguard Worker struct IsStdArrayImpl<std::array<T, N>> : std::true_type {}; 43*635a8641SAndroid Build Coastguard Worker 44*635a8641SAndroid Build Coastguard Worker template <typename T> 45*635a8641SAndroid Build Coastguard Worker using IsStdArray = IsStdArrayImpl<std::decay_t<T>>; 46*635a8641SAndroid Build Coastguard Worker 47*635a8641SAndroid Build Coastguard Worker template <typename T> 48*635a8641SAndroid Build Coastguard Worker using IsCArray = std::is_array<std::remove_reference_t<T>>; 49*635a8641SAndroid Build Coastguard Worker 50*635a8641SAndroid Build Coastguard Worker template <typename From, typename To> 51*635a8641SAndroid Build Coastguard Worker using IsLegalDataConversion = std::is_convertible<From (*)[], To (*)[]>; 52*635a8641SAndroid Build Coastguard Worker 53*635a8641SAndroid Build Coastguard Worker template <typename Container, typename T> 54*635a8641SAndroid Build Coastguard Worker using ContainerHasConvertibleData = IsLegalDataConversion< 55*635a8641SAndroid Build Coastguard Worker std::remove_pointer_t<decltype(base::data(std::declval<Container>()))>, 56*635a8641SAndroid Build Coastguard Worker T>; 57*635a8641SAndroid Build Coastguard Worker 58*635a8641SAndroid Build Coastguard Worker template <typename Container> 59*635a8641SAndroid Build Coastguard Worker using ContainerHasIntegralSize = 60*635a8641SAndroid Build Coastguard Worker std::is_integral<decltype(base::size(std::declval<Container>()))>; 61*635a8641SAndroid Build Coastguard Worker 62*635a8641SAndroid Build Coastguard Worker template <typename From, size_t FromExtent, typename To, size_t ToExtent> 63*635a8641SAndroid Build Coastguard Worker using EnableIfLegalSpanConversion = 64*635a8641SAndroid Build Coastguard Worker std::enable_if_t<(ToExtent == dynamic_extent || ToExtent == FromExtent) && 65*635a8641SAndroid Build Coastguard Worker IsLegalDataConversion<From, To>::value>; 66*635a8641SAndroid Build Coastguard Worker 67*635a8641SAndroid Build Coastguard Worker // SFINAE check if Array can be converted to a span<T>. 68*635a8641SAndroid Build Coastguard Worker template <typename Array, size_t N, typename T, size_t Extent> 69*635a8641SAndroid Build Coastguard Worker using EnableIfSpanCompatibleArray = 70*635a8641SAndroid Build Coastguard Worker std::enable_if_t<(Extent == dynamic_extent || Extent == N) && 71*635a8641SAndroid Build Coastguard Worker ContainerHasConvertibleData<Array, T>::value>; 72*635a8641SAndroid Build Coastguard Worker 73*635a8641SAndroid Build Coastguard Worker // SFINAE check if Container can be converted to a span<T>. 74*635a8641SAndroid Build Coastguard Worker template <typename Container, typename T> 75*635a8641SAndroid Build Coastguard Worker using EnableIfSpanCompatibleContainer = 76*635a8641SAndroid Build Coastguard Worker std::enable_if_t<!internal::IsSpan<Container>::value && 77*635a8641SAndroid Build Coastguard Worker !internal::IsStdArray<Container>::value && 78*635a8641SAndroid Build Coastguard Worker !internal::IsCArray<Container>::value && 79*635a8641SAndroid Build Coastguard Worker ContainerHasConvertibleData<Container, T>::value && 80*635a8641SAndroid Build Coastguard Worker ContainerHasIntegralSize<Container>::value>; 81*635a8641SAndroid Build Coastguard Worker 82*635a8641SAndroid Build Coastguard Worker } // namespace internal 83*635a8641SAndroid Build Coastguard Worker 84*635a8641SAndroid Build Coastguard Worker // A span is a value type that represents an array of elements of type T. Since 85*635a8641SAndroid Build Coastguard Worker // it only consists of a pointer to memory with an associated size, it is very 86*635a8641SAndroid Build Coastguard Worker // light-weight. It is cheap to construct, copy, move and use spans, so that 87*635a8641SAndroid Build Coastguard Worker // users are encouraged to use it as a pass-by-value parameter. A span does not 88*635a8641SAndroid Build Coastguard Worker // own the underlying memory, so care must be taken to ensure that a span does 89*635a8641SAndroid Build Coastguard Worker // not outlive the backing store. 90*635a8641SAndroid Build Coastguard Worker // 91*635a8641SAndroid Build Coastguard Worker // span is somewhat analogous to StringPiece, but with arbitrary element types, 92*635a8641SAndroid Build Coastguard Worker // allowing mutation if T is non-const. 93*635a8641SAndroid Build Coastguard Worker // 94*635a8641SAndroid Build Coastguard Worker // span is implicitly convertible from C++ arrays, as well as most [1] 95*635a8641SAndroid Build Coastguard Worker // container-like types that provide a data() and size() method (such as 96*635a8641SAndroid Build Coastguard Worker // std::vector<T>). A mutable span<T> can also be implicitly converted to an 97*635a8641SAndroid Build Coastguard Worker // immutable span<const T>. 98*635a8641SAndroid Build Coastguard Worker // 99*635a8641SAndroid Build Coastguard Worker // Consider using a span for functions that take a data pointer and size 100*635a8641SAndroid Build Coastguard Worker // parameter: it allows the function to still act on an array-like type, while 101*635a8641SAndroid Build Coastguard Worker // allowing the caller code to be a bit more concise. 102*635a8641SAndroid Build Coastguard Worker // 103*635a8641SAndroid Build Coastguard Worker // For read-only data access pass a span<const T>: the caller can supply either 104*635a8641SAndroid Build Coastguard Worker // a span<const T> or a span<T>, while the callee will have a read-only view. 105*635a8641SAndroid Build Coastguard Worker // For read-write access a mutable span<T> is required. 106*635a8641SAndroid Build Coastguard Worker // 107*635a8641SAndroid Build Coastguard Worker // Without span: 108*635a8641SAndroid Build Coastguard Worker // Read-Only: 109*635a8641SAndroid Build Coastguard Worker // // std::string HexEncode(const uint8_t* data, size_t size); 110*635a8641SAndroid Build Coastguard Worker // std::vector<uint8_t> data_buffer = GenerateData(); 111*635a8641SAndroid Build Coastguard Worker // std::string r = HexEncode(data_buffer.data(), data_buffer.size()); 112*635a8641SAndroid Build Coastguard Worker // 113*635a8641SAndroid Build Coastguard Worker // Mutable: 114*635a8641SAndroid Build Coastguard Worker // // ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, Args...); 115*635a8641SAndroid Build Coastguard Worker // char str_buffer[100]; 116*635a8641SAndroid Build Coastguard Worker // SafeSNPrintf(str_buffer, sizeof(str_buffer), "Pi ~= %lf", 3.14); 117*635a8641SAndroid Build Coastguard Worker // 118*635a8641SAndroid Build Coastguard Worker // With span: 119*635a8641SAndroid Build Coastguard Worker // Read-Only: 120*635a8641SAndroid Build Coastguard Worker // // std::string HexEncode(base::span<const uint8_t> data); 121*635a8641SAndroid Build Coastguard Worker // std::vector<uint8_t> data_buffer = GenerateData(); 122*635a8641SAndroid Build Coastguard Worker // std::string r = HexEncode(data_buffer); 123*635a8641SAndroid Build Coastguard Worker // 124*635a8641SAndroid Build Coastguard Worker // Mutable: 125*635a8641SAndroid Build Coastguard Worker // // ssize_t SafeSNPrintf(base::span<char>, const char* fmt, Args...); 126*635a8641SAndroid Build Coastguard Worker // char str_buffer[100]; 127*635a8641SAndroid Build Coastguard Worker // SafeSNPrintf(str_buffer, "Pi ~= %lf", 3.14); 128*635a8641SAndroid Build Coastguard Worker // 129*635a8641SAndroid Build Coastguard Worker // Spans with "const" and pointers 130*635a8641SAndroid Build Coastguard Worker // ------------------------------- 131*635a8641SAndroid Build Coastguard Worker // 132*635a8641SAndroid Build Coastguard Worker // Const and pointers can get confusing. Here are vectors of pointers and their 133*635a8641SAndroid Build Coastguard Worker // corresponding spans: 134*635a8641SAndroid Build Coastguard Worker // 135*635a8641SAndroid Build Coastguard Worker // const std::vector<int*> => base::span<int* const> 136*635a8641SAndroid Build Coastguard Worker // std::vector<const int*> => base::span<const int*> 137*635a8641SAndroid Build Coastguard Worker // const std::vector<const int*> => base::span<const int* const> 138*635a8641SAndroid Build Coastguard Worker // 139*635a8641SAndroid Build Coastguard Worker // Differences from the working group proposal 140*635a8641SAndroid Build Coastguard Worker // ------------------------------------------- 141*635a8641SAndroid Build Coastguard Worker // 142*635a8641SAndroid Build Coastguard Worker // https://wg21.link/P0122 is the latest working group proposal, Chromium 143*635a8641SAndroid Build Coastguard Worker // currently implements R7. Differences between the proposal and the 144*635a8641SAndroid Build Coastguard Worker // implementation are documented in subsections below. 145*635a8641SAndroid Build Coastguard Worker // 146*635a8641SAndroid Build Coastguard Worker // Differences from [span.objectrep]: 147*635a8641SAndroid Build Coastguard Worker // - as_bytes() and as_writable_bytes() return spans of uint8_t instead of 148*635a8641SAndroid Build Coastguard Worker // std::byte 149*635a8641SAndroid Build Coastguard Worker // 150*635a8641SAndroid Build Coastguard Worker // Differences in constants and types: 151*635a8641SAndroid Build Coastguard Worker // - index_type is aliased to size_t 152*635a8641SAndroid Build Coastguard Worker // 153*635a8641SAndroid Build Coastguard Worker // Differences from [span.sub]: 154*635a8641SAndroid Build Coastguard Worker // - using size_t instead of ptrdiff_t for indexing 155*635a8641SAndroid Build Coastguard Worker // 156*635a8641SAndroid Build Coastguard Worker // Differences from [span.obs]: 157*635a8641SAndroid Build Coastguard Worker // - using size_t instead of ptrdiff_t to represent size() 158*635a8641SAndroid Build Coastguard Worker // 159*635a8641SAndroid Build Coastguard Worker // Differences from [span.elem]: 160*635a8641SAndroid Build Coastguard Worker // - using size_t instead of ptrdiff_t for indexing 161*635a8641SAndroid Build Coastguard Worker // 162*635a8641SAndroid Build Coastguard Worker // Furthermore, all constructors and methods are marked noexcept due to the lack 163*635a8641SAndroid Build Coastguard Worker // of exceptions in Chromium. 164*635a8641SAndroid Build Coastguard Worker // 165*635a8641SAndroid Build Coastguard Worker // Due to the lack of class template argument deduction guides in C++14 166*635a8641SAndroid Build Coastguard Worker // appropriate make_span() utility functions are provided. 167*635a8641SAndroid Build Coastguard Worker 168*635a8641SAndroid Build Coastguard Worker // [span], class template span 169*635a8641SAndroid Build Coastguard Worker template <typename T, size_t Extent> 170*635a8641SAndroid Build Coastguard Worker class span { 171*635a8641SAndroid Build Coastguard Worker public: 172*635a8641SAndroid Build Coastguard Worker using element_type = T; 173*635a8641SAndroid Build Coastguard Worker using value_type = std::remove_cv_t<T>; 174*635a8641SAndroid Build Coastguard Worker using index_type = size_t; 175*635a8641SAndroid Build Coastguard Worker using difference_type = ptrdiff_t; 176*635a8641SAndroid Build Coastguard Worker using pointer = T*; 177*635a8641SAndroid Build Coastguard Worker using reference = T&; 178*635a8641SAndroid Build Coastguard Worker using iterator = T*; 179*635a8641SAndroid Build Coastguard Worker using const_iterator = const T*; 180*635a8641SAndroid Build Coastguard Worker using reverse_iterator = std::reverse_iterator<iterator>; 181*635a8641SAndroid Build Coastguard Worker using const_reverse_iterator = std::reverse_iterator<const_iterator>; 182*635a8641SAndroid Build Coastguard Worker static constexpr index_type extent = Extent; 183*635a8641SAndroid Build Coastguard Worker 184*635a8641SAndroid Build Coastguard Worker // [span.cons], span constructors, copy, assignment, and destructor 185*635a8641SAndroid Build Coastguard Worker constexpr span() noexcept : data_(nullptr), size_(0) { 186*635a8641SAndroid Build Coastguard Worker static_assert(Extent == dynamic_extent || Extent == 0, "Invalid Extent"); 187*635a8641SAndroid Build Coastguard Worker } 188*635a8641SAndroid Build Coastguard Worker 189*635a8641SAndroid Build Coastguard Worker constexpr span(T* data, size_t size) noexcept : data_(data), size_(size) { 190*635a8641SAndroid Build Coastguard Worker CHECK(Extent == dynamic_extent || Extent == size); 191*635a8641SAndroid Build Coastguard Worker } 192*635a8641SAndroid Build Coastguard Worker 193*635a8641SAndroid Build Coastguard Worker // Artificially templatized to break ambiguity for span(ptr, 0). 194*635a8641SAndroid Build Coastguard Worker template <typename = void> 195*635a8641SAndroid Build Coastguard Worker constexpr span(T* begin, T* end) noexcept : span(begin, end - begin) { 196*635a8641SAndroid Build Coastguard Worker // Note: CHECK_LE is not constexpr, hence regular CHECK must be used. 197*635a8641SAndroid Build Coastguard Worker CHECK(begin <= end); 198*635a8641SAndroid Build Coastguard Worker } 199*635a8641SAndroid Build Coastguard Worker 200*635a8641SAndroid Build Coastguard Worker template < 201*635a8641SAndroid Build Coastguard Worker size_t N, 202*635a8641SAndroid Build Coastguard Worker typename = internal::EnableIfSpanCompatibleArray<T (&)[N], N, T, Extent>> 203*635a8641SAndroid Build Coastguard Worker constexpr span(T (&array)[N]) noexcept : span(base::data(array), N) {} 204*635a8641SAndroid Build Coastguard Worker 205*635a8641SAndroid Build Coastguard Worker template < 206*635a8641SAndroid Build Coastguard Worker size_t N, 207*635a8641SAndroid Build Coastguard Worker typename = internal:: 208*635a8641SAndroid Build Coastguard Worker EnableIfSpanCompatibleArray<std::array<value_type, N>&, N, T, Extent>> 209*635a8641SAndroid Build Coastguard Worker constexpr span(std::array<value_type, N>& array) noexcept 210*635a8641SAndroid Build Coastguard Worker : span(base::data(array), N) {} 211*635a8641SAndroid Build Coastguard Worker 212*635a8641SAndroid Build Coastguard Worker template <size_t N, 213*635a8641SAndroid Build Coastguard Worker typename = internal::EnableIfSpanCompatibleArray< 214*635a8641SAndroid Build Coastguard Worker const std::array<value_type, N>&, 215*635a8641SAndroid Build Coastguard Worker N, 216*635a8641SAndroid Build Coastguard Worker T, 217*635a8641SAndroid Build Coastguard Worker Extent>> 218*635a8641SAndroid Build Coastguard Worker constexpr span(const std::array<value_type, N>& array) noexcept 219*635a8641SAndroid Build Coastguard Worker : span(base::data(array), N) {} 220*635a8641SAndroid Build Coastguard Worker 221*635a8641SAndroid Build Coastguard Worker // Conversion from a container that has compatible base::data() and integral 222*635a8641SAndroid Build Coastguard Worker // base::size(). 223*635a8641SAndroid Build Coastguard Worker template <typename Container, 224*635a8641SAndroid Build Coastguard Worker typename = internal::EnableIfSpanCompatibleContainer<Container&, T>> 225*635a8641SAndroid Build Coastguard Worker constexpr span(Container& container) noexcept 226*635a8641SAndroid Build Coastguard Worker : span(base::data(container), base::size(container)) {} 227*635a8641SAndroid Build Coastguard Worker 228*635a8641SAndroid Build Coastguard Worker template < 229*635a8641SAndroid Build Coastguard Worker typename Container, 230*635a8641SAndroid Build Coastguard Worker typename = internal::EnableIfSpanCompatibleContainer<const Container&, T>> 231*635a8641SAndroid Build Coastguard Worker span(const Container& container) noexcept 232*635a8641SAndroid Build Coastguard Worker : span(base::data(container), base::size(container)) {} 233*635a8641SAndroid Build Coastguard Worker 234*635a8641SAndroid Build Coastguard Worker constexpr span(const span& other) noexcept = default; 235*635a8641SAndroid Build Coastguard Worker 236*635a8641SAndroid Build Coastguard Worker // Conversions from spans of compatible types and extents: this allows a 237*635a8641SAndroid Build Coastguard Worker // span<T> to be seamlessly used as a span<const T>, but not the other way 238*635a8641SAndroid Build Coastguard Worker // around. If extent is not dynamic, OtherExtent has to be equal to Extent. 239*635a8641SAndroid Build Coastguard Worker template < 240*635a8641SAndroid Build Coastguard Worker typename U, 241*635a8641SAndroid Build Coastguard Worker size_t OtherExtent, 242*635a8641SAndroid Build Coastguard Worker typename = 243*635a8641SAndroid Build Coastguard Worker internal::EnableIfLegalSpanConversion<U, OtherExtent, T, Extent>> 244*635a8641SAndroid Build Coastguard Worker constexpr span(const span<U, OtherExtent>& other) 245*635a8641SAndroid Build Coastguard Worker : span(other.data(), other.size()) {} 246*635a8641SAndroid Build Coastguard Worker 247*635a8641SAndroid Build Coastguard Worker constexpr span& operator=(const span& other) noexcept = default; 248*635a8641SAndroid Build Coastguard Worker ~span() noexcept = default; 249*635a8641SAndroid Build Coastguard Worker 250*635a8641SAndroid Build Coastguard Worker // [span.sub], span subviews 251*635a8641SAndroid Build Coastguard Worker template <size_t Count> 252*635a8641SAndroid Build Coastguard Worker constexpr span<T, Count> first() const noexcept { 253*635a8641SAndroid Build Coastguard Worker static_assert(Extent == dynamic_extent || Count <= Extent, 254*635a8641SAndroid Build Coastguard Worker "Count must not exceed Extent"); 255*635a8641SAndroid Build Coastguard Worker CHECK(Extent != dynamic_extent || Count <= size()); 256*635a8641SAndroid Build Coastguard Worker return {data(), Count}; 257*635a8641SAndroid Build Coastguard Worker } 258*635a8641SAndroid Build Coastguard Worker 259*635a8641SAndroid Build Coastguard Worker template <size_t Count> 260*635a8641SAndroid Build Coastguard Worker constexpr span<T, Count> last() const noexcept { 261*635a8641SAndroid Build Coastguard Worker static_assert(Extent == dynamic_extent || Count <= Extent, 262*635a8641SAndroid Build Coastguard Worker "Count must not exceed Extent"); 263*635a8641SAndroid Build Coastguard Worker CHECK(Extent != dynamic_extent || Count <= size()); 264*635a8641SAndroid Build Coastguard Worker return {data() + (size() - Count), Count}; 265*635a8641SAndroid Build Coastguard Worker } 266*635a8641SAndroid Build Coastguard Worker 267*635a8641SAndroid Build Coastguard Worker template <size_t Offset, size_t Count = dynamic_extent> 268*635a8641SAndroid Build Coastguard Worker constexpr span<T, 269*635a8641SAndroid Build Coastguard Worker (Count != dynamic_extent 270*635a8641SAndroid Build Coastguard Worker ? Count 271*635a8641SAndroid Build Coastguard Worker : (Extent != dynamic_extent ? Extent - Offset 272*635a8641SAndroid Build Coastguard Worker : dynamic_extent))> 273*635a8641SAndroid Build Coastguard Worker subspan() const noexcept { 274*635a8641SAndroid Build Coastguard Worker static_assert(Extent == dynamic_extent || Offset <= Extent, 275*635a8641SAndroid Build Coastguard Worker "Offset must not exceed Extent"); 276*635a8641SAndroid Build Coastguard Worker static_assert(Extent == dynamic_extent || Count == dynamic_extent || 277*635a8641SAndroid Build Coastguard Worker Count <= Extent - Offset, 278*635a8641SAndroid Build Coastguard Worker "Count must not exceed Extent - Offset"); 279*635a8641SAndroid Build Coastguard Worker CHECK(Extent != dynamic_extent || Offset <= size()); 280*635a8641SAndroid Build Coastguard Worker CHECK(Extent != dynamic_extent || Count == dynamic_extent || 281*635a8641SAndroid Build Coastguard Worker Count <= size() - Offset); 282*635a8641SAndroid Build Coastguard Worker return {data() + Offset, Count != dynamic_extent ? Count : size() - Offset}; 283*635a8641SAndroid Build Coastguard Worker } 284*635a8641SAndroid Build Coastguard Worker 285*635a8641SAndroid Build Coastguard Worker constexpr span<T, dynamic_extent> first(size_t count) const noexcept { 286*635a8641SAndroid Build Coastguard Worker // Note: CHECK_LE is not constexpr, hence regular CHECK must be used. 287*635a8641SAndroid Build Coastguard Worker CHECK(count <= size()); 288*635a8641SAndroid Build Coastguard Worker return {data(), count}; 289*635a8641SAndroid Build Coastguard Worker } 290*635a8641SAndroid Build Coastguard Worker 291*635a8641SAndroid Build Coastguard Worker constexpr span<T, dynamic_extent> last(size_t count) const noexcept { 292*635a8641SAndroid Build Coastguard Worker // Note: CHECK_LE is not constexpr, hence regular CHECK must be used. 293*635a8641SAndroid Build Coastguard Worker CHECK(count <= size()); 294*635a8641SAndroid Build Coastguard Worker return {data() + (size() - count), count}; 295*635a8641SAndroid Build Coastguard Worker } 296*635a8641SAndroid Build Coastguard Worker 297*635a8641SAndroid Build Coastguard Worker constexpr span<T, dynamic_extent> subspan(size_t offset, 298*635a8641SAndroid Build Coastguard Worker size_t count = dynamic_extent) const 299*635a8641SAndroid Build Coastguard Worker noexcept { 300*635a8641SAndroid Build Coastguard Worker // Note: CHECK_LE is not constexpr, hence regular CHECK must be used. 301*635a8641SAndroid Build Coastguard Worker CHECK(offset <= size()); 302*635a8641SAndroid Build Coastguard Worker CHECK(count == dynamic_extent || count <= size() - offset); 303*635a8641SAndroid Build Coastguard Worker return {data() + offset, count != dynamic_extent ? count : size() - offset}; 304*635a8641SAndroid Build Coastguard Worker } 305*635a8641SAndroid Build Coastguard Worker 306*635a8641SAndroid Build Coastguard Worker // [span.obs], span observers 307*635a8641SAndroid Build Coastguard Worker constexpr size_t size() const noexcept { return size_; } 308*635a8641SAndroid Build Coastguard Worker constexpr size_t size_bytes() const noexcept { return size() * sizeof(T); } 309*635a8641SAndroid Build Coastguard Worker constexpr bool empty() const noexcept { return size() == 0; } 310*635a8641SAndroid Build Coastguard Worker 311*635a8641SAndroid Build Coastguard Worker // [span.elem], span element access 312*635a8641SAndroid Build Coastguard Worker constexpr T& operator[](size_t idx) const noexcept { 313*635a8641SAndroid Build Coastguard Worker // Note: CHECK_LT is not constexpr, hence regular CHECK must be used. 314*635a8641SAndroid Build Coastguard Worker CHECK(idx < size()); 315*635a8641SAndroid Build Coastguard Worker return *(data() + idx); 316*635a8641SAndroid Build Coastguard Worker } 317*635a8641SAndroid Build Coastguard Worker 318*635a8641SAndroid Build Coastguard Worker constexpr T& operator()(size_t idx) const noexcept { 319*635a8641SAndroid Build Coastguard Worker // Note: CHECK_LT is not constexpr, hence regular CHECK must be used. 320*635a8641SAndroid Build Coastguard Worker CHECK(idx < size()); 321*635a8641SAndroid Build Coastguard Worker return *(data() + idx); 322*635a8641SAndroid Build Coastguard Worker } 323*635a8641SAndroid Build Coastguard Worker 324*635a8641SAndroid Build Coastguard Worker constexpr T* data() const noexcept { return data_; } 325*635a8641SAndroid Build Coastguard Worker 326*635a8641SAndroid Build Coastguard Worker // [span.iter], span iterator support 327*635a8641SAndroid Build Coastguard Worker constexpr iterator begin() const noexcept { return data(); } 328*635a8641SAndroid Build Coastguard Worker constexpr iterator end() const noexcept { return data() + size(); } 329*635a8641SAndroid Build Coastguard Worker 330*635a8641SAndroid Build Coastguard Worker constexpr const_iterator cbegin() const noexcept { return begin(); } 331*635a8641SAndroid Build Coastguard Worker constexpr const_iterator cend() const noexcept { return end(); } 332*635a8641SAndroid Build Coastguard Worker 333*635a8641SAndroid Build Coastguard Worker constexpr reverse_iterator rbegin() const noexcept { 334*635a8641SAndroid Build Coastguard Worker return reverse_iterator(end()); 335*635a8641SAndroid Build Coastguard Worker } 336*635a8641SAndroid Build Coastguard Worker constexpr reverse_iterator rend() const noexcept { 337*635a8641SAndroid Build Coastguard Worker return reverse_iterator(begin()); 338*635a8641SAndroid Build Coastguard Worker } 339*635a8641SAndroid Build Coastguard Worker 340*635a8641SAndroid Build Coastguard Worker constexpr const_reverse_iterator crbegin() const noexcept { 341*635a8641SAndroid Build Coastguard Worker return const_reverse_iterator(cend()); 342*635a8641SAndroid Build Coastguard Worker } 343*635a8641SAndroid Build Coastguard Worker constexpr const_reverse_iterator crend() const noexcept { 344*635a8641SAndroid Build Coastguard Worker return const_reverse_iterator(cbegin()); 345*635a8641SAndroid Build Coastguard Worker } 346*635a8641SAndroid Build Coastguard Worker 347*635a8641SAndroid Build Coastguard Worker private: 348*635a8641SAndroid Build Coastguard Worker T* data_; 349*635a8641SAndroid Build Coastguard Worker size_t size_; 350*635a8641SAndroid Build Coastguard Worker }; 351*635a8641SAndroid Build Coastguard Worker 352*635a8641SAndroid Build Coastguard Worker // span<T, Extent>::extent can not be declared inline prior to C++17, hence this 353*635a8641SAndroid Build Coastguard Worker // definition is required. 354*635a8641SAndroid Build Coastguard Worker template <class T, size_t Extent> 355*635a8641SAndroid Build Coastguard Worker constexpr size_t span<T, Extent>::extent; 356*635a8641SAndroid Build Coastguard Worker 357*635a8641SAndroid Build Coastguard Worker // [span.comparison], span comparison operators 358*635a8641SAndroid Build Coastguard Worker // Relational operators. Equality is a element-wise comparison. 359*635a8641SAndroid Build Coastguard Worker template <typename T, size_t X, typename U, size_t Y> 360*635a8641SAndroid Build Coastguard Worker constexpr bool operator==(span<T, X> lhs, span<U, Y> rhs) noexcept { 361*635a8641SAndroid Build Coastguard Worker return std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend()); 362*635a8641SAndroid Build Coastguard Worker } 363*635a8641SAndroid Build Coastguard Worker 364*635a8641SAndroid Build Coastguard Worker template <typename T, size_t X, typename U, size_t Y> 365*635a8641SAndroid Build Coastguard Worker constexpr bool operator!=(span<T, X> lhs, span<U, Y> rhs) noexcept { 366*635a8641SAndroid Build Coastguard Worker return !(lhs == rhs); 367*635a8641SAndroid Build Coastguard Worker } 368*635a8641SAndroid Build Coastguard Worker 369*635a8641SAndroid Build Coastguard Worker template <typename T, size_t X, typename U, size_t Y> 370*635a8641SAndroid Build Coastguard Worker constexpr bool operator<(span<T, X> lhs, span<U, Y> rhs) noexcept { 371*635a8641SAndroid Build Coastguard Worker return std::lexicographical_compare(lhs.cbegin(), lhs.cend(), rhs.cbegin(), 372*635a8641SAndroid Build Coastguard Worker rhs.cend()); 373*635a8641SAndroid Build Coastguard Worker } 374*635a8641SAndroid Build Coastguard Worker 375*635a8641SAndroid Build Coastguard Worker template <typename T, size_t X, typename U, size_t Y> 376*635a8641SAndroid Build Coastguard Worker constexpr bool operator<=(span<T, X> lhs, span<U, Y> rhs) noexcept { 377*635a8641SAndroid Build Coastguard Worker return !(rhs < lhs); 378*635a8641SAndroid Build Coastguard Worker } 379*635a8641SAndroid Build Coastguard Worker 380*635a8641SAndroid Build Coastguard Worker template <typename T, size_t X, typename U, size_t Y> 381*635a8641SAndroid Build Coastguard Worker constexpr bool operator>(span<T, X> lhs, span<U, Y> rhs) noexcept { 382*635a8641SAndroid Build Coastguard Worker return rhs < lhs; 383*635a8641SAndroid Build Coastguard Worker } 384*635a8641SAndroid Build Coastguard Worker 385*635a8641SAndroid Build Coastguard Worker template <typename T, size_t X, typename U, size_t Y> 386*635a8641SAndroid Build Coastguard Worker constexpr bool operator>=(span<T, X> lhs, span<U, Y> rhs) noexcept { 387*635a8641SAndroid Build Coastguard Worker return !(lhs < rhs); 388*635a8641SAndroid Build Coastguard Worker } 389*635a8641SAndroid Build Coastguard Worker 390*635a8641SAndroid Build Coastguard Worker // [span.objectrep], views of object representation 391*635a8641SAndroid Build Coastguard Worker template <typename T, size_t X> 392*635a8641SAndroid Build Coastguard Worker span<const uint8_t, (X == dynamic_extent ? dynamic_extent : sizeof(T) * X)> 393*635a8641SAndroid Build Coastguard Worker as_bytes(span<T, X> s) noexcept { 394*635a8641SAndroid Build Coastguard Worker return {reinterpret_cast<const uint8_t*>(s.data()), s.size_bytes()}; 395*635a8641SAndroid Build Coastguard Worker } 396*635a8641SAndroid Build Coastguard Worker 397*635a8641SAndroid Build Coastguard Worker template <typename T, 398*635a8641SAndroid Build Coastguard Worker size_t X, 399*635a8641SAndroid Build Coastguard Worker typename = std::enable_if_t<!std::is_const<T>::value>> 400*635a8641SAndroid Build Coastguard Worker span<uint8_t, (X == dynamic_extent ? dynamic_extent : sizeof(T) * X)> 401*635a8641SAndroid Build Coastguard Worker as_writable_bytes(span<T, X> s) noexcept { 402*635a8641SAndroid Build Coastguard Worker return {reinterpret_cast<uint8_t*>(s.data()), s.size_bytes()}; 403*635a8641SAndroid Build Coastguard Worker } 404*635a8641SAndroid Build Coastguard Worker 405*635a8641SAndroid Build Coastguard Worker // Type-deducing helpers for constructing a span. 406*635a8641SAndroid Build Coastguard Worker template <typename T> 407*635a8641SAndroid Build Coastguard Worker constexpr span<T> make_span(T* data, size_t size) noexcept { 408*635a8641SAndroid Build Coastguard Worker return {data, size}; 409*635a8641SAndroid Build Coastguard Worker } 410*635a8641SAndroid Build Coastguard Worker 411*635a8641SAndroid Build Coastguard Worker template <typename T> 412*635a8641SAndroid Build Coastguard Worker constexpr span<T> make_span(T* begin, T* end) noexcept { 413*635a8641SAndroid Build Coastguard Worker return {begin, end}; 414*635a8641SAndroid Build Coastguard Worker } 415*635a8641SAndroid Build Coastguard Worker 416*635a8641SAndroid Build Coastguard Worker template <typename T, size_t N> 417*635a8641SAndroid Build Coastguard Worker constexpr span<T, N> make_span(T (&array)[N]) noexcept { 418*635a8641SAndroid Build Coastguard Worker return array; 419*635a8641SAndroid Build Coastguard Worker } 420*635a8641SAndroid Build Coastguard Worker 421*635a8641SAndroid Build Coastguard Worker template <typename T, size_t N> 422*635a8641SAndroid Build Coastguard Worker constexpr span<T, N> make_span(std::array<T, N>& array) noexcept { 423*635a8641SAndroid Build Coastguard Worker return array; 424*635a8641SAndroid Build Coastguard Worker } 425*635a8641SAndroid Build Coastguard Worker 426*635a8641SAndroid Build Coastguard Worker template <typename T, size_t N> 427*635a8641SAndroid Build Coastguard Worker constexpr span<const T, N> make_span(const std::array<T, N>& array) noexcept { 428*635a8641SAndroid Build Coastguard Worker return array; 429*635a8641SAndroid Build Coastguard Worker } 430*635a8641SAndroid Build Coastguard Worker 431*635a8641SAndroid Build Coastguard Worker template <typename Container, 432*635a8641SAndroid Build Coastguard Worker typename T = typename Container::value_type, 433*635a8641SAndroid Build Coastguard Worker typename = internal::EnableIfSpanCompatibleContainer<Container&, T>> 434*635a8641SAndroid Build Coastguard Worker constexpr span<T> make_span(Container& container) noexcept { 435*635a8641SAndroid Build Coastguard Worker return container; 436*635a8641SAndroid Build Coastguard Worker } 437*635a8641SAndroid Build Coastguard Worker 438*635a8641SAndroid Build Coastguard Worker template < 439*635a8641SAndroid Build Coastguard Worker typename Container, 440*635a8641SAndroid Build Coastguard Worker typename T = const typename Container::value_type, 441*635a8641SAndroid Build Coastguard Worker typename = internal::EnableIfSpanCompatibleContainer<const Container&, T>> 442*635a8641SAndroid Build Coastguard Worker constexpr span<T> make_span(const Container& container) noexcept { 443*635a8641SAndroid Build Coastguard Worker return container; 444*635a8641SAndroid Build Coastguard Worker } 445*635a8641SAndroid Build Coastguard Worker 446*635a8641SAndroid Build Coastguard Worker template <typename T, size_t X> 447*635a8641SAndroid Build Coastguard Worker constexpr span<T, X> make_span(const span<T, X>& span) noexcept { 448*635a8641SAndroid Build Coastguard Worker return span; 449*635a8641SAndroid Build Coastguard Worker } 450*635a8641SAndroid Build Coastguard Worker 451*635a8641SAndroid Build Coastguard Worker } // namespace base 452*635a8641SAndroid Build Coastguard Worker 453*635a8641SAndroid Build Coastguard Worker #endif // BASE_CONTAINERS_SPAN_H_ 454