Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:45:07

0001 /*
0002 Copyright 2019-2023 Glen Joseph Fernandes
0003 (glenjofe@gmail.com)
0004 
0005 Distributed under the Boost Software License, Version 1.0.
0006 (http://www.boost.org/LICENSE_1_0.txt)
0007 */
0008 #ifndef BOOST_CORE_SPAN_HPP
0009 #define BOOST_CORE_SPAN_HPP
0010 
0011 #include <boost/core/detail/assert.hpp>
0012 #include <boost/core/data.hpp>
0013 #include <array>
0014 #include <iterator>
0015 #include <type_traits>
0016 
0017 namespace boost {
0018 
0019 constexpr std::size_t dynamic_extent = static_cast<std::size_t>(-1);
0020 
0021 template<class T, std::size_t E = dynamic_extent>
0022 class span;
0023 
0024 namespace detail {
0025 
0026 template<class U, class T>
0027 struct span_convertible {
0028     static constexpr bool value = std::is_convertible<U(*)[], T(*)[]>::value;
0029 };
0030 
0031 template<std::size_t E, std::size_t N>
0032 struct span_capacity {
0033     static constexpr bool value = E == boost::dynamic_extent || E == N;
0034 };
0035 
0036 template<class T, std::size_t E, class U, std::size_t N>
0037 struct span_compatible {
0038     static constexpr bool value = span_capacity<E, N>::value &&
0039         span_convertible<U, T>::value;
0040 };
0041 
0042 template<class T>
0043 using span_uncvref = typename std::remove_cv<typename
0044     std::remove_reference<T>::type>::type;
0045 
0046 template<class>
0047 struct span_is_span {
0048     static constexpr bool value = false;
0049 };
0050 
0051 template<class T, std::size_t E>
0052 struct span_is_span<boost::span<T, E> > {
0053     static constexpr bool value = true;
0054 };
0055 
0056 template<class T>
0057 struct span_is_array {
0058     static constexpr bool value = false;
0059 };
0060 
0061 template<class T, std::size_t N>
0062 struct span_is_array<std::array<T, N> > {
0063     static constexpr bool value = true;
0064 };
0065 
0066 template<class T>
0067 using span_ptr = decltype(boost::data(std::declval<T&>()));
0068 
0069 template<class, class = void>
0070 struct span_data { };
0071 
0072 template<class T>
0073 struct span_data<T,
0074     typename std::enable_if<std::is_pointer<span_ptr<T> >::value>::type> {
0075     typedef typename std::remove_pointer<span_ptr<T> >::type type;
0076 };
0077 
0078 template<class, class, class = void>
0079 struct span_has_data {
0080     static constexpr bool value = false;
0081 };
0082 
0083 template<class R, class T>
0084 struct span_has_data<R, T, typename std::enable_if<span_convertible<typename
0085     span_data<R>::type, T>::value>::type> {
0086     static constexpr bool value = true;
0087 };
0088 
0089 template<class, class = void>
0090 struct span_has_size {
0091     static constexpr bool value = false;
0092 };
0093 
0094 template<class R>
0095 struct span_has_size<R, typename
0096     std::enable_if<std::is_convertible<decltype(std::declval<R&>().size()),
0097         std::size_t>::value>::type> {
0098     static constexpr bool value = true;
0099 };
0100 
0101 template<class R, class T>
0102 struct span_is_range {
0103     static constexpr bool value = (std::is_const<T>::value ||
0104         std::is_lvalue_reference<R>::value) &&
0105         !span_is_span<span_uncvref<R> >::value &&
0106         !span_is_array<span_uncvref<R> >::value &&
0107         !std::is_array<span_uncvref<R> >::value &&
0108         span_has_data<R, T>::value &&
0109         span_has_size<R>::value;
0110 };
0111 
0112 template<std::size_t E, std::size_t N>
0113 struct span_implicit {
0114     static constexpr bool value = E == boost::dynamic_extent ||
0115         N != boost::dynamic_extent;
0116 };
0117 
0118 template<class T, std::size_t E, class U, std::size_t N>
0119 struct span_copyable {
0120     static constexpr bool value = (N == boost::dynamic_extent ||
0121         span_capacity<E, N>::value) && span_convertible<U, T>::value;
0122 };
0123 
0124 template<std::size_t E, std::size_t O>
0125 struct span_sub {
0126     static constexpr std::size_t value = E == boost::dynamic_extent ?
0127         boost::dynamic_extent : E - O;
0128 };
0129 
0130 template<class T, std::size_t E>
0131 struct span_store {
0132     constexpr span_store(T* p_, std::size_t) noexcept
0133         : p(p_) { }
0134     static constexpr std::size_t n = E;
0135     T* p;
0136 };
0137 
0138 template<class T>
0139 struct span_store<T, boost::dynamic_extent> {
0140     constexpr span_store(T* p_, std::size_t n_) noexcept
0141         : p(p_)
0142         , n(n_) { }
0143     T* p;
0144     std::size_t n;
0145 };
0146 
0147 template<class T, std::size_t E>
0148 struct span_bytes {
0149     static constexpr std::size_t value = sizeof(T) * E;
0150 };
0151 
0152 template<class T>
0153 struct span_bytes<T, boost::dynamic_extent> {
0154     static constexpr std::size_t value = boost::dynamic_extent;
0155 };
0156 
0157 } /* detail */
0158 
0159 template<class T, std::size_t E>
0160 class span {
0161 public:
0162     typedef T element_type;
0163     typedef typename std::remove_cv<T>::type value_type;
0164     typedef std::size_t size_type;
0165     typedef std::ptrdiff_t difference_type;
0166     typedef T* pointer;
0167     typedef const T* const_pointer;
0168     typedef T& reference;
0169     typedef const T& const_reference;
0170     typedef T* iterator;
0171     typedef const T* const_iterator;
0172     typedef std::reverse_iterator<T*> reverse_iterator;
0173     typedef std::reverse_iterator<const T*> const_reverse_iterator;
0174 
0175     static constexpr std::size_t extent = E;
0176 
0177     template<std::size_t N = E,
0178         typename std::enable_if<N == dynamic_extent || N == 0, int>::type = 0>
0179     constexpr span() noexcept
0180         : s_(0, 0) { }
0181 
0182     template<class I,
0183         typename std::enable_if<E == dynamic_extent &&
0184             detail::span_convertible<I, T>::value, int>::type = 0>
0185     constexpr span(I* f, size_type c)
0186         : s_(f, c) { }
0187 
0188     template<class I,
0189         typename std::enable_if<E != dynamic_extent &&
0190             detail::span_convertible<I, T>::value, int>::type = 0>
0191     explicit constexpr span(I* f, size_type c)
0192         : s_(f, c) { }
0193 
0194     template<class I, class L,
0195         typename std::enable_if<E == dynamic_extent &&
0196             detail::span_convertible<I, T>::value, int>::type = 0>
0197     constexpr span(I* f, L* l)
0198         : s_(f, l - f) { }
0199 
0200     template<class I, class L,
0201         typename std::enable_if<E != dynamic_extent &&
0202             detail::span_convertible<I, T>::value, int>::type = 0>
0203     explicit constexpr span(I* f, L* l)
0204         : s_(f, l - f) { }
0205 
0206     template<std::size_t N,
0207         typename std::enable_if<detail::span_capacity<E, N>::value,
0208             int>::type = 0>
0209     constexpr span(typename std::enable_if<true, T>::type (&a)[N]) noexcept
0210         : s_(a, N) { }
0211 
0212     template<class U, std::size_t N,
0213         typename std::enable_if<detail::span_compatible<T, E, U, N>::value,
0214             int>::type = 0>
0215     constexpr span(std::array<U, N>& a) noexcept
0216         : s_(a.data(), N) { }
0217 
0218     template<class U, std::size_t N,
0219         typename std::enable_if<detail::span_compatible<T, E, const U,
0220             N>::value, int>::type = 0>
0221     constexpr span(const std::array<U, N>& a) noexcept
0222         : s_(a.data(), N) { }
0223 
0224     template<class R,
0225         typename std::enable_if<E == dynamic_extent &&
0226             detail::span_is_range<R, T>::value, int>::type = 0>
0227     constexpr span(R&& r) noexcept(noexcept(boost::data(r)) &&
0228         noexcept(r.size()))
0229         : s_(boost::data(r), r.size()) { }
0230 
0231     template<class R,
0232         typename std::enable_if<E != dynamic_extent &&
0233             detail::span_is_range<R, T>::value, int>::type = 0>
0234     explicit constexpr span(R&& r) noexcept(noexcept(boost::data(r)) &&
0235         noexcept(r.size()))
0236         : s_(boost::data(r), r.size()) { }
0237 
0238     template<class U, std::size_t N,
0239         typename std::enable_if<detail::span_implicit<E, N>::value &&
0240             detail::span_copyable<T, E, U, N>::value, int>::type = 0>
0241     constexpr span(const span<U, N>& s) noexcept
0242         : s_(s.data(), s.size()) { }
0243 
0244     template<class U, std::size_t N,
0245         typename std::enable_if<!detail::span_implicit<E, N>::value &&
0246             detail::span_copyable<T, E, U, N>::value, int>::type = 0>
0247     explicit constexpr span(const span<U, N>& s) noexcept
0248         : s_(s.data(), s.size()) { }
0249 
0250     template<std::size_t C>
0251     constexpr span<T, C> first() const {
0252         static_assert(C <= E, "Count <= Extent");
0253         return span<T, C>(s_.p, C);
0254     }
0255 
0256     template<std::size_t C>
0257     constexpr span<T, C> last() const {
0258         static_assert(C <= E, "Count <= Extent");
0259         return span<T, C>(s_.p + (s_.n - C), C);
0260     }
0261 
0262     template<std::size_t O, std::size_t C = dynamic_extent>
0263     constexpr typename std::enable_if<C == dynamic_extent,
0264         span<T, detail::span_sub<E, O>::value> >::type subspan() const {
0265         static_assert(O <= E, "Offset <= Extent");
0266         return span<T, detail::span_sub<E, O>::value>(s_.p + O, s_.n - O);
0267     }
0268 
0269     template<std::size_t O, std::size_t C = dynamic_extent>
0270     constexpr typename std::enable_if<C != dynamic_extent,
0271         span<T, C> >::type subspan() const {
0272         static_assert(O <= E && C <= E - O,
0273             "Offset <= Extent && Count <= Extent - Offset");
0274         return span<T, C>(s_.p + O, C);
0275     }
0276 
0277     constexpr span<T, dynamic_extent> first(size_type c) const {
0278         return BOOST_CORE_DETAIL_ASSERT(c <= size()),
0279             span<T, dynamic_extent>(s_.p, c);
0280     }
0281 
0282     constexpr span<T, dynamic_extent> last(size_type c) const {
0283         return BOOST_CORE_DETAIL_ASSERT(c <= size()),
0284             span<T, dynamic_extent>(s_.p + (s_.n - c), c);
0285     }
0286 
0287     constexpr span<T, dynamic_extent> subspan(size_type o,
0288         size_type c = dynamic_extent) const {
0289         return BOOST_CORE_DETAIL_ASSERT(o <= size() &&
0290                 (c == dynamic_extent || c + o <= size())),
0291             span<T, dynamic_extent>(s_.p + o,
0292                 c == dynamic_extent ? s_.n - o : c);
0293     }
0294 
0295     constexpr size_type size() const noexcept {
0296         return s_.n;
0297     }
0298 
0299     constexpr size_type size_bytes() const noexcept {
0300         return s_.n * sizeof(T);
0301     }
0302 
0303     constexpr bool empty() const noexcept {
0304         return s_.n == 0;
0305     }
0306 
0307     constexpr reference operator[](size_type i) const {
0308         return BOOST_CORE_DETAIL_ASSERT(i < size()), s_.p[i];
0309     }
0310 
0311     constexpr reference front() const {
0312         return BOOST_CORE_DETAIL_ASSERT(!empty()), *s_.p;
0313     }
0314 
0315     constexpr reference back() const {
0316         return BOOST_CORE_DETAIL_ASSERT(!empty()), s_.p[s_.n - 1];
0317     }
0318 
0319     constexpr pointer data() const noexcept {
0320         return s_.p;
0321     }
0322 
0323     constexpr iterator begin() const noexcept {
0324         return s_.p;
0325     }
0326 
0327     constexpr iterator end() const noexcept {
0328         return s_.p + s_.n;
0329     }
0330 
0331     constexpr reverse_iterator rbegin() const noexcept {
0332         return reverse_iterator(s_.p + s_.n);
0333     }
0334 
0335     constexpr reverse_iterator rend() const noexcept {
0336         return reverse_iterator(s_.p);
0337     }
0338 
0339     constexpr const_iterator cbegin() const noexcept {
0340         return s_.p;
0341     }
0342 
0343     constexpr const_iterator cend() const noexcept {
0344         return s_.p + s_.n;
0345     }
0346 
0347     constexpr const_reverse_iterator crbegin() const noexcept {
0348         return const_reverse_iterator(s_.p + s_.n);
0349     }
0350 
0351     constexpr const_reverse_iterator crend() const noexcept {
0352         return const_reverse_iterator(s_.p);
0353     }
0354 
0355 private:
0356     detail::span_store<T, E> s_;
0357 };
0358 
0359 #if defined(BOOST_NO_CXX17_INLINE_VARIABLES)
0360 template<class T, std::size_t E>
0361 constexpr std::size_t span<T, E>::extent;
0362 #endif
0363 
0364 #ifdef __cpp_deduction_guides
0365 template<class I, class L>
0366 span(I*, L) -> span<I>;
0367 
0368 template<class T, std::size_t N>
0369 span(T(&)[N]) -> span<T, N>;
0370 
0371 template<class T, std::size_t N>
0372 span(std::array<T, N>&) -> span<T, N>;
0373 
0374 template<class T, std::size_t N>
0375 span(const std::array<T, N>&) -> span<const T, N>;
0376 
0377 template<class R>
0378 span(R&&) -> span<typename detail::span_data<R>::type>;
0379 
0380 template<class T, std::size_t E>
0381 span(span<T, E>) -> span<T, E>;
0382 #endif
0383 
0384 #ifdef __cpp_lib_byte
0385 template<class T, std::size_t E>
0386 inline span<const std::byte, detail::span_bytes<T, E>::value>
0387 as_bytes(span<T, E> s) noexcept
0388 {
0389     return span<const std::byte, detail::span_bytes<T,
0390         E>::value>(reinterpret_cast<const std::byte*>(s.data()),
0391             s.size_bytes());
0392 }
0393 
0394 template<class T, std::size_t E>
0395 inline typename std::enable_if<!std::is_const<T>::value,
0396     span<std::byte, detail::span_bytes<T, E>::value> >::type
0397 as_writable_bytes(span<T, E> s) noexcept
0398 {
0399     return span<std::byte, detail::span_bytes<T,
0400         E>::value>(reinterpret_cast<std::byte*>(s.data()), s.size_bytes());
0401 }
0402 #endif
0403 
0404 } /* boost */
0405 
0406 #endif