[libcamera-devel] [PATCH 13/23] libcamera: span: Add support for STL containers
Jacopo Mondi
jacopo at jmondi.org
Mon Jan 13 17:42:35 CET 2020
From: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
Add support for STL containers to the Span class implementation and
make it fully C++20-compliant.
Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
---
include/libcamera/span.h | 187 +++++++++++++++++++++++++++++++--------
src/libcamera/span.cpp | 115 ------------------------
2 files changed, 152 insertions(+), 150 deletions(-)
diff --git a/include/libcamera/span.h b/include/libcamera/span.h
index 3e63603f60ed..0fffad3a99db 100644
--- a/include/libcamera/span.h
+++ b/include/libcamera/span.h
@@ -9,79 +9,196 @@
#define __LIBCAMERA_SPAN_H__
#include <array>
+#include <iterator>
+#include <limits>
#include <stddef.h>
+#include <type_traits>
namespace libcamera {
+static constexpr std::size_t dynamic_extent = std::numeric_limits<std::size_t>::max();
+
+template<typename T, size_t Extent = dynamic_extent>
+class Span;
+
template<typename T>
-class Span
+class Span<T, dynamic_extent>
{
private:
+ template<typename U>
+ struct is_array : public std::false_type {
+ };
+
+ template<typename U, std::size_t N>
+ struct is_array<std::array<U, N>> : public std::true_type {
+ };
+
+ template<typename U>
+ struct is_span : public std::false_type {
+ };
+
+ template<typename U, std::size_t Extent>
+ struct is_span<Span<U, Extent>> : public std::true_type {
+ };
+
+ template<bool B, class U = void>
+ using enable_if_t = typename std::enable_if<B, U>::type;
+
+ template<typename U>
+ using remove_pointer_t = typename std::remove_pointer<U>::type;
+
+public:
+ using element_type = T;
+ using value_type = typename std::remove_cv<T>::type;
+ using size_type = std::size_t;
+ using different_type = std::ptrdiff_t;
+ using pointer = T *;
+ using const_pointer = const T *;
+ using reference = T &;
+ using const_reference = const T &;
using iterator = T *;
using const_iterator = const T *;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const iterator>;
- class Storage
+ static constexpr std::size_t extent = dynamic_extent;
+
+ constexpr Span() noexcept
+ : data_(nullptr), size_(0)
{
- public:
- Storage(T *ptr, size_t size)
- : ptr_(ptr), size_(size)
- {
- }
+ }
- T *ptr() const { return ptr_; }
- size_t size() const { return size_; }
+ constexpr Span(pointer ptr, size_type count)
+ : data_(ptr), size_(count)
+ {
+ }
- private:
- T *ptr_;
- size_t size_;
- };
+ constexpr Span(pointer first, pointer last)
+ : data_(first), size_(last - first)
+ {
+ }
-public:
- Span(T &v)
- : storage_(&v, 1)
+ template<std::size_t N>
+ constexpr Span(element_type (&arr)[N],
+ enable_if_t<std::is_convertible<remove_pointer_t<decltype(arr)> (*)[],
+ element_type (*)[]>::value,
+ std::nullptr_t> = nullptr) noexcept
+ : data_(arr), size_(N)
{
}
- Span(const T &v)
- : storage_(const_cast<T *>(&v), 1)
+ template<std::size_t N>
+ constexpr Span(std::array<value_type, N> &arr,
+ enable_if_t<std::is_convertible<remove_pointer_t<decltype(arr.data())> (*)[],
+ element_type (*)[]>::value,
+ std::nullptr_t> = nullptr) noexcept
+ : data_(arr.data()), size_(N)
{
}
- Span(T *v, size_t s)
- : storage_(v, s)
+ template<std::size_t N>
+ constexpr Span(const std::array<value_type, N> &arr) noexcept
+ : data_(arr.data()), size_(N)
{
}
- Span(const T *v, size_t s)
- : storage_(const_cast<T *>(v), s)
+ template<class Container>
+ constexpr Span(Container &cont,
+ enable_if_t<!is_span<Container>::value &&
+ !is_array<Container>::value &&
+ !std::is_array<Container>::value &&
+ std::is_convertible<remove_pointer_t<decltype(cont.data())> (*)[],
+ element_type (*)[]>::value,
+ std::nullptr_t> = nullptr)
+ : data_(cont.data()), size_(cont.size())
{
}
- Span(std::initializer_list<T> list)
- : storage_(const_cast<T *>(list.begin()), list.size())
+ template<class Container>
+ constexpr Span(const Container &cont,
+ enable_if_t<!is_span<Container>::value &&
+ !is_array<Container>::value &&
+ !std::is_array<Container>::value &&
+ std::is_convertible<remove_pointer_t<decltype(cont.data())> (*)[],
+ element_type (*)[]>::value,
+ std::nullptr_t> = nullptr)
+ : data_(cont.data()), size_(cont.size())
{
}
- Span(const Span &other) = default;
- Span &operator=(const Span &other) = default;
+ template<class U, std::size_t N>
+ constexpr Span(const Span<U, N> &s,
+ enable_if_t<std::is_convertible<U (*)[], element_type (*)[]>::value,
+ std::nullptr_t> = nullptr) noexcept
+ : data_(s.data()), size_(s.size())
+ {
+ }
- T *data() const { return storage_.ptr(); }
- size_t size() const { return storage_.size(); }
+ constexpr Span(const Span &other) noexcept = default;
- T &operator[](unsigned int index) const
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wconstexpr-not-const"
+ constexpr Span &operator=(const Span &other) noexcept
{
- if (index >= size())
- return *(end() - 1);
- return *(data() + index);
+ return *this, data_ = other.data_, size_ = other.size_;
}
+#pragma GCC diagnostic pop
constexpr iterator begin() const { return data(); }
- constexpr iterator cbegin() const { return begin(); }
+ constexpr const_iterator cbegin() const { return begin(); }
constexpr iterator end() const { return data() + size(); }
- constexpr iterator cend() const { return end(); }
+ constexpr const_iterator cend() const { return end(); }
+ constexpr reverse_iterator rbegin() const { return data() + size() - 1; }
+ constexpr const_reverse_iterator crbegin() const { return rbegin(); }
+ constexpr reverse_iterator rend() const { return data() - 1; }
+ constexpr const_reverse_iterator crend() const { return rend(); }
+
+ constexpr reference front() const { return *data(); }
+ constexpr reference back() const { return *(data() + size() - 1); }
+ constexpr reference operator[](size_type idx) const { return data()[idx]; }
+ constexpr pointer data() const noexcept { return data_; }
+
+ constexpr size_type size() const noexcept { return size_; }
+ constexpr size_type size_bytes() const noexcept { return size_ * sizeof(element_type); }
+ constexpr bool empty() const noexcept { return size_ == 0; }
+
+ template<std::size_t Count>
+ constexpr Span<element_type, Count> first() const
+ {
+ return { data(), Count };
+ }
+
+ constexpr Span<element_type, dynamic_extent> first(std::size_t Count) const
+ {
+ return { data(), Count };
+ }
+
+ template<std::size_t Count>
+ constexpr Span<element_type, Count> last() const
+ {
+ return { data() + size() - Count, Count };
+ }
+
+ constexpr Span<element_type, dynamic_extent> last(std::size_t Count) const
+ {
+ return { data() + size() - Count, Count };
+ }
+
+ template<std::size_t Offset, std::size_t Count = dynamic_extent>
+ constexpr Span<element_type, dynamic_extent> subspan() const
+ {
+ return { data() + Offset, Count == dynamic_extent ? size() - Offset : Count };
+ }
+
+ constexpr Span<element_type, dynamic_extent>
+ subspan(std::size_t Offset, std::size_t Count = dynamic_extent) const
+ {
+ return { data() + Offset, Count == dynamic_extent ? size() - Offset : Count };
+ }
private:
- Storage storage_;
+ pointer data_;
+ size_type size_;
};
}; /* namespace libcamera */
diff --git a/src/libcamera/span.cpp b/src/libcamera/span.cpp
index 72ffdf7481c4..43391b29ec85 100644
--- a/src/libcamera/span.cpp
+++ b/src/libcamera/span.cpp
@@ -7,122 +7,7 @@
#include <libcamera/span.h>
-/**
- * \file span.h
- * \brief libcamera implementation of C++20 std::span<>
- */
-
namespace libcamera {
-/**
- * \class Span
- * \brief Representation of a sequence of contiguous objects of type T
- *
- * This class represents a sequence of fixed size of contiguous objects of
- * template type T with the first object residing in position 0.
- *
- * A Span internally consists of a pointer to raw memory and an associated
- * number of elements there located. It does not enforce any ownership on the
- * memory it represents, but it only provides a convenient, lightweight and
- * easily transportable view on such memory area.
- *
- * A Span can be constructed from a single element as well as from raw memory
- * by providing an associated size. It can be accessed by index and iterated
- * as a regular standard library container. As Span does not enforce any memory
- * ownership, destroying a Span instance does not invalidate the memory it
- * represents.
- *
- * The libcamera implementation of Span it's a simplified implementation of
- * C++20 the std::span<> class and it is no 1-to-1 compatible with it. Care
- * should be taken in not mixing usage of the two classes.
- */
-
-/**
- * \fn Span::Span(T &v)
- * \brief Contruct a Span of size 1 representing element \a v
- * \param[in] v The element represented by the Span
- */
-
-/**
- * \fn Span::Span(const T &v)
- * \brief Contruct a Span of size 1 representing the constant element \a v
- * \param[in] v The constant element represented by the Span
- */
-
-/**
- * \fn Span::Span(T *v, size_t s)
- * \brief Contruct a Span of size \a s representing elements in memory \a v
- * \param[in] v The memory area represeted by the Span
- * \param[in] s The number of elements in memory area \a v
- */
-
-/**
- * \fn Span::Span(const T *v, size_t s)
- * \brief Contruct a Span of size \a s representing elements in constant memory \a v
- * \param[in] v The constant memory area represeted by the Span
- * \param[in] s The number of elements in memory area \a v
- */
-
-/**
- * \fn Span::Span(std::initializer_list<T> list)
- * \brief Contruct a Span with an initialier list of elements
- * \param[in] list The initializer list
- */
-
-/**
- * \fn Span::Span(const Span &other)
- * \brief Contruct a Span with the content of \a other
- * \param[in] other The other Span
- */
-
-/**
- * \fn Span::operator=(const Span &other)
- * \brief Replace the content of the Span with the one from \a other
- * \param[in] other The other Span
- */
-
-/**
- * \fn Span::data()
- * \brief Retrieve a pointer to the beginning of the memory area represented by
- * the Span
- * \return A pointer to the raw memory area
- */
-
-/**
- * \fn Span::size()
- * \brief Retrieve the number of elements in the Span
- * \return The number of elements in the Span
- */
-
-/**
- * \fn Span::operator[](unsigned int index)
- * \brief Retrieve element in position \a index
- * \param[in] index
- *
- * If \a index is larger than the number of elements in the Span, the last
- * element is returned.
- *
- * \return The element at position \a index
- */
-
-/**
- * \fn iterator Span::begin()
- * \brief Retrieve an iterator to the first element in the Span
- */
-
-/**
- * \fn const_iterator Span::cbegin()
- * \brief Retrieve a constant iterator to the first element in the Span
- */
-
-/**
- * \fn iterator Span::end()
- * \brief Retrieve an iterator pointing to the past-the-end element in the Span
- */
-
-/**
- * \fn const_iterator Span::cend()
- * \brief Retrieve a constant iterator pointing to the past-the-end element in the Span
- */
} /* namespace libcamera */
--
2.24.0
More information about the libcamera-devel
mailing list