diff options
Diffstat (limited to 'kernel/lib/libcxx/include/span')
| -rw-r--r-- | kernel/lib/libcxx/include/span | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/kernel/lib/libcxx/include/span b/kernel/lib/libcxx/include/span new file mode 100644 index 0000000..3e4c3ee --- /dev/null +++ b/kernel/lib/libcxx/include/span @@ -0,0 +1,216 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the BastionOS freestanding C++ standard library. +// +// std::span — non-owning contiguous view. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBBASTION_SPAN +#define _LIBBASTION_SPAN + +#include <__config> +#include <__type_traits/integral_constant.h> +#include <__type_traits/type_modifications.h> +#include <__type_traits/type_relationships.h> +#include <array> +#include <cstddef> + +_LIBBASTION_BEGIN_NAMESPACE_STD + +inline constexpr size_t dynamic_extent = static_cast<size_t>(-1); + +// ── span — dynamic extent ─────────────────────────────────────────────────── + +template<class _Tp, size_t _Extent = dynamic_extent> +class span; + +template<class _Tp> +class span<_Tp, dynamic_extent> { +public: + using element_type = _Tp; + using value_type = remove_cv_t<_Tp>; + using size_type = size_t; + using difference_type = ptrdiff_t; + using pointer = _Tp*; + using const_pointer = const _Tp*; + using reference = _Tp&; + using const_reference = const _Tp&; + using iterator = _Tp*; + using const_iterator = const _Tp*; + + static constexpr size_type extent = dynamic_extent; + + // Constructors + constexpr span() noexcept : __data_(nullptr), __size_(0) {} + constexpr span(_Tp* __ptr, size_type __count) noexcept : __data_(__ptr), __size_(__count) {} + constexpr span(_Tp* __first, _Tp* __last) noexcept : __data_(__first), __size_(static_cast<size_type>(__last - __first)) {} + + template<size_t _Np> + constexpr span(_Tp (&__arr)[_Np]) noexcept : __data_(__arr), __size_(_Np) {} + + template<class _Up, size_t _Np> + requires is_convertible_v<_Up(*)[], _Tp(*)[]> + constexpr span(array<_Up, _Np>& __arr) noexcept : __data_(__arr.data()), __size_(_Np) {} + + template<class _Up, size_t _Np> + requires is_convertible_v<const _Up(*)[], _Tp(*)[]> + constexpr span(const array<_Up, _Np>& __arr) noexcept : __data_(__arr.data()), __size_(_Np) {} + + // From other span + template<class _Up, size_t _OtherExtent> + requires is_convertible_v<_Up(*)[], _Tp(*)[]> + constexpr span(const span<_Up, _OtherExtent>& __other) noexcept + : __data_(__other.data()), __size_(__other.size()) {} + + constexpr span(const span&) noexcept = default; + constexpr span& operator=(const span&) noexcept = default; + + // Element access + _LIBBASTION_NODISCARD constexpr reference operator[](size_type __idx) const { return __data_[__idx]; } + _LIBBASTION_NODISCARD constexpr reference front() const { return __data_[0]; } + _LIBBASTION_NODISCARD constexpr reference back() const { return __data_[__size_ - 1]; } + _LIBBASTION_NODISCARD constexpr pointer data() const noexcept { return __data_; } + + // Iterators + _LIBBASTION_NODISCARD constexpr iterator begin() const noexcept { return __data_; } + _LIBBASTION_NODISCARD constexpr iterator end() const noexcept { return __data_ + __size_; } + _LIBBASTION_NODISCARD constexpr const_iterator cbegin() const noexcept { return __data_; } + _LIBBASTION_NODISCARD constexpr const_iterator cend() const noexcept { return __data_ + __size_; } + + // Capacity + _LIBBASTION_NODISCARD constexpr size_type size() const noexcept { return __size_; } + _LIBBASTION_NODISCARD constexpr size_type size_bytes() const noexcept { return __size_ * sizeof(_Tp); } + _LIBBASTION_NODISCARD constexpr bool empty() const noexcept { return __size_ == 0; } + + // Subviews + constexpr span first(size_type __count) const { return span(__data_, __count); } + constexpr span last(size_type __count) const { return span(__data_ + __size_ - __count, __count); } + + constexpr span subspan(size_type __offset, size_type __count = dynamic_extent) const { + return span(__data_ + __offset, __count == dynamic_extent ? __size_ - __offset : __count); + } + + template<size_t _Count> + constexpr span<_Tp, _Count> first() const { return span<_Tp, _Count>(__data_, _Count); } + + template<size_t _Count> + constexpr span<_Tp, _Count> last() const { return span<_Tp, _Count>(__data_ + __size_ - _Count, _Count); } + +private: + pointer __data_; + size_type __size_; +}; + +// ── span — static extent ──────────────────────────────────────────────────── + +template<class _Tp, size_t _Extent> +class span { +public: + using element_type = _Tp; + using value_type = remove_cv_t<_Tp>; + using size_type = size_t; + using difference_type = ptrdiff_t; + using pointer = _Tp*; + using const_pointer = const _Tp*; + using reference = _Tp&; + using const_reference = const _Tp&; + using iterator = _Tp*; + using const_iterator = const _Tp*; + + static constexpr size_type extent = _Extent; + + // Constructors + constexpr span() noexcept requires (_Extent == 0) : __data_(nullptr) {} + constexpr span(_Tp* __ptr, size_type) noexcept : __data_(__ptr) {} + constexpr span(_Tp* __first, _Tp*) noexcept : __data_(__first) {} + + constexpr span(_Tp (&__arr)[_Extent]) noexcept : __data_(__arr) {} + + template<class _Up> + requires is_convertible_v<_Up(*)[], _Tp(*)[]> + constexpr span(array<_Up, _Extent>& __arr) noexcept : __data_(__arr.data()) {} + + template<class _Up> + requires is_convertible_v<const _Up(*)[], _Tp(*)[]> + constexpr span(const array<_Up, _Extent>& __arr) noexcept : __data_(__arr.data()) {} + + // From dynamic span + template<class _Up> + requires is_convertible_v<_Up(*)[], _Tp(*)[]> + constexpr span(const span<_Up, dynamic_extent>& __other) noexcept : __data_(__other.data()) {} + + // From other static span + template<class _Up, size_t _OtherExtent> + requires (_OtherExtent == _Extent) && is_convertible_v<_Up(*)[], _Tp(*)[]> + constexpr span(const span<_Up, _OtherExtent>& __other) noexcept : __data_(__other.data()) {} + + constexpr span(const span&) noexcept = default; + constexpr span& operator=(const span&) noexcept = default; + + // Element access + _LIBBASTION_NODISCARD constexpr reference operator[](size_type __idx) const { return __data_[__idx]; } + _LIBBASTION_NODISCARD constexpr reference front() const { return __data_[0]; } + _LIBBASTION_NODISCARD constexpr reference back() const { return __data_[_Extent - 1]; } + _LIBBASTION_NODISCARD constexpr pointer data() const noexcept { return __data_; } + + // Iterators + _LIBBASTION_NODISCARD constexpr iterator begin() const noexcept { return __data_; } + _LIBBASTION_NODISCARD constexpr iterator end() const noexcept { return __data_ + _Extent; } + _LIBBASTION_NODISCARD constexpr const_iterator cbegin() const noexcept { return __data_; } + _LIBBASTION_NODISCARD constexpr const_iterator cend() const noexcept { return __data_ + _Extent; } + + // Capacity + _LIBBASTION_NODISCARD constexpr size_type size() const noexcept { return _Extent; } + _LIBBASTION_NODISCARD constexpr size_type size_bytes() const noexcept { return _Extent * sizeof(_Tp); } + _LIBBASTION_NODISCARD constexpr bool empty() const noexcept { return _Extent == 0; } + + // Subviews + constexpr span<_Tp, dynamic_extent> first(size_type __count) const { + return span<_Tp, dynamic_extent>(__data_, __count); + } + constexpr span<_Tp, dynamic_extent> last(size_type __count) const { + return span<_Tp, dynamic_extent>(__data_ + _Extent - __count, __count); + } + constexpr span<_Tp, dynamic_extent> subspan(size_type __offset, size_type __count = dynamic_extent) const { + return span<_Tp, dynamic_extent>(__data_ + __offset, __count == dynamic_extent ? _Extent - __offset : __count); + } + + template<size_t _Count> + constexpr span<_Tp, _Count> first() const { return span<_Tp, _Count>(__data_, _Count); } + + template<size_t _Count> + constexpr span<_Tp, _Count> last() const { return span<_Tp, _Count>(__data_ + _Extent - _Count, _Count); } + +private: + pointer __data_; +}; + +// Deduction guides +template<class _Tp, size_t _Np> +span(_Tp (&)[_Np]) -> span<_Tp, _Np>; + +template<class _Tp, size_t _Np> +span(array<_Tp, _Np>&) -> span<_Tp, _Np>; + +template<class _Tp, size_t _Np> +span(const array<_Tp, _Np>&) -> span<const _Tp, _Np>; + +// as_bytes / as_writable_bytes +template<class _Tp, size_t _Extent> +span<const byte, _Extent == dynamic_extent ? dynamic_extent : sizeof(_Tp) * _Extent> +as_bytes(span<_Tp, _Extent> __sp) noexcept { + return {reinterpret_cast<const byte*>(__sp.data()), __sp.size_bytes()}; +} + +template<class _Tp, size_t _Extent> + requires (!__is_const(_Tp)) +span<byte, _Extent == dynamic_extent ? dynamic_extent : sizeof(_Tp) * _Extent> +as_writable_bytes(span<_Tp, _Extent> __sp) noexcept { + return {reinterpret_cast<byte*>(__sp.data()), __sp.size_bytes()}; +} + +_LIBBASTION_END_NAMESPACE_STD + +#endif // _LIBBASTION_SPAN |
