From e59cf7b09e7388d369e8d2bf73501cde79c28708 Mon Sep 17 00:00:00 2001 From: Toni Uhlig Date: Thu, 8 Apr 2021 16:43:58 +0200 Subject: Squashed 'EASTL/' content from commit fad5471 git-subtree-dir: EASTL git-subtree-split: fad54717f8e4ebb13b20095da7efd07a53af0f10 --- include/EASTL/span.h | 427 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 427 insertions(+) create mode 100644 include/EASTL/span.h (limited to 'include/EASTL/span.h') diff --git a/include/EASTL/span.h b/include/EASTL/span.h new file mode 100644 index 0000000..1f3b9b4 --- /dev/null +++ b/include/EASTL/span.h @@ -0,0 +1,427 @@ +///////////////////////////////////////////////////////////////////////////// +// Copyright (c) Electronic Arts Inc. All rights reserved. +///////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// This file implements the eastl::span which is part of the C++ standard +// STL library specification. +// +// eastl::span is a non-owning container that refers to a contiguous block of +// memory. It bundles up the classic pattern of a pointer and a size into a +// single type. A span can either have a static extent, in which case the +// number of elements in the sequence is known and encoded in the type, or a +// dynamic extent. +// +// http://en.cppreference.com/w/cpp/container/span +// http://eel.is/c++draft/views#span.syn +/////////////////////////////////////////////////////////////////////////////// + +#ifndef EASTL_SPAN_H +#define EASTL_SPAN_H + +#if defined(EA_PRAGMA_ONCE_SUPPORTED) + #pragma once +#endif + +#include +#include +#include +#include + +namespace eastl +{ + static EA_CONSTEXPR size_t dynamic_extent = size_t(-1); + + namespace Internal + { + // HasSizeAndData + // + // custom type trait to determine if eastl::data(Container) and eastl::size(Container) are well-formed. + // + template + struct HasSizeAndData : eastl::false_type {}; + + template + struct HasSizeAndData())), decltype(eastl::data(eastl::declval()))>> : eastl::true_type {}; + + // SubspanExtent + // + // Integral constant that calculates the resulting extent of a templated subspan operation. + // + // If Count is not dynamic_extent then SubspanExtent::value is Count, + // otherwise, if Extent is not dynamic_extent, SubspanExtent::value is (Extent - Offset), + // otherwise, SubspanExtent::value is dynamic_extent. + // + template + struct SubspanExtent : eastl::integral_constant {}; + } + + template + class span + { + public: + typedef T element_type; + typedef remove_cv_t value_type; + typedef eastl_size_t index_type; + typedef ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T* iterator; + typedef const T* const_iterator; + typedef eastl::reverse_iterator reverse_iterator; + typedef eastl::reverse_iterator const_reverse_iterator; + + static EA_CONSTEXPR size_t extent = Extent; + + // constructors / destructor + EA_CONSTEXPR span() EA_NOEXCEPT = default; + EA_CONSTEXPR span(const span& other) EA_NOEXCEPT = default; + EA_CONSTEXPR span(pointer ptr, index_type count); + EA_CONSTEXPR span(pointer pBegin, pointer pEnd); + ~span() EA_NOEXCEPT = default; + + // copy-assignment operator + EA_CPP14_CONSTEXPR span& operator=(const span& other) EA_NOEXCEPT = default; + + // conversion constructors for c-array and eastl::array + template EA_CONSTEXPR span(element_type (&arr)[N]) EA_NOEXCEPT; + template EA_CONSTEXPR span(eastl::array& arr) EA_NOEXCEPT; + template EA_CONSTEXPR span(const eastl::array& arr) EA_NOEXCEPT; + + // SfinaeForGenericContainers + // + template + using SfinaeForGenericContainers = + enable_if_t && !is_same_v> && + !is_array_v && + Internal::HasSizeAndData::value && + is_convertible_v()))> (*)[], element_type (*)[]>>; + + // generic container conversion constructors + template > + EA_CONSTEXPR span(Container& cont); + + template > + EA_CONSTEXPR span(const Container& cont); + + template )>> + EA_CONSTEXPR span(const span& s) EA_NOEXCEPT; + + // subviews + template + EA_CPP14_CONSTEXPR span first() const; + EA_CPP14_CONSTEXPR span first(size_t Count) const; + + template + EA_CPP14_CONSTEXPR span last() const; + EA_CPP14_CONSTEXPR span last(size_t Count) const; + + template + EA_CONSTEXPR span::value> subspan() const; + EA_CONSTEXPR span subspan(size_t Offset, size_t Count = dynamic_extent) const; + + // observers + EA_CONSTEXPR pointer data() const EA_NOEXCEPT; + EA_CONSTEXPR index_type size() const EA_NOEXCEPT; + EA_CONSTEXPR index_type size_bytes() const EA_NOEXCEPT; + EA_CONSTEXPR bool empty() const EA_NOEXCEPT; + + // subscript operators, element access + EA_CONSTEXPR reference front() const; + EA_CONSTEXPR reference back() const; + EA_CONSTEXPR reference operator[](index_type idx) const; + EA_CONSTEXPR reference operator()(index_type idx) const; + + // iterator support + EA_CONSTEXPR iterator begin() const EA_NOEXCEPT; + EA_CONSTEXPR iterator end() const EA_NOEXCEPT; + EA_CONSTEXPR const_iterator cbegin() const EA_NOEXCEPT; + EA_CONSTEXPR const_iterator cend() const EA_NOEXCEPT; + EA_CONSTEXPR reverse_iterator rbegin() const EA_NOEXCEPT; + EA_CONSTEXPR reverse_iterator rend() const EA_NOEXCEPT; + EA_CONSTEXPR const_reverse_iterator crbegin() const EA_NOEXCEPT; + EA_CONSTEXPR const_reverse_iterator crend() const EA_NOEXCEPT; + + private: + pointer mpData = nullptr; + index_type mnSize = 0; + + private: + EA_CONSTEXPR bool bounds_check(size_t) const; // utility used in asserts + }; + + + /////////////////////////////////////////////////////////////////////////// + // template deduction guides + /////////////////////////////////////////////////////////////////////////// + #ifdef __cpp_deduction_guides + template span(T (&)[N]) -> span ; + template span(array&) -> span ; + template span(const array&) -> span ; + template span(Container&) -> span ; + template span(const Container&) -> span ; + #endif + + + /////////////////////////////////////////////////////////////////////////// + // comparison operators + /////////////////////////////////////////////////////////////////////////// + + template + EA_CONSTEXPR bool operator==(span l, span r) + { + return (l.size() == r.size()) && eastl::equal(l.begin(), l.end(), r.begin()); + } + + template + EA_CONSTEXPR bool operator<(span l, span r) + { + return eastl::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); + } + + template + EA_CONSTEXPR bool operator!=(span l, span r) { return !(l == r); } + + template + EA_CONSTEXPR bool operator<=(span l, span r) { return !(r < l); } + + template + EA_CONSTEXPR bool operator>(span l, span r) { return r < l; } + + template + EA_CONSTEXPR bool operator>=(span l, span r) { return !(l < r); } + + + /////////////////////////////////////////////////////////////////////////// + // ctor implementations + /////////////////////////////////////////////////////////////////////////// + + template + EA_CONSTEXPR span::span(pointer ptr, index_type size) + : mpData(ptr), mnSize(size) + { + } + + template + EA_CONSTEXPR span::span(pointer pBegin, pointer pEnd) + : mpData(pBegin), mnSize(static_cast(pEnd - pBegin)) + { + } + + template + template + EA_CONSTEXPR span::span(element_type(&arr)[N]) EA_NOEXCEPT + : span(arr, static_cast(N)) + { + } + + template + template + EA_CONSTEXPR span::span(eastl::array &arr) EA_NOEXCEPT + : span(arr.data(), arr.size()) + { + } + + template + template + EA_CONSTEXPR span::span(const eastl::array& arr) EA_NOEXCEPT + : span(arr.data(), arr.size()) + { + } + + + template + template + EA_CONSTEXPR span::span(Container& cont) + : span(static_cast(eastl::data(cont)), static_cast(eastl::size(cont))) + { + } + + template + template + EA_CONSTEXPR span::span(const Container& cont) + : span(static_cast(eastl::data(cont)), static_cast(eastl::size(cont))) + { + } + + template + template + EA_CONSTEXPR span::span(const span& s) EA_NOEXCEPT + : span(s.data(), s.size()) + { + } + + + /////////////////////////////////////////////////////////////////////////// + // member function implementations + /////////////////////////////////////////////////////////////////////////// + + template + EA_CONSTEXPR typename span::pointer span::data() const EA_NOEXCEPT + { + return mpData; + } + + template + EA_CONSTEXPR typename span::index_type span::size() const EA_NOEXCEPT + { + return mnSize; + } + + template + EA_CONSTEXPR typename span::index_type span::size_bytes() const EA_NOEXCEPT + { + return size() * sizeof(element_type); + } + + template + EA_CONSTEXPR bool span::empty() const EA_NOEXCEPT + { + return size() == 0; + } + + template + EA_CONSTEXPR typename span::reference span::front() const + { + EASTL_ASSERT_MSG(!empty(), "undefined behavior accessing an empty span"); + + return mpData[0]; + } + + template + EA_CONSTEXPR typename span::reference span::back() const + { + EASTL_ASSERT_MSG(!empty(), "undefined behavior accessing an empty span"); + + return mpData[mnSize - 1]; + } + + template + EA_CONSTEXPR typename span::reference span::operator[](index_type idx) const + { + EASTL_ASSERT_MSG(!empty(), "undefined behavior accessing an empty span"); + EASTL_ASSERT_MSG(bounds_check(idx), "undefined behavior accessing out of bounds"); + + return mpData[idx]; + } + + template + EA_CONSTEXPR typename span::reference span::operator()(index_type idx) const + { + EASTL_ASSERT_MSG(!empty(), "undefined behavior accessing an empty span"); + EASTL_ASSERT_MSG(bounds_check(idx), "undefined behavior accessing out of bounds"); + + return mpData[idx]; + } + + template + EA_CONSTEXPR typename span::iterator span::begin() const EA_NOEXCEPT + { + return mpData; + } + + template + EA_CONSTEXPR typename span::iterator span::end() const EA_NOEXCEPT + { + return mpData + mnSize; + } + + template + EA_CONSTEXPR typename span::const_iterator span::cbegin() const EA_NOEXCEPT + { + return mpData; + } + + template + EA_CONSTEXPR typename span::const_iterator span::cend() const EA_NOEXCEPT + { + return mpData + mnSize; + } + + template + EA_CONSTEXPR typename span::reverse_iterator span::rbegin() const EA_NOEXCEPT + { + return reverse_iterator(mpData + mnSize); + } + + template + EA_CONSTEXPR typename span::reverse_iterator span::rend() const EA_NOEXCEPT + { + return reverse_iterator(mpData); + } + + template + EA_CONSTEXPR typename span::const_reverse_iterator span::crbegin() const EA_NOEXCEPT + { + return const_reverse_iterator(mpData + mnSize); + } + + template + EA_CONSTEXPR typename span::const_reverse_iterator span::crend() const EA_NOEXCEPT + { + return const_reverse_iterator(mpData); + } + + template + template + EA_CPP14_CONSTEXPR span::element_type, Count> span::first() const + { + EASTL_ASSERT_MSG(bounds_check(Count), "undefined behavior accessing out of bounds"); + return {data(), static_cast(Count)}; + } + + template + EA_CPP14_CONSTEXPR span::element_type, dynamic_extent> + span::first(size_t sz) const + { + EASTL_ASSERT_MSG(bounds_check(sz), "undefined behavior accessing out of bounds"); + return {data(), static_cast(sz)}; + } + + template + template + EA_CPP14_CONSTEXPR span::element_type, Count> span::last() const + { + EASTL_ASSERT_MSG(bounds_check(Count), "undefined behavior accessing out of bounds"); + return {data() + size() - Count, static_cast(Count)}; + } + + template + EA_CPP14_CONSTEXPR span::element_type, dynamic_extent> + span::last(size_t sz) const + { + EASTL_ASSERT_MSG(bounds_check(sz), "undefined behavior accessing out of bounds"); + return {data() + size() - sz, static_cast(sz)}; + } + + template + template + EA_CONSTEXPR span::element_type, Internal::SubspanExtent::value> + span::subspan() const + { + EASTL_ASSERT_MSG(bounds_check(Offset), "undefined behaviour accessing out of bounds"); + EASTL_ASSERT_MSG(Count == dynamic_extent || Count <= (size() - Offset), "undefined behaviour exceeding size of span"); + + return {data() + Offset, eastl_size_t(Count == dynamic_extent ? size() - Offset : Count)}; + } + + template + EA_CONSTEXPR span::element_type, dynamic_extent> + span::subspan(size_t offset, size_t count) const + { + EASTL_ASSERT_MSG(bounds_check(offset), "undefined behaviour accessing out of bounds"); + EASTL_ASSERT_MSG(count == dynamic_extent || count <= (size() - offset), "undefined behaviour exceeding size of span"); + + return {data() + offset, eastl_size_t(count == dynamic_extent ? size() - offset : count)}; + } + + template + EA_CONSTEXPR bool span::bounds_check(size_t sz) const + { + return (sz >= 0 && sz < size()); + } +} + +#endif // EASTL_SPAN_H -- cgit v1.2.3