Go to the documentation of this file.
9 #ifndef EAGINE_MEMORY_SPAN_HPP
10 #define EAGINE_MEMORY_SPAN_HPP
12 #include "../anything.hpp"
13 #include "../assert.hpp"
14 #include "../compare.hpp"
15 #include "../extract.hpp"
16 #include "../int_constant.hpp"
17 #include "../type_identity.hpp"
18 #include "../types.hpp"
21 #include <initializer_list>
23 #include <type_traits>
30 template <
typename Ptr,
typename U>
31 struct rebind_pointer;
33 template <
typename Ptr,
typename U>
34 using rebind_pointer_t =
typename rebind_pointer<Ptr, U>::type;
36 template <
typename T,
typename U>
37 struct rebind_pointer<T*, U> : type_identity<U*> {};
41 struct _has_span_size_member_base {
42 template <typename X, typename S = decltype(std::declval<X>().size())>
44 static auto _detect(X*) -> bool_constant<std::is_integral_v<S>>;
45 static auto _detect(...) -> std::false_type;
53 _has_span_size_member_base::_detect(static_cast<T*>(nullptr))) {};
62 template <
typename Elem>
63 struct _has_span_data_member_base {
66 typename P = decltype(std::declval<X>().data()),
67 typename PT =
typename std::pointer_traits<P>::element_type>
68 static auto _detect(X*) -> std::is_convertible<PT, Elem>;
70 static auto _detect(...) -> std::false_type;
75 template <
typename T,
typename E>
78 _has_span_data_member_base<E>::_detect(static_cast<T*>(nullptr))) {};
82 template <
typename T,
typename E = anything>
100 typename Pointer = ValueType*,
132 : _addr{
static_cast<Pointer
>(
addr)}
138 , _size{b <= e ? e - b : 0} {}
142 : _addr{
static_cast<Pointer
>(ba)}
143 , _size{limit_cast<size_type>(
144 ba <= be ? (be - ba) /
sizeof(
value_type) : 0)} {}
146 template <
typename T,
typename P,
typename S>
147 using enable_if_convertible = std::enable_if_t<
148 std::is_convertible_v<T, ValueType> &&
149 std::is_convertible_v<P, Pointer> && std::is_convertible_v<S, SizeType>>;
151 template <
typename T,
typename P,
typename S>
152 using enable_if_different = std::enable_if_t<
153 !std::is_same_v<T, ValueType> || !std::is_same_v<P, Pointer> ||
154 !std::is_same_v<S, SizeType>>;
179 typename = enable_if_convertible<T, P, S>,
180 typename = enable_if_different<T, P, S>>
182 : _addr{
static_cast<Pointer
>(that.data())}
183 , _size{limit_cast<SizeType>(that.size())} {}
190 typename = enable_if_convertible<T, P, S>,
191 typename = enable_if_different<T, P, S>>
193 _addr =
static_cast<Pointer
>(that.data());
194 _size = limit_cast<SizeType>(that.size());
222 explicit constexpr
operator bool() const noexcept {
235 constexpr
auto empty() const noexcept ->
bool {
247 return EAGINE_LIKELY(_size >= 0) ? _size : -_size;
274 constexpr
auto rend() const noexcept {
294 template <
typename X>
296 return addr().template is_aligned_as<X>();
308 template <
typename Ts,
typename Ps,
typename Ss>
310 return (
addr() <= that.addr()) && (that.end_addr() <=
end_addr());
316 template <
typename Ts,
typename Ps,
typename Ss>
325 -> std::add_const_t<value_type>& {
326 return EAGINE_CONSTEXPR_ASSERT(index <
size(), _addr[index]);
332 return EAGINE_CONSTEXPR_ASSERT(index <
size(), _addr[index]);
339 return EAGINE_CONSTEXPR_ASSERT(0 <
size(), _addr[0]);
346 return EAGINE_CONSTEXPR_ASSERT(0 <
size(), _addr[0]);
353 return EAGINE_CONSTEXPR_ASSERT(0 <
size(), _addr[
size() - 1]);
360 return EAGINE_CONSTEXPR_ASSERT(0 <
size(), _addr[
size() - 1]);
365 template <
typename Int>
366 constexpr
auto element(Int index)
const noexcept
367 -> std::enable_if_t<std::is_integral_v<Int>, std::add_const_t<value_type>&> {
373 template <
typename Int>
375 -> std::enable_if_t<std::is_integral_v<Int>,
value_type&> {
381 template <
typename Int>
383 -> std::enable_if_t<std::is_integral_v<Int>,
value_type&> {
389 template <
typename Int>
391 -> std::enable_if_t<std::is_integral_v<Int>, std::add_const_t<value_type>&> {
406 template <
typename T,
typename P,
typename S>
414 template <
typename T,
typename S = span_
size_t>
419 template <
typename T>
424 template <
typename T>
429 template <
typename T>
431 return {std::addressof(value),
span_size(1)};
436 template <
typename T>
438 return {std::addressof(value),
span_size(1)};
443 template <
typename T>
450 template <
typename T>
457 template <
typename T,
typename S>
464 template <
typename T,
typename S>
471 template <
typename T,
typename S>
479 template <
typename T,
typename S>
487 template <
typename T, std::
size_t N>
489 return view(
static_cast<const T*
>(array), N);
494 template <
typename T, std::
size_t N>
496 return cover(
static_cast<T*
>(array), N);
501 template <
typename T>
502 static constexpr
auto view(std::initializer_list<T> il) noexcept
504 return view(il.begin(), il.size());
512 std::enable_if_t<has_span_data_member_v<C> && has_span_size_member_v<C>>>
513 static constexpr
auto view(
const C& container) noexcept {
514 return view(container.data(), container.size());
522 std::enable_if_t<has_span_data_member_v<C> && has_span_size_member_v<C>>>
523 static constexpr
auto cover(C& container) noexcept {
524 return cover(container.data(), container.size());
529 static constexpr
auto can_accomodate_between(
533 return (end - bgn) >= size;
538 template <
typename T,
typename B,
typename P,
typename S>
543 return can_accomodate_between(
551 template <
typename T,
typename B,
typename P,
typename S>
552 static constexpr
auto
561 template <
typename T,
typename B,
typename P,
typename S>
562 static constexpr
auto
564 ->
basic_span<std::add_const_t<T>, rebind_pointer_t<P, T>, S> {
574 template <
typename T,
typename P,
typename S>
576 return EAGINE_CONSTEXPR_ASSERT(spn.size() >= 1, spn.front());
581 template <
typename T,
typename P,
typename S>
584 return (spn.size() >= 1) ? spn.front() : fallback;
589 template <
typename T,
typename P,
typename S,
typename F>
591 -> std::enable_if_t<std::is_convertible_v<F, T>, T> {
592 return (spn.size() >= 1) ? spn.front() : T{std::forward<F>(fallback)};
604 struct equal_cmp<memory::basic_span<Tl, Pl, Sl>, memory::basic_span<Tr, Pr, Sr>> {
607 memory::basic_span<Tl, Pl, Sl> l,
608 memory::basic_span<Tr, Pr, Sr> r) noexcept ->
bool {
609 if(are_equal(l.size(), r.size())) {
611 std::is_same_v<std::remove_const_t<Tl>, std::remove_const_t<Tr>> &&
612 std::is_integral_v<std::remove_const_t<Tl>>) {
615 l.data(), r.data(),
sizeof(Tl) *
std_size(l.size()));
619 if(!are_equal(l[i], r[i])) {
632 #endif // EAGINE_MEMORY_SPAN_HPP
constexpr auto rbegin() const noexcept
Returns a reverse interator to the end of the span.
Definition: span.hpp:269
constexpr auto empty() const noexcept -> bool
Indicates that the span is empty.
Definition: span.hpp:235
static constexpr auto align_up_to(basic_address< std::is_const_v< T >> addr, type_identity< T >={}, span_size_t align=span_align_of< T >(), span_size_t max=span_size_of< T >()) noexcept
Aligns a memory address up to the required alignment of type T.
Definition: address.hpp:320
Class for handling memory addresses as integer values.
Definition: address.hpp:23
std::ptrdiff_t span_size_t
Signed span size type used by eagine.
Definition: types.hpp:36
static constexpr auto span_size(T v) noexcept
Converts argument to span size type.
Definition: types.hpp:59
auto operator[](Int index) noexcept -> std::enable_if_t< std::is_integral_v< Int >, value_type & >
Array subscript operator.
Definition: span.hpp:382
Common code is placed in this namespace.
Definition: eagine.hpp:21
static constexpr auto as_address(T *addr) noexcept
Casts a pointer to basic_address.
Definition: address.hpp:208
const gl_types::ubyte_type * pointer
The pointer type.
Definition: span.hpp:114
auto reset(address_type addr, size_type length) noexcept -> auto &
Resets this span with a new memory address and length.
Definition: span.hpp:210
static constexpr auto extract(api_result_value< Result, api_result_validity::never > &) noexcept -> Result &
Overload of extract for api_result_value.
Definition: c_api_wrap.hpp:270
constexpr basic_span(pointer addr, size_type len) noexcept
Construction from pointer and length.
Definition: span.hpp:126
std::enable_if_t<!std::is_const_v< T >, span< T > > span_if_mutable
Alias for span<T> if T is mutable type. Ill defined otherwise.
Definition: span.hpp:420
static constexpr auto can_accomodate(basic_span< B, P, S > blk, type_identity< T > tid={}) noexcept
Indicates if the specified memory block can accomodate one element of T.
Definition: span.hpp:553
constexpr auto begin() const noexcept -> iterator
Returns an interator to the start of the span.
Definition: span.hpp:259
constexpr auto addr() const noexcept -> address_type
Returns the memory address of the start of the span.
Definition: span.hpp:279
auto front() noexcept -> value_type &
Returns a reference to value at the front of the span.
Definition: span.hpp:345
constexpr auto data() const noexcept -> pointer
Returns a pointer to the start of the span.
Definition: span.hpp:254
constexpr auto end() const noexcept -> iterator
Returns a iterator past the end of the span.
Definition: span.hpp:264
auto back() noexcept -> value_type &
Returns a const reference to value at the back of the span.
Definition: span.hpp:359
auto ref(size_type index) noexcept -> value_type &
Returns a reference to value at the specified index.
Definition: span.hpp:331
constexpr basic_span() noexcept=default
Default constructor. Constructs an empty span.
constexpr basic_span(pointer b, pointer e) noexcept
Construction from a pair of pointers.
Definition: span.hpp:136
static constexpr auto cover_one(T *pointer) noexcept -> span_if_mutable< T >
Creates a single-element mutable span from the specified pointer.
Definition: span.hpp:451
constexpr bool has_span_size_member_v
Trait indicating if type T has x.size() member function.
Definition: span.hpp:58
auto reset(pointer addr, size_type length) noexcept -> auto &
Resets this span with a new pointer and length.
Definition: span.hpp:205
static constexpr auto view_one(const T *pointer) noexcept -> const_span< T >
Creates a single-const-element view from the specified pointer.
Definition: span.hpp:444
auto reset() noexcept -> auto &
Resets this span.
Definition: span.hpp:200
span_size_t size_type
The element count type.
Definition: span.hpp:108
auto contains(basic_span< Ts, Ps, Ss > that) const noexcept -> bool
Indicates if this span encloses another span.
Definition: span.hpp:309
static constexpr auto std_size(T v) noexcept
Converts argument to std size type.
Definition: types.hpp:52
constexpr auto is_empty() const noexcept -> bool
Indicates that the span is empty.
Definition: span.hpp:228
static constexpr auto view(const C &container) noexcept
Creates a const view over a compatible contiguous container.
Definition: span.hpp:513
constexpr auto rend() const noexcept
Returns a reverse interator past the begin of the span.
Definition: span.hpp:274
constexpr auto element(Int index) const noexcept -> std::enable_if_t< std::is_integral_v< Int >, std::add_const_t< value_type > & >
Returns a const reference to value at the specified index.
Definition: span.hpp:366
std::reverse_iterator< iterator > reverse_iterator
The reverse iterator type.
Definition: span.hpp:123
Non-owning view of a contiguous range of memory with ValueType elements.
Definition: flatten_fwd.hpp:16
constexpr auto operator[](Int index) const noexcept -> std::enable_if_t< std::is_integral_v< Int >, std::add_const_t< value_type > & >
Array subscript operator.
Definition: span.hpp:390
static constexpr auto align_up(basic_address< IsConst > addr, span_size_t align, span_size_t max) noexcept -> basic_address< IsConst >
Aligns a memory address up to the specified alignment.
Definition: address.hpp:266
basic_address< true > const_address
Type alias for const memory address values.
Definition: address.hpp:199
static constexpr auto span_align_of(type_identity< T >={}) noexcept
Returns the byte alignment of type T as span_size_t.
Definition: types.hpp:66
static constexpr auto span_size_of(type_identity< T >={}) noexcept
Returns the byte size of type T as span_size_t.
Definition: types.hpp:73
constexpr auto is_zero_terminated() const noexcept -> bool
Indicates that the span is terminated with value T(0) if applicable.
Definition: span.hpp:240
auto is_aligned_as() const noexcept -> bool
Checks if the start of the span is aligned as the alignment of X.
Definition: span.hpp:295
auto reset(pointer b, pointer e) noexcept -> auto &
Resets this span with a pair or pointers.
Definition: span.hpp:215
auto encloses(const_address a) const noexcept -> bool
Indicates if this span encloses the specified address.
Definition: span.hpp:301
constexpr auto ref(size_type index) const noexcept -> std::add_const_t< value_type > &
Returns a const reference to value at the specified index.
Definition: span.hpp:324
static constexpr auto align_down(basic_address< IsConst > addr, span_size_t align, span_size_t max) noexcept -> basic_address< IsConst >
Aligns a memory address down to the specified alignment.
Definition: address.hpp:292
static constexpr auto accomodate(basic_span< B, P, S > blk, type_identity< T > tid={}) noexcept -> basic_span< std::add_const_t< T >, rebind_pointer_t< P, T >, S >
Returns a span, rebinding the element type (typically from basic_block).
Definition: span.hpp:563
constexpr auto begin_addr() const noexcept -> address_type
Returns the memory address of the start of the span.
Definition: span.hpp:284
constexpr basic_span(address_type addr, size_type len) noexcept
Construction from memory address and length.
Definition: span.hpp:131
static constexpr auto align_down_to(basic_address< std::is_const_v< T >> addr, type_identity< T >={}, span_size_t align=span_align_of< T >(), span_size_t max=span_size_of< T >()) noexcept
Aligns a memory address down to the required alignment of type T.
Definition: address.hpp:337
constexpr auto size() const noexcept -> size_type
Returns the number of elements in the span.
Definition: span.hpp:246
Helper class detecting if type T has x.size() member function.
Definition: span.hpp:51
constexpr bool has_span_data_member_v
Trait indicating if type T has x.size() member function.
Definition: span.hpp:83
const gl_types::ubyte_type value_type
The element value type.
Definition: span.hpp:105
static constexpr auto cover(C &container) noexcept
Creates a mutable span covering a compatible contiguous container.
Definition: span.hpp:523
Template type used mostly for function type-tag dispatching.
Definition: type_identity.hpp:19
constexpr basic_span(address_type ba, address_type be) noexcept
Construction from a pair of memory addresses.
Definition: span.hpp:141
const gl_types::ubyte_type * iterator
The iterator type.
Definition: span.hpp:117
constexpr auto end_addr() const noexcept -> address_type
Returns the memory address past the end of the span.
Definition: span.hpp:289
auto operator=(basic_span< T, P, S > that) noexcept -> auto &
Converting copy assignment from span of compatible elements.
Definition: span.hpp:192
static constexpr auto extract_or(basic_span< T, P, S > spn, T &fallback) noexcept -> T &
Overload of extract_or for spans. Returns the first element,.
Definition: span.hpp:582
Helper class detecting if type T has x.data() member function.
Definition: span.hpp:76
const gl_types::ubyte_type * const_iterator
The const iterator type.
Definition: span.hpp:120
auto front() const noexcept -> const value_type &
Returns a const reference to value at the front of the span.
Definition: span.hpp:338
auto overlaps(const basic_span< Ts, Ps, Ss > &that) const noexcept -> bool
Indicates if this span overlaps with another span.
Definition: span.hpp:317
static constexpr auto absolute(basic_span< T, P, S > spn) noexcept -> basic_span< T, T *, S >
Converts argument to span using a native pointer type.
Definition: span.hpp:407
auto back() const noexcept -> const value_type &
Returns a const reference to value at the back of the span.
Definition: span.hpp:352
auto element(Int index) noexcept -> std::enable_if_t< std::is_integral_v< Int >, value_type & >
Returns a reference to value at the specified index.
Definition: span.hpp:374