From patchwork Mon Jan 13 16:42:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2628 X-Patchwork-Delegate: jacopo@jmondi.org Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BC5D3606EA for ; Mon, 13 Jan 2020 17:40:34 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id 43B0D100012; Mon, 13 Jan 2020 16:40:34 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:35 +0100 Message-Id: <20200113164245.52535-14-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 13/23] libcamera: span: Add support for STL containers X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:34 -0000 From: Laurent Pinchart Add support for STL containers to the Span class implementation and make it fully C++20-compliant. Signed-off-by: Laurent Pinchart --- 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 +#include +#include #include +#include namespace libcamera { +static constexpr std::size_t dynamic_extent = std::numeric_limits::max(); + +template +class Span; + template -class Span +class Span { private: + template + struct is_array : public std::false_type { + }; + + template + struct is_array> : public std::true_type { + }; + + template + struct is_span : public std::false_type { + }; + + template + struct is_span> : public std::true_type { + }; + + template + using enable_if_t = typename std::enable_if::type; + + template + using remove_pointer_t = typename std::remove_pointer::type; + +public: + using element_type = T; + using value_type = typename std::remove_cv::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; + using const_reverse_iterator = std::reverse_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 + constexpr Span(element_type (&arr)[N], + enable_if_t (*)[], + element_type (*)[]>::value, + std::nullptr_t> = nullptr) noexcept + : data_(arr), size_(N) { } - Span(const T &v) - : storage_(const_cast(&v), 1) + template + constexpr Span(std::array &arr, + enable_if_t (*)[], + element_type (*)[]>::value, + std::nullptr_t> = nullptr) noexcept + : data_(arr.data()), size_(N) { } - Span(T *v, size_t s) - : storage_(v, s) + template + constexpr Span(const std::array &arr) noexcept + : data_(arr.data()), size_(N) { } - Span(const T *v, size_t s) - : storage_(const_cast(v), s) + template + constexpr Span(Container &cont, + enable_if_t::value && + !is_array::value && + !std::is_array::value && + std::is_convertible (*)[], + element_type (*)[]>::value, + std::nullptr_t> = nullptr) + : data_(cont.data()), size_(cont.size()) { } - Span(std::initializer_list list) - : storage_(const_cast(list.begin()), list.size()) + template + constexpr Span(const Container &cont, + enable_if_t::value && + !is_array::value && + !std::is_array::value && + std::is_convertible (*)[], + 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 + constexpr Span(const Span &s, + enable_if_t::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 + constexpr Span first() const + { + return { data(), Count }; + } + + constexpr Span first(std::size_t Count) const + { + return { data(), Count }; + } + + template + constexpr Span last() const + { + return { data() + size() - Count, Count }; + } + + constexpr Span last(std::size_t Count) const + { + return { data() + size() - Count, Count }; + } + + template + constexpr Span subspan() const + { + return { data() + Offset, Count == dynamic_extent ? size() - Offset : Count }; + } + + constexpr Span + 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 -/** - * \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 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 */