/* * Copyright 2013-2020 Software Radio Systems Limited * * This file is part of srsLTE. * * srsLTE is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * srsLTE is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * A copy of the GNU Affero General Public License can be found in * the LICENSE file in the top-level directory of this distribution * and at http://www.gnu.org/licenses/. * */ #ifndef SRSLTE_SPAN_H #define SRSLTE_SPAN_H #include #include #include #include #include #include namespace srslte { template class span; namespace detail { /// Helper traits used by SFINAE expressions in constructors. template struct make_void { typedef void type; }; template using void_t = typename make_void::type; template struct is_span : std::false_type {}; template struct is_span > : std::true_type {}; template struct is_std_array : std::false_type {}; template struct is_std_array > : std::true_type {}; template using remove_cvref_t = typename std::remove_cv::type>::type; template struct is_container_compatible : public std::false_type {}; template struct is_container_compatible< Container, U, void_t< // Check if the container type has data and size members. decltype(std::declval().data()), decltype(std::declval().size()), // Container should not be a span. typename std::enable_if >::value, int>::type, // Container should not be a std::array. typename std::enable_if >::value, int>::type, // Container should not be an array. typename std::enable_if >::value, int>::type, // Check type compatibility between the contained type and the span type. typename std::enable_if< std::is_convertible().data())>::type (*)[], U (*)[]>::value, int>::type> > : public std::true_type {}; } // namespace detail /// The class template span describes an object that can refer to a contiguous sequence of objects with the first /// element of the sequence at position zero. template class span { public: /// Member types. using element_type = T; using value_type = typename std::remove_cv::type; using size_type = std::size_t; using difference_type = std::ptrdiff_t; using pointer = element_type*; using const_pointer = const element_type*; using reference = element_type&; using const_reference = const element_type&; using iterator = pointer; using reverse_iterator = std::reverse_iterator; /// Constructs an empty span with data() == nullptr and size() == 0. constexpr span() noexcept = default; /// Constructs a span that is a view over the range [ptr, ptr + len). constexpr span(pointer ptr, size_type len) noexcept : ptr(ptr), len(len) {} /// Constructs a span that is a view over the range [first, last). constexpr span(pointer first, pointer last) noexcept : ptr(first), len(last - first) {} /// Constructs a span that is a view over the array arr. template constexpr span(element_type (&arr)[N]) noexcept : ptr(arr), len(N) {} /// Constructs a span that is a view over the array arr. template ::value, int>::type = 0> constexpr span(std::array& arr) noexcept : ptr(arr.data()), len(N) {} /// Constructs a span that is a view over the array arr. template ::value, int>::type = 0> constexpr span(const std::array& arr) noexcept : ptr(arr.data()), len(N) {} /// Constructs a span that is a view over the container c. template ::value, int>::type = 0> constexpr span(Container& c) noexcept : ptr(c.data()), len(c.size()) {} /// Constructs a span that is a view over the container c. template < typename Container, typename std::enable_if::value, int>::type = 0> constexpr span(const Container& c) noexcept : ptr(c.data()), len(c.size()) {} template ::value, int>::type = 0> constexpr span(const span& other) noexcept : ptr(other.data()), len(other.size()) {} span& operator=(const span& other) noexcept = default; ~span() noexcept = default; /// Returns the number of elements in the span. constexpr size_type size() const noexcept { return len; } /// Returns the size of the sequence in bytes. constexpr size_type size_bytes() const noexcept { return len * sizeof(element_type); } /// Checks if the span is empty. constexpr bool empty() const noexcept { return size() == 0; } /// Returns a reference to the first element in the span. /// NOTE: Calling front on an empty span results in undefined behavior. reference front() const { assert(!empty() && "called front with empty span"); return *data(); } /// Returns a reference to the last element in the span. /// NOTE: Calling back on an empty span results in undefined behavior. reference back() const { assert(!empty() && "called back with empty span"); return *(data() + size() - 1); } /// Returns a reference to the idx-th element of the sequence. /// NOTE: The behavior is undefined if idx is out of range. reference operator[](size_type idx) const { assert(idx < len && "index out of bounds!"); return ptr[idx]; } /// Returns a pointer to the beginning of the sequence. constexpr pointer data() const noexcept { return ptr; } /// Returns an iterator to the first element of the span. constexpr iterator begin() const noexcept { return data(); } /// Returns an iterator to the element following the last element of the span. constexpr iterator end() const noexcept { return data() + size(); } /// Returns a reverse iterator to the first element of the reversed span. constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } /// Returns a reverse iterator to the element following the last element of the reversed span. constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } /// Obtains a span that is a view over the first count elements of this span. /// NOTE: The behavior is undefined if count > size(). span first(size_type count) const { assert(count <= size() && "count is out of range"); return subspan(0, count); } /// Obtains a span that is a view over the last count elements of this span. /// NOTE: The behavior is undefined if count > size(). span last(size_type count) const { assert(count <= size() && "count is out of range"); return subspan(size() - count, count); } /// Obtains a span that is a view over the count elements of this span starting at offset offset. span subspan(size_type offset, size_type count) const { assert(count <= size() - offset && "size out of bounds!"); return {data() + offset, count}; } /// Returns true if the input span has the same elements as this. bool equals(span rhs) const { return (len == rhs.len) ? std::equal(begin(), end(), rhs.begin()) : false; } private: pointer ptr = nullptr; size_type len = 0; }; template inline bool operator==(span lhs, span rhs) { return lhs.equals(rhs); } template inline bool operator!=(span lhs, span rhs) { return not lhs.equals(rhs); } } // namespace srslte #endif // SRSLTE_SPAN_H