1 /**
2  * \file wasmtime/span.hh
3  */
4 
5 #ifndef WASMTIME_SPAN_HH
6 #define WASMTIME_SPAN_HH
7 
8 #ifdef __has_include
9 #if __has_include(<span>)
10 #include <span>
11 #endif
12 #endif
13 
14 #ifndef __cpp_lib_span
15 #include <cstddef>
16 #include <limits>
17 #include <type_traits>
18 #endif
19 
20 namespace wasmtime {
21 
22 #ifdef __cpp_lib_span
23 
24 /// \brief Alias to C++20 std::span when it is available
25 template <typename T, std::size_t Extent = std::dynamic_extent>
26 using Span = std::span<T, Extent>;
27 
28 #else
29 
30 /// \brief Means number of elements determined at runtime
31 inline constexpr size_t dynamic_extent =
32     std::numeric_limits<std::size_t>::max();
33 
34 /**
35  * \brief Span class used when c++20 is not available
36  * @tparam T Type of data
37  * @tparam Extent Static size of data referred by Span class
38  */
39 template <typename T, std::size_t Extent = dynamic_extent> class Span;
40 
41 /// \brief Check whether a type is `Span`
42 template <typename T> struct IsSpan : std::false_type {};
43 
44 template <typename T, std::size_t Extent>
45 struct IsSpan<Span<T, Extent>> : std::true_type {};
46 
47 template <typename T, std::size_t Extent> class Span {
48   static_assert(Extent == dynamic_extent,
49                 "The current implementation supports dynamic-extent span only");
50 
51 public:
52   /// \brief Type used to iterate over this span (a raw pointer)
53   using iterator = T *;
54 
55   /// \brief Constructor of Span class
56   Span(T *t, std::size_t n) : ptr_{t}, size_{n} {}
57 
58   /// \brief Constructor of Span class for containers
59   template <typename C,
60             std::enable_if_t<
61                 !IsSpan<C>::value &&
62                     std::is_pointer_v<decltype(std::declval<C &>().data())> &&
63                     std::is_convertible_v<
64                         std::remove_pointer_t<
65                             decltype(std::declval<C &>().data())> (*)[],
66                         T (*)[]> &&
67                     std::is_convertible_v<decltype(std::declval<C>().size()),
68                                           std::size_t>,
69                 int> = 0>
70   Span(C &range) : ptr_{range.data()}, size_{range.size()} {}
71 
72   /// \brief Returns item by index
73   T &operator[](ptrdiff_t idx) const {
74     return ptr_[idx]; // NOLINT
75   }
76 
77   /// \brief Returns pointer to data
78   T *data() const { return ptr_; }
79 
80   /// \brief Returns number of data that referred by Span class
81   std::size_t size() const { return size_; }
82 
83   /// \brief Returns begin iterator
84   iterator begin() const { return ptr_; }
85 
86   /// \brief Returns end iterator
87   iterator end() const {
88     return ptr_ + size_; // NOLINT
89   }
90 
91   /// \brief Returns size in bytes
92   std::size_t size_bytes() const { return sizeof(T) * size_; }
93 
94 private:
95   T *ptr_;
96   std::size_t size_;
97 };
98 
99 #endif
100 
101 } // namespace wasmtime
102 
103 #endif // WASMTIME_SPAN_HH
104