From a141c401f78467bc15f62882fca5d55a007cacbb Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Mon, 17 Feb 2025 00:21:48 +0100 Subject: Reorganize everything --- asl/types/span.hpp | 235 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 asl/types/span.hpp (limited to 'asl/types/span.hpp') diff --git a/asl/types/span.hpp b/asl/types/span.hpp new file mode 100644 index 0000000..b258708 --- /dev/null +++ b/asl/types/span.hpp @@ -0,0 +1,235 @@ +#pragma once + +#include "asl/base/meta.hpp" +#include "asl/base/assert.hpp" +#include "asl/base/annotations.hpp" +#include "asl/memory/layout.hpp" + +namespace asl +{ + +static constexpr isize_t dynamic_size = -1; + +template +class contiguous_iterator +{ + T* m_ptr; + +public: + constexpr explicit contiguous_iterator(T* ptr) : m_ptr{ptr} {} + + constexpr bool operator==(const contiguous_iterator& other) const + { + return other.m_ptr == m_ptr; + } + + constexpr contiguous_iterator& operator++() + { + m_ptr += 1; + return *this; + } + + constexpr contiguous_iterator operator++(int) + { + return contiguous_iterator{ exchange(m_ptr, m_ptr + 1) }; + } + + constexpr T& operator*() const { return *m_ptr; } + + constexpr T* operator->() const { return m_ptr; } +}; + +template +contiguous_iterator(T) -> contiguous_iterator; + +template +class span +{ + static constexpr bool is_dynamic(isize_t size) + { + return size < 0; + } + + static constexpr bool kIsDynamic = is_dynamic(kSize); + + using SizeType = select_t; + + T* m_data{}; + ASL_NO_UNIQUE_ADDRESS SizeType m_size{}; + +public: + constexpr span() requires (kIsDynamic || kSize == 0) = default; + + constexpr span(T* data, isize_t size) + requires kIsDynamic + : m_data{data} + , m_size{size} + {} + + constexpr explicit span(T* data, isize_t size) + requires (!kIsDynamic) + : m_data{data} + { + ASL_ASSERT(size == kSize); + } + + template + constexpr span(T (&array)[N]) // NOLINT(*-explicit-conversions) + requires (kIsDynamic) + : m_data{array} + , m_size{N} + {} + + template + constexpr span(T (&array)[N]) // NOLINT(*-explicit-conversions) + requires (!kIsDynamic) && (N == kSize) + : m_data{array} + {} + + template + constexpr explicit(!kIsDynamic) + span(const span& other) // NOLINT(*-explicit-conversions) + requires ( + ( + kIsDynamic || + is_dynamic(kOtherSize) || + kOtherSize == kSize + ) && convertible_from + ) + : span{static_cast(other.data()), other.size()} + { + } + + constexpr span(const span&) = default; + constexpr span(span&&) = default; + + constexpr span& operator=(const span&) = default; + constexpr span& operator=(span&&) = default; + + ~span() = default; + + constexpr isize_t size() const + { + if constexpr (kIsDynamic) { return m_size; } + else { return kSize; } + } + + constexpr isize_t size_bytes() const { return size() * size_of; } + + constexpr bool is_empty() const { return size() == 0; } + + constexpr T* data() const { return m_data; } + + constexpr contiguous_iterator begin() const + { + return contiguous_iterator{m_data}; + } + + constexpr contiguous_iterator end() const + { + return contiguous_iterator{m_data + size()}; + } + + constexpr T& operator[](isize_t i) const + { + ASL_ASSERT(i >= 0 && i < size()); + return m_data[i]; // NOLINT(*-pointer-arithmetic) + } + + template + constexpr auto subspan() const + requires ( + kOffset >= 0 && + (kIsDynamic || kOffset <= kSize) && + (kIsDynamic || is_dynamic(kSubSize) || kSubSize <= kSize - kOffset) + ) + { + ASL_ASSERT(kOffset <= size()); + + if constexpr (is_dynamic(kSubSize)) + { + if constexpr (kIsDynamic) + { + return span(data() + kOffset, size() - kOffset); + } + else + { + return span(data() + kOffset, size() - kOffset); + } + } + else + { + ASL_ASSERT(kSubSize <= size() - kOffset); + return span(data() + kOffset, kSubSize); + } + } + + constexpr span subspan(isize_t offset) const + { + ASL_ASSERT(offset <= size()); + return span{ data() + offset, size() - offset }; + } + + constexpr span subspan(isize_t offset, isize_t sub_size) const + { + ASL_ASSERT(offset <= size() && !is_dynamic(sub_size)); + ASL_ASSERT(sub_size <= size() - offset); + return span{ data() + offset, sub_size }; + } + + template + constexpr auto first() const + requires ( + kSubSize >= 0 && + (kIsDynamic || kSubSize <= kSize) + ) + { + ASL_ASSERT(kSubSize <= size()); + return span{ data(), kSubSize }; + } + + constexpr span first(isize_t sub_size) const + { + ASL_ASSERT(sub_size >= 0 && sub_size <= size()); + return span{ data(), sub_size }; + } + + template + constexpr auto last() const + requires ( + kSubSize >= 0 && + (kIsDynamic || kSubSize <= kSize) + ) + { + ASL_ASSERT(kSubSize <= size()); + return span{ data() + size() - kSubSize, kSubSize }; + } + + constexpr span last(isize_t sub_size) const + { + ASL_ASSERT(sub_size >= 0 && sub_size <= size()); + return span{ data() + size() - sub_size, sub_size }; + } +}; + +template +inline span as_bytes(span s) +{ + return span( + reinterpret_cast(s.data()), + s.size_bytes()); +} + +template +inline span as_mutable_bytes(span s) + requires (!is_const) +{ + return span( + reinterpret_cast(s.data()), + s.size_bytes()); +} + +template +span(T (&)[kSize]) -> span; + +} // namespace asl -- cgit