- Simplified the usage of span now with implicit constructors as it should be.

- Added overload for generic containers that have size and data members like vector.
- Removed unnecessary uses of make_span.
master
faluco 4 years ago committed by Francisco Paisana
parent 158edd4fe7
commit 072e84cec8

@ -33,12 +33,53 @@ namespace srslte {
/// The class template span describes an object that can refer to a contiguous sequence of objects with the first /// 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. /// element of the sequence at position zero.
/// It is encouraged to use the make_span() helper functions for creating new spans instead of using the constructors
/// directly. This way is more explicit in code and makes the developer think first to make sure the lifetime of the
/// sequence outlasts the new created span.
template <typename T> template <typename T>
class span class span
{ {
/// Helper traits used by SFINAE expressions in constructors.
template <typename... Ts>
struct make_void {
typedef void type;
};
template <typename... Ts>
using void_t = typename make_void<Ts...>::type;
template <typename U>
struct is_span : std::false_type {};
template <typename U>
struct is_span<span<U> > : std::true_type {};
template <typename U>
struct is_std_array : std::false_type {};
template <typename U, std::size_t N>
struct is_std_array<std::array<U, N> > : std::true_type {};
template <typename U>
using remove_cvref_t = typename std::remove_cv<typename std::remove_reference<U>::type>::type;
template <class Container, class U, class = void>
struct is_container_compatible : public std::false_type {};
template <class Container, class U>
struct is_container_compatible<
Container,
U,
void_t<
// Check if the container type has data and size members.
decltype(std::declval<Container>().data()),
decltype(std::declval<Container>().size()),
// Container should not be a span.
typename std::enable_if<!is_span<remove_cvref_t<Container> >::value, int>::type,
// Container should not be a std::array.
typename std::enable_if<!is_std_array<remove_cvref_t<Container> >::value, int>::type,
// Container should not be an array.
typename std::enable_if<!std::is_array<remove_cvref_t<Container> >::value, int>::type,
// Check type compatibility between the contained type and the span type.
typename std::enable_if<
std::is_convertible<typename std::remove_pointer<decltype(std::declval<Container>().data())>::type (*)[],
U (*)[]>::value,
int>::type> > : public std::true_type {};
public: public:
/// Member types. /// Member types.
using element_type = T; using element_type = T;
@ -56,10 +97,10 @@ public:
constexpr span() noexcept = default; constexpr span() noexcept = default;
/// Constructs a span that is a view over the range [ptr, ptr + len). /// Constructs a span that is a view over the range [ptr, ptr + len).
constexpr explicit span(pointer ptr, size_type len) noexcept : ptr(ptr), len(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). /// Constructs a span that is a view over the range [first, last).
constexpr explicit span(pointer first, pointer last) noexcept : ptr(first), len(last - first) {} constexpr span(pointer first, pointer last) noexcept : ptr(first), len(last - first) {}
/// Constructs a span that is a view over the array arr. /// Constructs a span that is a view over the array arr.
template <std::size_t N> template <std::size_t N>
@ -80,6 +121,18 @@ public:
constexpr span(const std::array<U, N>& arr) noexcept : ptr(arr.data()), len(N) constexpr span(const std::array<U, N>& arr) noexcept : ptr(arr.data()), len(N)
{} {}
/// Constructs a span that is a view over the container c.
template <typename Container,
typename std::enable_if<is_container_compatible<Container, element_type>::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<is_container_compatible<const Container, element_type>::value, int>::type = 0>
constexpr span(const Container& c) noexcept : ptr(c.data()), len(c.size())
{}
template <typename U, typename std::enable_if<std::is_convertible<U (*)[], element_type (*)[]>::value, int>::type = 0> template <typename U, typename std::enable_if<std::is_convertible<U (*)[], element_type (*)[]>::value, int>::type = 0>
constexpr span(const span<U>& other) noexcept : ptr(other.data()), len(other.size()) constexpr span(const span<U>& other) noexcept : ptr(other.data()), len(other.size())
{} {}
@ -156,7 +209,7 @@ public:
span<element_type> subspan(size_type offset, size_type count) const span<element_type> subspan(size_type offset, size_type count) const
{ {
assert(count <= size() - offset && "size out of bounds!"); assert(count <= size() - offset && "size out of bounds!");
return span{data() + offset, count}; return {data() + offset, count};
} }
/// Returns true if the input span has the same elements as this. /// Returns true if the input span has the same elements as this.
@ -179,40 +232,6 @@ inline bool operator!=(span<T> lhs, span<T> rhs)
return not lhs.equals(rhs); return not lhs.equals(rhs);
} }
///
/// Helpers to construct span objects from different types of contiguous containers.
///
template <typename T, std::size_t N>
inline span<T> make_span(T (&arr)[N])
{
return span<T>{arr};
}
template <typename T, std::size_t N>
inline span<T> make_span(std::array<T, N>& arr)
{
return span<T>{arr};
}
template <typename T, std::size_t N>
inline span<const T> make_span(const std::array<T, N>& arr)
{
return span<const T>{arr};
}
template <typename T>
inline span<T> make_span(std::vector<T>& v)
{
return span<T>{v.data(), v.size()};
}
template <typename T>
inline span<const T> make_span(const std::vector<T>& v)
{
return span<const T>{v.data(), v.size()};
}
} // namespace srslte } // namespace srslte
#endif // SRSLTE_SPAN_H #endif // SRSLTE_SPAN_H

@ -27,7 +27,7 @@ int test_span_access()
std::array<int, 7> values{1, 2, 3, 4, 5, 6, 7}; std::array<int, 7> values{1, 2, 3, 4, 5, 6, 7};
{ {
auto view = srslte::make_span(values); srslte::span<int> view = values;
// access operators // access operators
TESTASSERT(view.size() == 7); TESTASSERT(view.size() == 7);
@ -56,7 +56,7 @@ int test_span_conversion()
{ {
// TEST: changing individual values // TEST: changing individual values
auto v = srslte::make_span(values), v2 = srslte::make_span(values2); srslte::span<int> v = values, v2 = values2;
TESTASSERT(v == v2); TESTASSERT(v == v2);
v[0] = 3; v[0] = 3;
@ -68,7 +68,7 @@ int test_span_conversion()
{ {
// TEST: const context // TEST: const context
const auto v = srslte::make_span(values), v2 = srslte::make_span(values2); const srslte::span<int> v = values, v2 = values2;
TESTASSERT(v != v2); TESTASSERT(v != v2);
TESTASSERT(v[0] == 3); TESTASSERT(v[0] == 3);
TESTASSERT(v2[0] == 2); TESTASSERT(v2[0] == 2);
@ -78,8 +78,8 @@ int test_span_conversion()
{ {
// TEST: raw arrays // TEST: raw arrays
int carray[] = {2, 3, 4, 5, 6, 7, 8}; int carray[] = {2, 3, 4, 5, 6, 7, 8};
auto v = srslte::make_span(values), v2 = srslte::make_span(carray); srslte::span<int> v = values, v2 = carray;
TESTASSERT(v == v2); TESTASSERT(v == v2);
TESTASSERT(v2.size() == v.size()); TESTASSERT(v2.size() == v.size());
} }

@ -430,7 +430,7 @@ int test_s1ap_mobility(mobility_test_params test_params)
0x01, 0x48, 0x04, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0xa0, 0x07, 0xa0, 0x01, 0x48, 0x04, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0xa0, 0x07, 0xa0,
0x10, 0x00, 0x01, 0x00, 0x05, 0x00, 0xa7, 0xd0, 0xc1, 0xf6, 0xaf, 0x3e, 0x12, 0xcc, 0x10, 0x00, 0x01, 0x00, 0x05, 0x00, 0xa7, 0xd0, 0xc1, 0xf6, 0xaf, 0x3e, 0x12, 0xcc,
0x86, 0x0d, 0x30, 0x00, 0x0b, 0x5a, 0x02, 0x17, 0x86, 0x00, 0x05, 0xa0, 0x20}; 0x86, 0x0d, 0x30, 0x00, 0x0b, 0x5a, 0x02, 0x17, 0x86, 0x00, 0x05, 0xa0, 0x20};
test_helpers::copy_msg_to_buffer(pdu, srslte::make_span(ho_cmd_rrc_container)); test_helpers::copy_msg_to_buffer(pdu, ho_cmd_rrc_container);
TESTASSERT(s1ap.last_enb_status.rnti != tester.rnti); TESTASSERT(s1ap.last_enb_status.rnti != tester.rnti);
tester.rrc.ho_preparation_complete(tester.rnti, true, std::move(pdu)); tester.rrc.ho_preparation_complete(tester.rnti, true, std::move(pdu));
TESTASSERT(s1ap.last_enb_status.status_present); TESTASSERT(s1ap.last_enb_status.status_present);

@ -228,7 +228,7 @@ int bring_rrc_to_reconf_state(srsenb::rrc& rrc, srslte::timer_handler& timers, u
// Send RRCConnectionRequest // Send RRCConnectionRequest
uint8_t rrc_conn_request[] = {0x40, 0x12, 0xf6, 0xfb, 0xe2, 0xc6}; uint8_t rrc_conn_request[] = {0x40, 0x12, 0xf6, 0xfb, 0xe2, 0xc6};
copy_msg_to_buffer(pdu, srslte::make_span(rrc_conn_request)); copy_msg_to_buffer(pdu, rrc_conn_request);
rrc.write_pdu(rnti, 0, std::move(pdu)); rrc.write_pdu(rnti, 0, std::move(pdu));
timers.step_all(); timers.step_all();
rrc.tti_clock(); rrc.tti_clock();
@ -237,7 +237,7 @@ int bring_rrc_to_reconf_state(srsenb::rrc& rrc, srslte::timer_handler& timers, u
uint8_t rrc_conn_setup_complete[] = {0x20, 0x00, 0x40, 0x2e, 0x90, 0x50, 0x49, 0xe8, 0x06, 0x0e, 0x82, 0xa2, uint8_t rrc_conn_setup_complete[] = {0x20, 0x00, 0x40, 0x2e, 0x90, 0x50, 0x49, 0xe8, 0x06, 0x0e, 0x82, 0xa2,
0x17, 0xec, 0x13, 0xe2, 0x0f, 0x00, 0x02, 0x02, 0x5e, 0xdf, 0x7c, 0x58, 0x17, 0xec, 0x13, 0xe2, 0x0f, 0x00, 0x02, 0x02, 0x5e, 0xdf, 0x7c, 0x58,
0x05, 0xc0, 0xc0, 0x00, 0x08, 0x04, 0x03, 0xa0, 0x23, 0x23, 0xc0}; 0x05, 0xc0, 0xc0, 0x00, 0x08, 0x04, 0x03, 0xa0, 0x23, 0x23, 0xc0};
copy_msg_to_buffer(pdu, srslte::make_span(rrc_conn_setup_complete)); copy_msg_to_buffer(pdu, rrc_conn_setup_complete);
rrc.write_pdu(rnti, 1, std::move(pdu)); rrc.write_pdu(rnti, 1, std::move(pdu));
timers.step_all(); timers.step_all();
rrc.tti_clock(); rrc.tti_clock();
@ -267,7 +267,7 @@ int bring_rrc_to_reconf_state(srsenb::rrc& rrc, srslte::timer_handler& timers, u
// Send SecurityModeComplete // Send SecurityModeComplete
uint8_t sec_mode_complete[] = {0x28, 0x00}; uint8_t sec_mode_complete[] = {0x28, 0x00};
copy_msg_to_buffer(pdu, srslte::make_span(sec_mode_complete)); copy_msg_to_buffer(pdu, sec_mode_complete);
rrc.write_pdu(rnti, 1, std::move(pdu)); rrc.write_pdu(rnti, 1, std::move(pdu));
timers.step_all(); timers.step_all();
rrc.tti_clock(); rrc.tti_clock();
@ -275,14 +275,14 @@ int bring_rrc_to_reconf_state(srsenb::rrc& rrc, srslte::timer_handler& timers, u
// send UE cap info // send UE cap info
uint8_t ue_cap_info[] = {0x38, 0x01, 0x01, 0x0c, 0x98, 0x00, 0x00, 0x18, 0x00, 0x0f, uint8_t ue_cap_info[] = {0x38, 0x01, 0x01, 0x0c, 0x98, 0x00, 0x00, 0x18, 0x00, 0x0f,
0x30, 0x20, 0x80, 0x00, 0x01, 0x00, 0x0e, 0x01, 0x00, 0x00}; 0x30, 0x20, 0x80, 0x00, 0x01, 0x00, 0x0e, 0x01, 0x00, 0x00};
copy_msg_to_buffer(pdu, srslte::make_span(ue_cap_info)); copy_msg_to_buffer(pdu, ue_cap_info);
rrc.write_pdu(rnti, 1, std::move(pdu)); rrc.write_pdu(rnti, 1, std::move(pdu));
timers.step_all(); timers.step_all();
rrc.tti_clock(); rrc.tti_clock();
// RRCConnectionReconfiguration was sent. Send RRCConnectionReconfigurationComplete // RRCConnectionReconfiguration was sent. Send RRCConnectionReconfigurationComplete
uint8_t rrc_conn_reconf_complete[] = {0x10, 0x00}; uint8_t rrc_conn_reconf_complete[] = {0x10, 0x00};
copy_msg_to_buffer(pdu, srslte::make_span(rrc_conn_reconf_complete)); copy_msg_to_buffer(pdu, rrc_conn_reconf_complete);
rrc.write_pdu(rnti, 1, std::move(pdu)); rrc.write_pdu(rnti, 1, std::move(pdu));
timers.step_all(); timers.step_all();
rrc.tti_clock(); rrc.tti_clock();

Loading…
Cancel
Save