aboutsummaryrefslogtreecommitdiffstats
path: root/common/alspan.h
diff options
context:
space:
mode:
Diffstat (limited to 'common/alspan.h')
-rw-r--r--common/alspan.h105
1 files changed, 105 insertions, 0 deletions
diff --git a/common/alspan.h b/common/alspan.h
new file mode 100644
index 00000000..27584de4
--- /dev/null
+++ b/common/alspan.h
@@ -0,0 +1,105 @@
+#ifndef AL_SPAN_H
+#define AL_SPAN_H
+
+#include <cstddef>
+#include <type_traits>
+#include <initializer_list>
+
+namespace al {
+
+template<typename T>
+constexpr auto size(T &cont) -> decltype(cont.size())
+{ return cont.size(); }
+
+template<typename T>
+constexpr auto size(const T &cont) -> decltype(cont.size())
+{ return cont.size(); }
+
+template<typename T, size_t N>
+constexpr size_t size(T (&)[N]) noexcept
+{ return N; }
+
+template<typename T>
+constexpr size_t size(std::initializer_list<T> list) noexcept
+{ return list.size(); }
+
+
+template<typename T>
+constexpr auto data(T &cont) -> decltype(cont.data())
+{ return cont.data(); }
+
+template<typename T>
+constexpr auto data(const T &cont) -> decltype(cont.data())
+{ return cont.data(); }
+
+template<typename T, size_t N>
+constexpr T* data(T (&arr)[N]) noexcept
+{ return arr; }
+
+template<typename T>
+constexpr const T* data(std::initializer_list<T> list) noexcept
+{ return list.begin(); }
+
+
+template<typename T>
+class span {
+public:
+ using element_type = T;
+ using value_type = typename std::remove_cv<T>::type;
+ using index_type = size_t;
+ using difference_type = ptrdiff_t;
+
+ using pointer = T*;
+ using const_pointer = const T*;
+ using reference = T&;
+ using const_reference = const T&;
+
+ using iterator = pointer;
+ using const_iterator = const_pointer;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+ constexpr span() noexcept = default;
+ constexpr span(pointer ptr, index_type count) : mData{ptr}, mCount{count} { }
+ constexpr span(pointer first, pointer last) : mData{first}, mCount{std::distance(first, last)} { }
+ template<size_t N>
+ constexpr span(element_type (&arr)[N]) noexcept : span{al::data(arr), al::size(arr)} { }
+ template<size_t N>
+ constexpr span(std::array<value_type,N> &arr) noexcept : span{al::data(arr), al::size(arr)} { }
+ template<size_t N>
+ constexpr span(const std::array<value_type,N> &arr) noexcept : span{al::data(arr), al::size(arr)} { }
+ template<typename U>
+ constexpr span(U &cont) : span{al::data(cont), al::size(cont)} { }
+ template<typename U>
+ constexpr span(const U &cont) : span{al::data(cont), al::size(cont)} { }
+ constexpr span(const span&) noexcept = default;
+
+ span& operator=(const span &rhs) noexcept = default;
+
+ constexpr reference front() const { return mData[0]; }
+ constexpr reference back() const { return mData[mCount-1]; }
+ constexpr reference operator[](index_type idx) const { return mData[idx]; }
+ constexpr pointer data() const noexcept { return mData; }
+
+ constexpr index_type size() const noexcept { return mCount; }
+ constexpr index_type size_bytes() const noexcept { return mCount * sizeof(value_type); }
+ constexpr bool empty() const noexcept { return mCount == 0; }
+
+ constexpr iterator begin() const noexcept { return mData; }
+ constexpr iterator end() const noexcept { return mData + mCount; }
+ constexpr const_iterator cbegin() const noexcept { return mData; }
+ constexpr const_iterator cend() const noexcept { return mData + mCount; }
+
+ constexpr reverse_iterator rbegin() const noexcept { return end(); }
+ constexpr reverse_iterator rend() const noexcept { return begin(); }
+ constexpr const_reverse_iterator crbegin() const noexcept { return cend(); }
+ constexpr const_reverse_iterator crend() const noexcept { return cbegin(); }
+
+private:
+ pointer mData{nullptr};
+ index_type mCount{0u};
+};
+
+} // namespace al
+
+#endif /* AL_SPAN_H */