Title: [279062] trunk/Source/WTF
Revision
279062
Author
wei...@apple.com
Date
2021-06-20 19:51:33 -0700 (Sun, 20 Jun 2021)

Log Message

Replace Span implementation with one from libc++, which is more spec complient
https://bugs.webkit.org/show_bug.cgi?id=227197

Reviewed by Darin Adler.

* wtf/Span.h:
The tcb span implementation had some SFINAE issues when converting containers
had data() and size() member functions but were not span compatible that were
causing failures. Rather than trying to fix those, this adopts a modified version
of the libc++ span implementation which is more up-to-date.

To fix MSVC compile issues, the as_bytes/as_writable_bytes functions have been
re-implemented to not work around a compile issue seen where using the dynamic_extent
specicialization from the static extent specicialization was failing to compile.

Modified Paths

Removed Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (279061 => 279062)


--- trunk/Source/WTF/ChangeLog	2021-06-21 01:19:50 UTC (rev 279061)
+++ trunk/Source/WTF/ChangeLog	2021-06-21 02:51:33 UTC (rev 279062)
@@ -1,3 +1,20 @@
+2021-06-20  Sam Weinig  <wei...@apple.com>
+
+        Replace Span implementation with one from libc++, which is more spec complient
+        https://bugs.webkit.org/show_bug.cgi?id=227197
+
+        Reviewed by Darin Adler.
+
+        * wtf/Span.h:
+        The tcb span implementation had some SFINAE issues when converting containers
+        had data() and size() member functions but were not span compatible that were
+        causing failures. Rather than trying to fix those, this adopts a modified version
+        of the libc++ span implementation which is more up-to-date.
+
+        To fix MSVC compile issues, the as_bytes/as_writable_bytes functions have been
+        re-implemented to not work around a compile issue seen where using the dynamic_extent
+        specicialization from the static extent specicialization was failing to compile.
+
 2021-06-20  Wenson Hsieh  <wenson_hs...@apple.com>
 
         [macOS] Rename WKVisualSearchPreviewController to WKQuickLookPreviewController

Deleted: trunk/Source/WTF/LICENSE_1_0-Boost.txt (279061 => 279062)


--- trunk/Source/WTF/LICENSE_1_0-Boost.txt	2021-06-21 01:19:50 UTC (rev 279061)
+++ trunk/Source/WTF/LICENSE_1_0-Boost.txt	2021-06-21 02:51:33 UTC (rev 279062)
@@ -1,23 +0,0 @@
-Boost Software License - Version 1.0 - August 17th, 2003
-
-Permission is hereby granted, free of charge, to any person or organization
-obtaining a copy of the software and accompanying documentation covered by
-this license (the "Software") to use, reproduce, display, distribute,
-execute, and transmit the Software, and to prepare derivative works of the
-Software, and to permit third-parties to whom the Software is furnished to
-do so, all subject to the following:
-
-The copyright notices in the Software and this entire statement, including
-the above license grant, this restriction and the following disclaimer,
-must be included in all copies of the Software, in whole or in part, and
-all derivative works of the Software, unless such copies or derivative
-works are solely in the form of machine-executable object code generated by
-a source language processor.
-
-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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
-SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
-FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.

Modified: trunk/Source/WTF/wtf/Span.h (279061 => 279062)


--- trunk/Source/WTF/wtf/Span.h	2021-06-21 01:19:50 UTC (rev 279061)
+++ trunk/Source/WTF/wtf/Span.h	2021-06-21 02:51:33 UTC (rev 279062)
@@ -1,620 +1,458 @@
-//              Copyright Tristan Brindle 2018.
-// Distributed under the Boost Software License, Version 1.0.
-//    (See accompanying file ../LICENSE_1_0-Boost.txt or copy at
-//          https://www.boost.org/LICENSE_1_0.txt)
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
 
-// This is an implementation of C++20's std::span http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/n4820.pdf
+#ifndef _WTF_LIBCPP_SPAN
+#define _WTF_LIBCPP_SPAN
 
-// This has been modified from the original version to make the following changes:
-//   Renamed tcb::span to WTF::Span.
-//   Renamed tcb::as_bytes to WTF::asBytes.
-//   Renamed tcb::as_writable_bytes to WTF::asWritableBytes.
+// Imports a copy of <span> from e892705d74c7366a1404a3b3471001edaa7659f8 of the
+// libc++ project (https://github.com/llvm/llvm-project.git) and modifies it to
+// work on top of any standard library implementation.
+//
+// - Renames macros with _LIBCPP_ prefix to use the prefix _WTF_LIBCPP_
+// - Renames std::span to WTF::Span
+// - Renames std::as_bytes/std::as_writable_bytes to WTF::asBytes/WTF::asWritableBytes.
+// - Stop #including internal libc++ headers.
+// - Remove check for > c++17.
+// - Remove push/pop availability of min/max macros.
 
-#ifndef TCB_SPAN_HPP_INCLUDED
-#define TCB_SPAN_HPP_INCLUDED
+#include <array>        // for array
+#include <cstddef>      // for byte
+#include <iterator>     // for iterators
+#include <type_traits>  // for remove_cv, etc
 
-#include <array>
-#include <cstddef>
-#include <cstdint>
-#include <type_traits>
+// Adds some macro defines usually defined in __config.
 
-#ifndef TCB_SPAN_NO_EXCEPTIONS
-// Attempt to discover whether we're being compiled with exception support
-#if !(defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND))
-#define TCB_SPAN_NO_EXCEPTIONS
-#endif
-#endif
+#define _WTF_LIBCPP_ABI_SPAN_POINTER_ITERATORS
+#define _WTF_LIBCPP_BEGIN_NAMESPACE namespace WTF {
+#define _WTF_LIBCPP_DEBUG_LEVEL 0
+#define _WTF_LIBCPP_END_NAMESPACE  }
+#define _WTF_LIBCPP_HAS_NO_RANGES
+#define _WTF_LIBCPP_INLINE_VISIBILITY
+#define _WTF_LIBCPP_TEMPLATE_VIS
+#define _WTF_VSTD std
 
-#ifndef TCB_SPAN_NO_EXCEPTIONS
-#include <cstdio>
-#include <stdexcept>
-#endif
+#include <wtf/Assertions.h>
+#define _WTF_LIBCPP_ASSERT ASSERT
 
-// Various feature test macros
+_WTF_LIBCPP_BEGIN_NAMESPACE
 
-#ifndef TCB_SPAN_NAMESPACE_NAME
-#define TCB_SPAN_NAMESPACE_NAME WTF
-#endif
+inline constexpr std::size_t dynamic_extent = std::numeric_limits<std::size_t>::max();
+template <typename _Tp, std::size_t _Extent = dynamic_extent> class Span;
 
-#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
-#define TCB_SPAN_HAVE_CPP17
-#endif
 
-#if __cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
-#define TCB_SPAN_HAVE_CPP14
-#endif
+template <class _Tp>
+struct __is_span_impl : public std::false_type {};
 
-namespace TCB_SPAN_NAMESPACE_NAME {
+template <class _Tp, std::size_t _Extent>
+struct __is_span_impl<Span<_Tp, _Extent>> : public std::true_type {};
 
-// Establish default contract checking behavior
-#if !defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION) &&                          \
-    !defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION) &&                      \
-    !defined(TCB_SPAN_NO_CONTRACT_CHECKING)
-#if defined(NDEBUG) || !defined(TCB_SPAN_HAVE_CPP14)
-#define TCB_SPAN_NO_CONTRACT_CHECKING
-#else
-#define TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION
-#endif
-#endif
+template <class _Tp>
+struct __is_span : public __is_span_impl<std::remove_cv_t<_Tp>> {};
 
-#if defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION)
-struct contract_violation_error : std::logic_error {
-    explicit contract_violation_error(const char* msg) : std::logic_error(msg)
-    {}
-};
+template <class _Tp>
+struct __is_std_array_impl : public std::false_type {};
 
-inline void contract_violation(const char* msg)
-{
-    throw contract_violation_error(msg);
-}
+template <class _Tp, std::size_t _Sz>
+struct __is_std_array_impl<std::array<_Tp, _Sz>> : public std::true_type {};
 
-#elif defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION)
-[[noreturn]] inline void contract_violation(const char* /*unused*/)
-{
-    std::terminate();
-}
-#endif
+template <class _Tp>
+struct __is_std_array : public __is_std_array_impl<std::remove_cv_t<_Tp>> {};
 
-#if !defined(TCB_SPAN_NO_CONTRACT_CHECKING)
-#define TCB_SPAN_STRINGIFY(cond) #cond
-#define TCB_SPAN_EXPECT(cond)                                                  \
-    cond ? (void) 0 : contract_violation("Expected " TCB_SPAN_STRINGIFY(cond))
-#else
-#define TCB_SPAN_EXPECT(cond)
-#endif
+template <class _Tp, class _ElementType, class = void>
+struct __is_span_compatible_container : public std::false_type {};
 
-#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_inline_variables)
-#define TCB_SPAN_INLINE_VAR inline
-#else
-#define TCB_SPAN_INLINE_VAR
-#endif
+template <class _Tp, class _ElementType>
+struct __is_span_compatible_container<_Tp, _ElementType,
+        std::void_t<
+        // is not a specialization of Span
+            typename std::enable_if<!__is_span<_Tp>::value, nullptr_t>::type,
+        // is not a specialization of array
+            typename std::enable_if<!__is_std_array<_Tp>::value, nullptr_t>::type,
+        // sd::is_array_v<Container> is false,
+            typename std::enable_if<!std::is_array_v<_Tp>, nullptr_t>::type,
+        // std::data(cont) and std::size(cont) are well formed
+            decltype(std::data(std::declval<_Tp>())),
+            decltype(std::size(std::declval<_Tp>())),
+        // remove_pointer_t<decltype(data(cont))>(*)[] is convertible to ElementType(*)[]
+            typename std::enable_if<
+                std::is_convertible_v<std::remove_pointer_t<decltype(std::data(std::declval<_Tp &>()))>(*)[],
+                                 _ElementType(*)[]>,
+                nullptr_t>::type
+        >>
+    : public std::true_type {};
 
-#if defined(TCB_SPAN_HAVE_CPP14) ||                                            \
-    (defined(__cpp_constexpr) && __cpp_constexpr >= 201304)
-#define TCB_SPAN_HAVE_CPP14_CONSTEXPR
-#endif
 
-#if defined(TCB_SPAN_HAVE_CPP14_CONSTEXPR)
-#define TCB_SPAN_CONSTEXPR14 constexpr
+template <typename _Tp, std::size_t _Extent>
+class _WTF_LIBCPP_TEMPLATE_VIS Span {
+public:
+//  constants and types
+    using element_type           = _Tp;
+    using value_type             = std::remove_cv_t<_Tp>;
+    using size_type              = std::size_t;
+    using difference_type        = std::ptrdiff_t;
+    using pointer                = _Tp *;
+    using const_pointer          = const _Tp *;
+    using reference              = _Tp &;
+    using const_reference        = const _Tp &;
+#if (_WTF_LIBCPP_DEBUG_LEVEL == 2) || defined(_WTF_LIBCPP_ABI_SPAN_POINTER_ITERATORS)
+    using iterator               = pointer;
 #else
-#define TCB_SPAN_CONSTEXPR14
+    using iterator               = __wrap_iter<pointer>;
 #endif
+    using reverse_iterator       = _WTF_VSTD::reverse_iterator<iterator>;
 
-#if defined(TCB_SPAN_HAVE_CPP14_CONSTEXPR) &&                                  \
-    (!defined(_MSC_VER) || _MSC_VER > 1900)
-#define TCB_SPAN_CONSTEXPR_ASSIGN constexpr
-#else
-#define TCB_SPAN_CONSTEXPR_ASSIGN
-#endif
+    static constexpr size_type extent = _Extent;
 
-#if defined(TCB_SPAN_NO_CONTRACT_CHECKING)
-#define TCB_SPAN_CONSTEXPR11 constexpr
-#else
-#define TCB_SPAN_CONSTEXPR11 TCB_SPAN_CONSTEXPR14
-#endif
+// [span.cons], span constructors, copy, assignment, and destructor
+    template <std::size_t _Sz = _Extent, std::enable_if_t<_Sz == 0, nullptr_t> = nullptr>
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr Span() noexcept : __data{nullptr} {}
 
-#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_deduction_guides)
-#define TCB_SPAN_HAVE_DEDUCTION_GUIDES
-#endif
+    constexpr Span           (const Span&) noexcept = default;
+    constexpr Span& operator=(const Span&) noexcept = default;
 
-#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_byte)
-#define TCB_SPAN_HAVE_STD_BYTE
-#endif
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr explicit Span(pointer __ptr, size_type __count) : __data{__ptr}
+        { (void)__count; _WTF_LIBCPP_ASSERT(_Extent == __count, "size mismatch in Span's constructor (ptr, len)"); }
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr explicit Span(pointer __f, pointer __l) : __data{__f}
+        { (void)__l;     _WTF_LIBCPP_ASSERT(_Extent == std::distance(__f, __l), "size mismatch in Span's constructor (ptr, ptr)"); }
 
-#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_array_constexpr)
-#define TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC
-#endif
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr Span(element_type (&__arr)[_Extent])          noexcept : __data{__arr} {}
 
-#if defined(TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC)
-#define TCB_SPAN_ARRAY_CONSTEXPR constexpr
-#else
-#define TCB_SPAN_ARRAY_CONSTEXPR
-#endif
+    template <class _OtherElementType,
+              std::enable_if_t<std::is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr>
+    _WTF_LIBCPP_INLINE_VISIBILITY
+    constexpr Span(std::array<_OtherElementType, _Extent>& __arr) noexcept : __data{__arr.data()} {}
 
-#ifdef TCB_SPAN_HAVE_STD_BYTE
-using byte = std::byte;
-#else
-using byte = unsigned char;
-#endif
+    template <class _OtherElementType,
+              std::enable_if_t<std::is_convertible_v<const _OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr>
+    _WTF_LIBCPP_INLINE_VISIBILITY
+    constexpr Span(const std::array<_OtherElementType, _Extent>& __arr) noexcept : __data{__arr.data()} {}
 
-#if defined(TCB_SPAN_HAVE_CPP17)
-#define TCB_SPAN_NODISCARD [[nodiscard]]
-#else
-#define TCB_SPAN_NODISCARD
-#endif
+    template <class _Container>
+    _WTF_LIBCPP_INLINE_VISIBILITY
+        constexpr explicit Span(      _Container& __c,
+            std::enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr)
+        : __data{_WTF_VSTD::data(__c)} {
+            _WTF_LIBCPP_ASSERT(_Extent == _WTF_VSTD::size(__c), "size mismatch in Span's constructor (range)");
+        }
 
-TCB_SPAN_INLINE_VAR constexpr std::size_t dynamic_extent = SIZE_MAX;
+    template <class _Container>
+    _WTF_LIBCPP_INLINE_VISIBILITY
+        constexpr explicit Span(const _Container& __c,
+            std::enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr)
+        : __data{_WTF_VSTD::data(__c)} {
+            _WTF_LIBCPP_ASSERT(_Extent == _WTF_VSTD::size(__c), "size mismatch in Span's constructor (range)");
+        }
 
-template <typename ElementType, std::size_t Extent = dynamic_extent>
-class Span;
+    template <class _OtherElementType>
+    _WTF_LIBCPP_INLINE_VISIBILITY
+        constexpr Span(const Span<_OtherElementType, _Extent>& __other,
+                       std::enable_if_t<
+                          std::is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
+                          nullptr_t> = nullptr)
+        : __data{__other.data()} {}
 
-namespace detail {
+    template <class _OtherElementType>
+    _WTF_LIBCPP_INLINE_VISIBILITY
+        constexpr explicit Span(const Span<_OtherElementType>& __other,
+                       std::enable_if_t<
+                          std::is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
+                          nullptr_t> = nullptr) noexcept
+        : __data{__other.data()} { _WTF_LIBCPP_ASSERT(_Extent == __other.size(), "size mismatch in Span's constructor (other Span)"); }
 
-template <typename E, std::size_t S>
-struct span_storage {
-    constexpr span_storage() noexcept = default;
 
-    constexpr span_storage(E* p_ptr, std::size_t /*unused*/) noexcept
-       : ptr(p_ptr)
-    {}
+//  ~Span() noexcept = default;
 
-    E* ptr = nullptr;
-    static constexpr std::size_t size = S;
-};
+    template <std::size_t _Count>
+    _WTF_LIBCPP_INLINE_VISIBILITY
+    constexpr Span<element_type, _Count> first() const noexcept
+    {
+        static_assert(_Count <= _Extent, "Count out of range in Span::first()");
+        return Span<element_type, _Count>{data(), _Count};
+    }
 
-template <typename E>
-struct span_storage<E, dynamic_extent> {
-    constexpr span_storage() noexcept = default;
+    template <std::size_t _Count>
+    _WTF_LIBCPP_INLINE_VISIBILITY
+    constexpr Span<element_type, _Count> last() const noexcept
+    {
+        static_assert(_Count <= _Extent, "Count out of range in Span::last()");
+        return Span<element_type, _Count>{data() + size() - _Count, _Count};
+    }
 
-    constexpr span_storage(E* p_ptr, std::size_t p_size) noexcept
-        : ptr(p_ptr), size(p_size)
-    {}
+    _WTF_LIBCPP_INLINE_VISIBILITY
+    constexpr Span<element_type, dynamic_extent> first(size_type __count) const noexcept
+    {
+        _WTF_LIBCPP_ASSERT(__count <= size(), "Count out of range in Span::first(count)");
+        return {data(), __count};
+    }
 
-    E* ptr = nullptr;
-    std::size_t size = 0;
-};
+    _WTF_LIBCPP_INLINE_VISIBILITY
+    constexpr Span<element_type, dynamic_extent> last(size_type __count) const noexcept
+    {
+        _WTF_LIBCPP_ASSERT(__count <= size(), "Count out of range in Span::last(count)");
+        return {data() + size() - __count, __count};
+    }
 
-// Reimplementation of C++17 std::size() and std::data()
-#if defined(TCB_SPAN_HAVE_CPP17) ||                                            \
-    defined(__cpp_lib_nonmember_container_access)
-using std::data;
-using std::size;
-#else
-template <class C>
-constexpr auto size(const C& c) -> decltype(c.size())
-{
-    return c.size();
-}
+    template <std::size_t _Offset, std::size_t _Count = dynamic_extent>
+    _WTF_LIBCPP_INLINE_VISIBILITY
+    constexpr auto subspan() const noexcept
+        -> Span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset>
+    {
+        static_assert(_Offset <= _Extent, "Offset out of range in Span::subspan()");
+        static_assert(_Count == dynamic_extent || _Count <= _Extent - _Offset, "Offset + count out of range in Span::subspan()");
 
-template <class T, std::size_t N>
-constexpr std::size_t size(const T (&)[N]) noexcept
-{
-    return N;
-}
+        using _ReturnType = Span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset>;
+        return _ReturnType{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
+    }
 
-template <class C>
-constexpr auto data(C& c) -> decltype(c.data())
-{
-    return c.data();
-}
 
-template <class C>
-constexpr auto data(const C& c) -> decltype(c.data())
-{
-    return c.data();
-}
+    _WTF_LIBCPP_INLINE_VISIBILITY
+    constexpr Span<element_type, dynamic_extent>
+       subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept
+    {
+        _WTF_LIBCPP_ASSERT(__offset <= size(), "Offset out of range in Span::subspan(offset, count)");
+        _WTF_LIBCPP_ASSERT(__count  <= size() || __count == dynamic_extent, "Count out of range in Span::subspan(offset, count)");
+        if (__count == dynamic_extent)
+            return {data() + __offset, size() - __offset};
+        _WTF_LIBCPP_ASSERT(__count <= size() - __offset, "Offset + count out of range in Span::subspan(offset, count)");
+        return {data() + __offset, __count};
+    }
 
-template <class T, std::size_t N>
-constexpr T* data(T (&array)[N]) noexcept
-{
-    return array;
-}
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr size_type size()       const noexcept { return _Extent; }
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr size_type size_bytes() const noexcept { return _Extent * sizeof(element_type); }
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr bool empty()           const noexcept { return _Extent == 0; }
 
-template <class E>
-constexpr const E* data(std::initializer_list<E> il) noexcept
-{
-    return il.begin();
-}
-#endif // TCB_SPAN_HAVE_CPP17
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr reference operator[](size_type __idx) const noexcept
+    {
+        _WTF_LIBCPP_ASSERT(__idx < size(), "Span<T,N>[] index out of bounds");
+        return __data[__idx];
+    }
 
-#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_void_t)
-using std::void_t;
-#else
-template <typename...>
-using void_t = void;
-#endif
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept
+    {
+        _WTF_LIBCPP_ASSERT(!empty(), "Span<T, N>::front() on empty Span");
+        return __data[0];
+    }
 
-template <typename T>
-using uncvref_t =
-    typename std::remove_cv<typename std::remove_reference<T>::type>::type;
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr reference back() const noexcept
+    {
+        _WTF_LIBCPP_ASSERT(!empty(), "Span<T, N>::back() on empty Span");
+        return __data[size()-1];
+    }
 
-template <typename>
-struct is_span : std::false_type {};
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr pointer data()                         const noexcept { return __data; }
 
-template <typename T, std::size_t S>
-struct is_span<Span<T, S>> : std::true_type {};
+// [span.iter], Span iterator support
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr iterator                 begin() const noexcept { return iterator(data()); }
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr iterator                   end() const noexcept { return iterator(data() + size()); }
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator        rbegin() const noexcept { return reverse_iterator(end()); }
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator          rend() const noexcept { return reverse_iterator(begin()); }
 
-template <typename>
-struct is_std_array : std::false_type {};
+private:
+    pointer    __data;
 
-template <typename T, std::size_t N>
-struct is_std_array<std::array<T, N>> : std::true_type {};
-
-template <typename, typename = void>
-struct has_size_and_data : std::false_type {};
-
-template <typename T>
-struct has_size_and_data<T, void_t<decltype(detail::size(std::declval<T>())),
-                                   decltype(detail::data(std::declval<T>()))>>
-    : std::true_type {};
-
-template <typename C, typename U = uncvref_t<C>>
-struct is_container {
-    static constexpr bool value =
-        !is_span<U>::value && !is_std_array<U>::value &&
-        !std::is_array<U>::value && has_size_and_data<C>::value;
 };
 
-template <typename T>
-using remove_pointer_t = typename std::remove_pointer<T>::type;
 
-template <typename, typename, typename = void>
-struct is_container_element_type_compatible : std::false_type {};
+template <typename _Tp>
+class _WTF_LIBCPP_TEMPLATE_VIS Span<_Tp, dynamic_extent> {
+private:
 
-template <typename T, typename E>
-struct is_container_element_type_compatible<
-    T, E,
-    typename std::enable_if<
-        !std::is_same<typename std::remove_cv<decltype(
-                          detail::data(std::declval<T>()))>::type,
-                      void>::value>::type>
-    : std::is_convertible<
-          remove_pointer_t<decltype(detail::data(std::declval<T>()))> (*)[],
-          E (*)[]> {};
-
-template <typename, typename = size_t>
-struct is_complete : std::false_type {};
-
-template <typename T>
-struct is_complete<T, decltype(sizeof(T))> : std::true_type {};
-
-} // namespace detail
-
-template <typename ElementType, std::size_t Extent>
-class Span {
-    static_assert(std::is_object<ElementType>::value,
-                  "A Span's ElementType must be an object type (not a "
-                  "reference type or void)");
-    static_assert(detail::is_complete<ElementType>::value,
-                  "A Span's ElementType must be a complete type (not a forward "
-                  "declaration)");
-    static_assert(!std::is_abstract<ElementType>::value,
-                  "A Span's ElementType cannot be an abstract class type");
-
-    using storage_type = detail::span_storage<ElementType, Extent>;
-
 public:
-    // constants and types
-    using element_type = ElementType;
-    using value_type = typename std::remove_cv<ElementType>::type;
-    using size_type = std::size_t;
-    using difference_type = std::ptrdiff_t;
-    using pointer = element_type*;
-    using const_pointer = const element_type*;
-    using reference = element_type&;
-    using const_reference = const element_type&;
-    using iterator = pointer;
-    using reverse_iterator = std::reverse_iterator<iterator>;
+//  constants and types
+    using element_type           = _Tp;
+    using value_type             = std::remove_cv_t<_Tp>;
+    using size_type              = std::size_t;
+    using difference_type        = std::ptrdiff_t;
+    using pointer                = _Tp *;
+    using const_pointer          = const _Tp *;
+    using reference              = _Tp &;
+    using const_reference        = const _Tp &;
+#if (_WTF_LIBCPP_DEBUG_LEVEL == 2) || defined(_WTF_LIBCPP_ABI_SPAN_POINTER_ITERATORS)
+    using iterator               = pointer;
+#else
+    using iterator               = __wrap_iter<pointer>;
+#endif
+    using reverse_iterator       = _WTF_VSTD::reverse_iterator<iterator>;
 
-    static constexpr size_type extent = Extent;
+    static constexpr size_type extent = dynamic_extent;
 
-    // [span.cons], Span constructors, copy, assignment, and destructor
-    template <
-        std::size_t E = Extent,
-        typename std::enable_if<(E == dynamic_extent || E <= 0), int>::type = 0>
-    constexpr Span() noexcept
-    {}
+// [span.cons], Span constructors, copy, assignment, and destructor
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr Span() noexcept : __data{nullptr}, __size{0} {}
 
-    TCB_SPAN_CONSTEXPR11 Span(pointer ptr, size_type count)
-        : storage_(ptr, count)
-    {
-        TCB_SPAN_EXPECT(extent == dynamic_extent || count == extent);
-    }
+    constexpr Span           (const Span&) noexcept = default;
+    constexpr Span& operator=(const Span&) noexcept = default;
 
-    TCB_SPAN_CONSTEXPR11 Span(pointer first_elem, pointer last_elem)
-        : storage_(first_elem, last_elem - first_elem)
-    {
-        TCB_SPAN_EXPECT(extent == dynamic_extent ||
-                        last_elem - first_elem ==
-                            static_cast<std::ptrdiff_t>(extent));
-    }
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr Span(pointer __ptr, size_type __count) : __data{__ptr}, __size{__count} {}
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr Span(pointer __f, pointer __l) : __data{__f}, __size{static_cast<std::size_t>(std::distance(__f, __l))} {}
 
-    template <std::size_t N, std::size_t E = Extent,
-              typename std::enable_if<
-                  (E == dynamic_extent || N == E) &&
-                      detail::is_container_element_type_compatible<
-                          element_type (&)[N], ElementType>::value,
-                  int>::type = 0>
-    constexpr Span(element_type (&arr)[N]) noexcept : storage_(arr, N)
-    {}
+    template <std::size_t _Sz>
+    _WTF_LIBCPP_INLINE_VISIBILITY
+    constexpr Span(element_type (&__arr)[_Sz])          noexcept : __data{__arr}, __size{_Sz} {}
 
-    template <std::size_t N, std::size_t E = Extent,
-              typename std::enable_if<
-                  (E == dynamic_extent || N == E) &&
-                      detail::is_container_element_type_compatible<
-                          std::array<value_type, N>&, ElementType>::value,
-                  int>::type = 0>
-    TCB_SPAN_ARRAY_CONSTEXPR Span(std::array<value_type, N>& arr) noexcept
-        : storage_(arr.data(), N)
-    {}
+    template <class _OtherElementType, std::size_t _Sz,
+              std::enable_if_t<std::is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr>
+    _WTF_LIBCPP_INLINE_VISIBILITY
+    constexpr Span(std::array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
 
-    template <std::size_t N, std::size_t E = Extent,
-              typename std::enable_if<
-                  (E == dynamic_extent || N == E) &&
-                      detail::is_container_element_type_compatible<
-                          const std::array<value_type, N>&, ElementType>::value,
-                  int>::type = 0>
-    TCB_SPAN_ARRAY_CONSTEXPR Span(const std::array<value_type, N>& arr) noexcept
-        : storage_(arr.data(), N)
-    {}
+    template <class _OtherElementType, std::size_t _Sz,
+              std::enable_if_t<std::is_convertible_v<const _OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr>
+    _WTF_LIBCPP_INLINE_VISIBILITY
+    constexpr Span(const std::array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
 
-    template <
-        typename Container, std::size_t E = Extent,
-        typename std::enable_if<
-            E == dynamic_extent && detail::is_container<Container>::value &&
-                detail::is_container_element_type_compatible<
-                    Container&, ElementType>::value,
-            int>::type = 0>
-    constexpr Span(Container& cont)
-        : storage_(detail::data(cont), detail::size(cont))
-    {}
+    template <class _Container>
+    _WTF_LIBCPP_INLINE_VISIBILITY
+        constexpr Span(      _Container& __c,
+            std::enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr)
+        : __data{_WTF_VSTD::data(__c)}, __size{(size_type) _WTF_VSTD::size(__c)} {}
 
-    template <
-        typename Container, std::size_t E = Extent,
-        typename std::enable_if<
-            E == dynamic_extent && detail::is_container<Container>::value &&
-                detail::is_container_element_type_compatible<
-                    const Container&, ElementType>::value,
-            int>::type = 0>
-    constexpr Span(const Container& cont)
-        : storage_(detail::data(cont), detail::size(cont))
-    {}
+    template <class _Container>
+    _WTF_LIBCPP_INLINE_VISIBILITY
+        constexpr Span(const _Container& __c,
+            std::enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr)
+        : __data{_WTF_VSTD::data(__c)}, __size{(size_type) _WTF_VSTD::size(__c)} {}
 
-    constexpr Span(const Span& other) noexcept = default;
 
-    template <typename OtherElementType, std::size_t OtherExtent,
-              typename std::enable_if<
-                  (Extent == OtherExtent || Extent == dynamic_extent) &&
-                      std::is_convertible<OtherElementType (*)[],
-                                          ElementType (*)[]>::value,
-                  int>::type = 0>
-    constexpr Span(const Span<OtherElementType, OtherExtent>& other) noexcept
-        : storage_(other.data(), other.size())
-    {}
+    template <class _OtherElementType, std::size_t _OtherExtent>
+    _WTF_LIBCPP_INLINE_VISIBILITY
+        constexpr Span(const Span<_OtherElementType, _OtherExtent>& __other,
+                       std::enable_if_t<
+                          std::is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
+                          nullptr_t> = nullptr) noexcept
+        : __data{__other.data()}, __size{__other.size()} {}
 
-    ~Span() noexcept = default;
+//    ~Span() noexcept = default;
 
-    TCB_SPAN_CONSTEXPR_ASSIGN Span&
-    operator=(const Span& other) noexcept = default;
-
-    // [span.sub], span subviews
-    template <std::size_t Count>
-    TCB_SPAN_CONSTEXPR11 Span<element_type, Count> first() const
+    template <std::size_t _Count>
+    _WTF_LIBCPP_INLINE_VISIBILITY
+    constexpr Span<element_type, _Count> first() const noexcept
     {
-        TCB_SPAN_EXPECT(Count <= size());
-        return {data(), Count};
+        _WTF_LIBCPP_ASSERT(_Count <= size(), "Count out of range in Span::first()");
+        return Span<element_type, _Count>{data(), _Count};
     }
 
-    template <std::size_t Count>
-    TCB_SPAN_CONSTEXPR11 Span<element_type, Count> last() const
+    template <std::size_t _Count>
+    _WTF_LIBCPP_INLINE_VISIBILITY
+    constexpr Span<element_type, _Count> last() const noexcept
     {
-        TCB_SPAN_EXPECT(Count <= size());
-        return {data() + (size() - Count), Count};
+        _WTF_LIBCPP_ASSERT(_Count <= size(), "Count out of range in Span::last()");
+        return Span<element_type, _Count>{data() + size() - _Count, _Count};
     }
 
-    template <std::size_t Offset, std::size_t Count = dynamic_extent>
-    using subspan_return_t =
-        Span<ElementType, Count != dynamic_extent
-                              ? Count
-                              : (Extent != dynamic_extent ? Extent - Offset
-                                                          : dynamic_extent)>;
-
-    template <std::size_t Offset, std::size_t Count = dynamic_extent>
-    TCB_SPAN_CONSTEXPR11 subspan_return_t<Offset, Count> subspan() const
+    _WTF_LIBCPP_INLINE_VISIBILITY
+    constexpr Span<element_type, dynamic_extent> first(size_type __count) const noexcept
     {
-        TCB_SPAN_EXPECT(Offset <= size() &&
-                        (Count == dynamic_extent || Offset + Count <= size()));
-        return {data() + Offset,
-                Count != dynamic_extent ? Count : size() - Offset};
+        _WTF_LIBCPP_ASSERT(__count <= size(), "Count out of range in Span::first(count)");
+        return {data(), __count};
     }
 
-    TCB_SPAN_CONSTEXPR11 Span<element_type, dynamic_extent>
-    first(size_type count) const
+    _WTF_LIBCPP_INLINE_VISIBILITY
+    constexpr Span<element_type, dynamic_extent> last (size_type __count) const noexcept
     {
-        TCB_SPAN_EXPECT(count <= size());
-        return {data(), count};
+        _WTF_LIBCPP_ASSERT(__count <= size(), "Count out of range in Span::last(count)");
+        return {data() + size() - __count, __count};
     }
 
-    TCB_SPAN_CONSTEXPR11 Span<element_type, dynamic_extent>
-    last(size_type count) const
+    template <std::size_t _Offset, std::size_t _Count = dynamic_extent>
+    _WTF_LIBCPP_INLINE_VISIBILITY
+    constexpr Span<element_type, _Count> subspan() const noexcept
     {
-        TCB_SPAN_EXPECT(count <= size());
-        return {data() + (size() - count), count};
+        _WTF_LIBCPP_ASSERT(_Offset <= size(), "Offset out of range in Span::subspan()");
+        _WTF_LIBCPP_ASSERT(_Count == dynamic_extent || _Count <= size() - _Offset, "Offset + count out of range in Span::subspan()");
+        return Span<element_type, _Count>{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
     }
 
-    TCB_SPAN_CONSTEXPR11 Span<element_type, dynamic_extent>
-    subspan(size_type offset, size_type count = dynamic_extent) const
+    constexpr Span<element_type, dynamic_extent>
+    _WTF_LIBCPP_INLINE_VISIBILITY
+    subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept
     {
-        TCB_SPAN_EXPECT(offset <= size() &&
-                        (count == dynamic_extent || offset + count <= size()));
-        return {data() + offset,
-                count == dynamic_extent ? size() - offset : count};
+        _WTF_LIBCPP_ASSERT(__offset <= size(), "Offset out of range in Span::subspan(offset, count)");
+        _WTF_LIBCPP_ASSERT(__count  <= size() || __count == dynamic_extent, "count out of range in Span::subspan(offset, count)");
+        if (__count == dynamic_extent)
+            return {data() + __offset, size() - __offset};
+        _WTF_LIBCPP_ASSERT(__count <= size() - __offset, "Offset + count out of range in Span::subspan(offset, count)");
+        return {data() + __offset, __count};
     }
 
-    // [span.obs], span observers
-    constexpr size_type size() const noexcept { return storage_.size; }
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr size_type size()       const noexcept { return __size; }
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr size_type size_bytes() const noexcept { return __size * sizeof(element_type); }
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr bool empty()           const noexcept { return __size == 0; }
 
-    constexpr size_type size_bytes() const noexcept
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr reference operator[](size_type __idx) const noexcept
     {
-        return size() * sizeof(element_type);
+        _WTF_LIBCPP_ASSERT(__idx < size(), "Span<T>[] index out of bounds");
+        return __data[__idx];
     }
 
-    TCB_SPAN_NODISCARD constexpr bool empty() const noexcept
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept
     {
-        return size() == 0;
+        _WTF_LIBCPP_ASSERT(!empty(), "Span<T>[].front() on empty Span");
+        return __data[0];
     }
 
-    // [span.elem], span element access
-    TCB_SPAN_CONSTEXPR11 reference operator[](size_type idx) const
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr reference back() const noexcept
     {
-        TCB_SPAN_EXPECT(idx < size());
-        return *(data() + idx);
+        _WTF_LIBCPP_ASSERT(!empty(), "Span<T>[].back() on empty Span");
+        return __data[size()-1];
     }
 
-    TCB_SPAN_CONSTEXPR11 reference front() const
-    {
-        TCB_SPAN_EXPECT(!empty());
-        return *data();
-    }
 
-    TCB_SPAN_CONSTEXPR11 reference back() const
-    {
-        TCB_SPAN_EXPECT(!empty());
-        return *(data() + (size() - 1));
-    }
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr pointer data()                         const noexcept { return __data; }
 
-    constexpr pointer data() const noexcept { return storage_.ptr; }
+// [span.iter], Span iterator support
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr iterator                 begin() const noexcept { return iterator(data()); }
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr iterator                   end() const noexcept { return iterator(data() + size()); }
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator        rbegin() const noexcept { return reverse_iterator(end()); }
+    _WTF_LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator          rend() const noexcept { return reverse_iterator(begin()); }
 
-    // [span.iterators], span iterator support
-    constexpr iterator begin() const noexcept { return data(); }
-
-    constexpr iterator end() const noexcept { return data() + size(); }
-
-    TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rbegin() const noexcept
-    {
-        return reverse_iterator(end());
-    }
-
-    TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rend() const noexcept
-    {
-        return reverse_iterator(begin());
-    }
-
 private:
-    storage_type storage_{};
+    pointer   __data;
+    size_type __size;
 };
 
-#ifdef TCB_SPAN_HAVE_DEDUCTION_GUIDES
+#if !defined(_WTF_LIBCPP_HAS_NO_RANGES)
+template <class _Tp, std::size_t _Extent>
+inline constexpr bool std::ranges::enable_borrowed_range<Span<_Tp, _Extent> > = true;
+#endif // !defined(_WTF_LIBCPP_HAS_NO_RANGES)
 
-/* Deduction Guides */
-template <class T, size_t N>
-Span(T (&)[N])->Span<T, N>;
+//  asBytes & asWritableBytes
+template <class _Tp, std::size_t _Extent>
+_WTF_LIBCPP_INLINE_VISIBILITY
+auto asBytes(Span<_Tp, _Extent> __s) noexcept
+-> Span<const std::byte, _Extent == dynamic_extent ? dynamic_extent : _Extent * sizeof(_Tp)>
+{ return { reinterpret_cast<const std::byte *>(__s.data()), __s.size_bytes() }; }
 
-template <class T, size_t N>
-Span(std::array<T, N>&)->Span<T, N>;
+template <class _Tp, std::size_t _Extent>
+_WTF_LIBCPP_INLINE_VISIBILITY
+auto asWritableBytes(Span<_Tp, _Extent> __s) noexcept
+-> std::enable_if_t<!std::is_const_v<_Tp>, Span<std::byte, _Extent == dynamic_extent ? dynamic_extent : _Extent * sizeof(_Tp)>>
+{ return { reinterpret_cast<std::byte *>(__s.data()), __s.size_bytes() }; }
 
-template <class T, size_t N>
-Span(const std::array<T, N>&)->Span<const T, N>;
+//  Deduction guides
+template<class _Tp, std::size_t _Sz>
+    Span(_Tp (&)[_Sz]) -> Span<_Tp, _Sz>;
 
-template <class Container>
-Span(Container&)->Span<typename Container::value_type>;
+template<class _Tp, std::size_t _Sz>
+    Span(std::array<_Tp, _Sz>&) -> Span<_Tp, _Sz>;
 
-template <class Container>
-Span(const Container&)->Span<const typename Container::value_type>;
+template<class _Tp, std::size_t _Sz>
+    Span(const std::array<_Tp, _Sz>&) -> Span<const _Tp, _Sz>;
 
-#endif // TCB_SPAN_HAVE_DEDUCTION_GUIDES
+template<class _Container>
+    Span(_Container&) -> Span<typename _Container::value_type>;
 
-#ifdef TCB_SPAN_INCLUDE_MAKE_SPAN
+template<class _Container>
+    Span(const _Container&) -> Span<const typename _Container::value_type>;
 
-template <typename ElementType, std::size_t Extent>
-constexpr Span<ElementType, Extent>
-make_span(Span<ElementType, Extent> s) noexcept
-{
-    return s;
-}
+_WTF_LIBCPP_END_NAMESPACE
 
-template <typename T, std::size_t N>
-constexpr Span<T, N> make_span(T (&arr)[N]) noexcept
-{
-    return {arr};
-}
-
-template <typename T, std::size_t N>
-TCB_SPAN_ARRAY_CONSTEXPR Span<T, N> make_span(std::array<T, N>& arr) noexcept
-{
-    return {arr};
-}
-
-template <typename T, std::size_t N>
-TCB_SPAN_ARRAY_CONSTEXPR Span<const T, N>
-make_span(const std::array<T, N>& arr) noexcept
-{
-    return {arr};
-}
-
-template <typename Container>
-constexpr Span<typename Container::value_type> make_span(Container& cont)
-{
-    return {cont};
-}
-
-template <typename Container>
-constexpr Span<const typename Container::value_type>
-make_span(const Container& cont)
-{
-    return {cont};
-}
-#endif // TCB_SPAN_INCLUDE_MAKE_SPAN
-
-template <typename ElementType, std::size_t Extent>
-Span<const byte, ((Extent == dynamic_extent) ? dynamic_extent
-                                             : sizeof(ElementType) * Extent)>
-asBytes(Span<ElementType, Extent> s) noexcept
-{
-    return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
-}
-
-template <
-    class ElementType, size_t Extent,
-    typename std::enable_if<!std::is_const<ElementType>::value, int>::type = 0>
-Span<byte, ((Extent == dynamic_extent) ? dynamic_extent
-                                       : sizeof(ElementType) * Extent)>
-asWritableBytes(Span<ElementType, Extent> s) noexcept
-{
-    return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
-}
-
-template <std::size_t N, typename E, std::size_t S>
-constexpr auto get(Span<E, S> s) -> decltype(s[N])
-{
-    return s[N];
-}
-
-} // namespace TCB_SPAN_NAMESPACE_NAME
-
-namespace std {
-
-template <typename ElementType, size_t Extent>
-class tuple_size<TCB_SPAN_NAMESPACE_NAME::Span<ElementType, Extent>>
-    : public integral_constant<size_t, Extent> {};
-
-template <typename ElementType>
-class tuple_size<TCB_SPAN_NAMESPACE_NAME::Span<
-    ElementType, TCB_SPAN_NAMESPACE_NAME::dynamic_extent>>; // not defined
-
-template <size_t I, typename ElementType, size_t Extent>
-class tuple_element<I, TCB_SPAN_NAMESPACE_NAME::Span<ElementType, Extent>> {
-public:
-    static_assert(Extent != TCB_SPAN_NAMESPACE_NAME::dynamic_extent &&
-                      I < Extent,
-                  "");
-    using type = ElementType;
-};
-
-} // end namespace std
-
 using WTF::Span;
 using WTF::asBytes;
 using WTF::asWritableBytes;
 
-#endif // TCB_SPAN_HPP_INCLUDED
+#endif // _WTF_LIBCPP_SPAN
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to