From 9c45e9c7df1efa5bc1c8e73b6eaef4726b828d3e Mon Sep 17 00:00:00 2001 From: Hannes Schulze Date: Tue, 4 Feb 2025 19:59:47 +0100 Subject: add span type --- lib/nes/common/span.hh | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 lib/nes/common/span.hh (limited to 'lib/nes/common/span.hh') diff --git a/lib/nes/common/span.hh b/lib/nes/common/span.hh new file mode 100644 index 0000000..16eb129 --- /dev/null +++ b/lib/nes/common/span.hh @@ -0,0 +1,82 @@ +#pragma once + +#include "nes/common/types.hh" + +namespace nes +{ + namespace detail + { + struct span_unchecked{}; + + inline constexpr auto span_dynamic_length = u32{ 0xFFFF }; + + template + struct remove_const + { + using type = T; + }; + + template + struct remove_const + { + using type = T; + }; + } // namespace detail + + /// Implementation of a container similar to std::span in C++20. + template + class span + { + template + friend class span; + + T* data_{ nullptr }; + u32 length_{ 0 }; + + public: + using iterator = T*; + + explicit span() + { + static_assert(Length == 0 || Length == detail::span_dynamic_length); + } + + explicit span(T* data, u32 const length) + : span{ data, length, {} } + { + static_assert(Length == detail::span_dynamic_length); + } + + template + span(T (&data)[ActualLength]) + : span{ data, ActualLength, {} } + { + static_assert(Length == ActualLength || Length == detail::span_dynamic_length); + } + + span(span::type, Length> const other) + : span{ other.data_, other.length_, {} } + { + } + + auto get_data() const -> T* { return data_; } + auto get_length() const -> u32 { return length_; } + + auto begin() const -> iterator { return data_; } + auto end() const -> iterator { return data_ + length_; } + + auto subspan(u32 const first, u32 const length) const -> span { return span{ data_ + first, length }; } + auto subspan(u32 const first) const -> span { return subspan(length_ - first); } + template + auto subspan(u32 const first) const -> span { return span{ data_ + first, OtherLength, {} }; } + + auto operator[](u32 const index) const -> T& { return data_[index]; } + + private: + explicit span(T* data, u32 const length, detail::span_unchecked) + : data_{ data } + , length_{ length } + { + } + }; +} // namespace nes \ No newline at end of file -- cgit v1.3.1