From d8c788a4138f974fd0832a98eb20fec5d059e5b5 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Sun, 19 Aug 2018 20:20:05 +0100 Subject: [PATCH 01/23] Platform: Add C++ Span class. The Span class allows the creation of views over contiguous memory. The view do not own memory, is typed and has a length. It can be used as a replacement of the traditional pair of pointer and size in parameters or class fields. Main operations: - size(): return the lenght of the memory viewed - empty(): return if the memory viewed is empty - [index]: access elements viewed - data(): return a pointer to the memory viewed. - first(count): Create a subview from the first count elements. - last(count): Create a subview from the last count elements. - == and !=: compare two views or a view to array and return if they are equal or not. The Span class came in two flavors: - Static size: The size is encoded in the Span type and it is as lightweitgh as a single pointer, - Dynamic size: The object can store arbitrary views and it costs one pointer and the size of the view. --- platform/Span.h | 578 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 578 insertions(+) create mode 100644 platform/Span.h diff --git a/platform/Span.h b/platform/Span.h new file mode 100644 index 0000000000..affa8f9e33 --- /dev/null +++ b/platform/Span.h @@ -0,0 +1,578 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBED_PLATFORM_SPAN_H_ +#define MBED_PLATFORM_SPAN_H_ + +#include +#include +#include + +#include "platform/mbed_assert.h" + +namespace mbed { + +/** + * Special value for the Size parameter of Span. + * If the type use this value then the size of the array is stored in the object + * at runtime. + */ +#define SPAN_DYNAMIC_SIZE -1 + +/** + * View to an array. + * + * Spans encapsulate the pointer to an array and its size into a single object + * or type; however, it does not manage the lifetime of the array viewed. + * You can use instances of Span to replace the traditional pair of pointer and + * size arguments in function calls. + * + * You can use the size member function to query the number of elements present + * in the array, and overloads of the subscript operator allow code using + * this object to access to the content of the array viewed. + * + * @note You can create Span instances with the help of the function + * template make_Span() and make_const_Span(). + * + * @note Span objects can be implicitly converted to Span objects + * where required. + * + * @tparam T type of objects held by the array. + * @tparam Size The size of the array viewed. The default value + * SPAN_DYNAMIC_SIZE is special as it allows construction of Span objects of + * any size (set at runtime). + */ +template +struct Span { + + MBED_STATIC_ASSERT(Size >= 0, "Invalid size for an ArrayView"); + + /** + * Construct a view to an empty array. + * + * @post a call to size() will return 0, and data() will return NULL. + */ + Span() : _array(NULL) { } + + /** + * Construct a Span from a pointer to a buffer. + * + * @param array_ptr Pointer to the array data + * @param array_size Number of elements of T present in the array. + * + * @post a call to size() will return array_size and data() will return + * array_tpr. + */ + Span(T* array_ptr, size_t array_size) : + _array(array_ptr) { + MBED_ASSERT(array_size >= (size_t) Size); + } + + /** + * Construct a Span from the reference to an array. + * + * @param elements Reference to the array viewed. + * + * @tparam Size Number of elements of T presents in the array. + * + * @post a call to size() will return Size, and data() will return + * a pointer to elements. + */ + Span(T (&elements)[Size]): + _array(elements) { } + + /** + * Return the size of the array viewed. + * + * @return The number of elements present in the array viewed. + */ + size_t size() const + { + return _array ? Size : 0; + } + + /** + * Return if the array is empty or not. + * + * @return true if the array is empty and false otherwise + */ + bool empty() const + { + return size() ? false : true; + } + + /** + * Access to a mutable element of the array. + * + * @param index Element index to access. + * + * @return A reference to the element at the index specified in input. + * + * @pre index shall be less than size(). + */ + T& operator[](size_t index) + { + return _array[index]; + } + + /** + * Access to an immutable element of the array. + * + * @param index Element index to access. + * + * @return A const reference to the element at the index specified in input. + * + * @pre index shall be less than size(). + */ + const T& operator[](size_t index) const + { + return _array[index]; + } + + /** + * Get the raw pointer to the array. + * + * @return The raw pointer to the array. + */ + T* data() + { + return _array; + } + + /** + * Get the raw const pointer to the array. + * + * @return The raw pointer to the array. + */ + const T* data() const + { + return _array; + } + + /** + * Create a new Span over the first @p count elements of the existing view. + * + * @param count The number of element viewed by the new Span + * + * @return A new Span over the first @p count elements. + */ + Span first(std::size_t count) const { + MBED_ASSERT(count <= Size); + return Span(_array, count); + } + + /** + * Create a new span over the first @p Count elements of the existing view. + * + * @tparam Count The number of element viewed by the new Span + * + * @return A new Span over the first @p Count elements. + */ + template + Span first() const { + MBED_ASSERT(Count <= Size); + return Span(_array); + } + + /** + * Create a new span over the last @p count elements of the existing view. + * + * @param count The number of element viewed by the new Span + * + * @return A new Span over the last @p count elements. + */ + Span last(std::ptrdiff_t count) const { + MBED_ASSERT(count <= Size); + return Span(_array + (Size - count), count); + } + + /** + * Create a new span over the last @p Count elements of the existing view. + * + * @tparam Count The number of element viewed by the new Span + * + * @return A new Span over the last @p Count elements. + */ + template + Span last() const { + MBED_ASSERT(Count <= Size); + return Span(_array + (Size - Count)); + } + +private: + T* _array; +}; + +/** + * Span specialisation that handle dynamic array size. + */ +template +struct Span { + + /** + * Construct a view to an empty array. + * + * @post a call to size() will return 0, and data() will return NULL. + */ + Span() : _array(0), _size(0) { } + + /** + * Construct a Span from a pointer to a buffer and its size. + * + * @param array_ptr Pointer to the array data + * @param array_size Number of elements of T present in the array. + * + * @post a call to size() will return array_size and data() will return + * array_tpr. + */ + Span(T* array_ptr, size_t array_size) : + _array(array_ptr), _size(array_size) { } + + /** + * Construct a Span from the reference to an array. + * + * @param elements Reference to the array viewed. + * + * @tparam Size Number of elements of T presents in the array. + * + * @post a call to size() will return Size, and data() will return + * a pointer to elements. + */ + template + Span(T (&elements)[Size]): + _array(elements), _size(Size) { } + + + /** + * Construct a Span object with a dynamic size from a Span object with a + * static size. + * @param other The Span object used to construct this. + */ + template + Span(const Span& other): + _array(other.data()), _size(other.size()) { } + + /** + * Return the size of the array viewed. + * + * @return The number of elements present in the array viewed. + */ + size_t size() const + { + return _size; + } + + /** + * Return if the array is empty or not + * @return true if the array is empty and false otherwise + */ + bool empty() const + { + return size() ? false : true; + } + + /** + * Access to a mutable element of the array. + * + * @param index Element index to access. + * + * @return A reference to the element at the index specified in input. + * + * @pre index shall be less than size(). + */ + T& operator[](size_t index) + { + return _array[index]; + } + + /** + * Access to an immutable element of the array. + * + * @param index Element index to access. + * + * @return A const reference to the element at the index specified in input. + * + * @pre index shall be less than size(). + */ + const T& operator[](size_t index) const + { + return _array[index]; + } + + /** + * Get the raw pointer to the array. + * + * @return The raw pointer to the array. + */ + T* data() + { + return _array; + } + + /** + * Get the raw const pointer to the array. + * + * @return The raw pointer to the array. + */ + const T* data() const + { + return _array; + } + + /** + * Create a new Span over the first @p count elements of the existing view. + * + * @param count The number of element viewed by the new Span + * + * @return A new Span over the first @p count elements. + */ + Span first(std::ptrdiff_t count) const { + MBED_ASSERT(count <= _size); + return Span(_array, count); + } + + /** + * Create a new span over the last @p count elements of the existing view. + * + * @param count The number of element viewed by the new Span + * + * @return A new Span over the last @p count elements. + */ + Span last(std::ptrdiff_t count) const { + MBED_ASSERT(count <= _size); + return Span(_array + (_size - count), count); + } + +private: + T* _array; + size_t _size; +}; + +/** + * Equality operator between two Span objects. + * + * @param lhs Left hand side of the binary operation. + * @param rhs Right hand side of the binary operation. + * + * @return True if arrays in input have the same size and the same content + * and false otherwise. + */ +template +bool operator==(const Span& lhs, const Span& rhs) +{ + if (lhs.size() != rhs.size()) { + return false; + } + + if (lhs.data() == rhs.data()) { + return true; + } + + return std::equal(lhs.data(), lhs.data() + lhs.size(), rhs.data()); +} + +/** + * Equality operation between a span and a reference to a C++ array. + * + * @param lhs Left hand side of the binary operation. + * @param rhs Right hand side of the binary operation. + * + * @return True if arrays in input have the same size and the same content + * and false otherwise. + */ +template +bool operator==(const Span& lhs, T (&rhs)[RhsSize]) +{ + return lhs == Span(rhs); +} + +/** + * Equality operation between a span and a reference to a C++ array. + * + * @param lhs Left hand side of the binary operation. + * @param rhs Right hand side of the binary operation. + * + * @return True if arrays in input have the same size and the same content + * and false otherwise. + */ +template +bool operator==(T (& lhs)[LhsSize], const Span& rhs) +{ + return Span(lhs) == rhs; +} + +/** + * Not equal operator + * + * @param lhs Left hand side of the binary operation. + * @param rhs Right hand side of the binary operation. + * + * @return True if arrays in input do not have the same size or the same + * content and false otherwise. + */ +template +bool operator!=(const Span& lhs, const Span& rhs) +{ + return !(lhs == rhs); +} + +/** + * Not Equal operation between a span and a reference to a C++ array. + * + * @param lhs Left hand side of the binary operation. + * @param rhs Right hand side of the binary operation. + * + * @return True if arrays in input have the same size and the same content + * and false otherwise. + */ +template +bool operator!=(const Span& lhs, T (&rhs)[RhsSize]) +{ + return !(lhs == Span(rhs)); +} + +/** + * Not Equal operation between a span and a reference to a C++ array. + * + * @param lhs Left hand side of the binary operation. + * @param rhs Right hand side of the binary operation. + * + * @return True if arrays in input have the same size and the same content + * and false otherwise. + */ +template +bool operator!=(T (& lhs)[LhsSize], const Span& rhs) +{ + return !(Span(lhs) == rhs); +} + +/** + * Generate a Span from a reference to a C/C++ array. + * + * @tparam T Type of elements held in elements. + * @tparam Size Number of items held in elements. + * + * @param elements The reference to the array viewed. + * + * @return The Span to elements. + * + * @note This helper avoids the typing of template parameter when Span is + * created 'inline'. + */ +template +Span make_Span(T (&elements)[Size]) +{ + return Span(elements); +} + +/** + * Generate a Span from a pointer to a C/C++ array. + * + * @tparam Size Number of items held in elements. + * @tparam T Type of elements held in elements. + * + * @param elements The reference to the array viewed. + * + * @return The Span to elements. + * + * @note This helper avoids the typing of template parameter when Span is + * created 'inline'. + */ +template +Span make_Span(T* elements) +{ + return Span(elements, Size); +} + +/** + * Generate a Span from a C/C++ pointer and the size of the array. + * + * @tparam T Type of elements held in array_ptr. + * + * @param array_ptr The pointer to the array to viewed. + * @param array_size The number of T elements in the array. + * + * @return The Span to array_ptr with a size of array_size. + * + * @note This helper avoids the typing of template parameter when Span is + * created 'inline'. + */ +template +Span make_Span(T* array_ptr, size_t array_size) +{ + return Span(array_ptr, array_size); +} + +/** + * Generate a Span to a const content from a reference to a C/C++ array. + * + * @tparam T Type of elements held in elements. + * @tparam Size Number of items held in elements. + * + * @param elements The array viewed. + * @return The Span to elements. + * + * @note This helper avoids the typing of template parameter when Span is + * created 'inline'. + */ +template +Span make_const_Span(const T (&elements)[Size]) +{ + return Span(elements); +} + +/** + * Generate a Span to a const content from a pointer to a C/C++ array. + * + * @tparam Size Number of items held in elements. + * @tparam T Type of elements held in elements. + * + * @param elements The reference to the array viewed. + * + * @return The Span to elements. + * + * @note This helper avoids the typing of template parameter when Span is + * created 'inline'. + */ +template +Span make_const_Span(const T* elements) +{ + return Span(elements, Size); +} + +/** + * Generate a Span to a const content from a C/C++ pointer and the size of the + * array. + * + * @tparam T Type of elements held in array_ptr. + * + * @param array_ptr The pointer to the array to viewed. + * @param array_size The number of T elements in the array. + * + * @return The Span to array_ptr with a size of array_size. + * + * @note This helper avoids the typing of template parameter when Span is + * created 'inline'. + */ +template +Span make_const_Span(T* array_ptr, size_t array_size) +{ + return Span(array_ptr, array_size); +} + +} // namespace mbed + +#endif /* MBED_PLATFORM_SPAN_H_ */ From 7f195b8ec13285da45d434ec7bb28cb0f8c255e0 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 20 Aug 2018 09:13:17 +0100 Subject: [PATCH 02/23] Span: Cleanup usage of ptrdiff_t and size_t --- platform/Span.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/Span.h b/platform/Span.h index affa8f9e33..9f07b85d26 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -181,7 +181,7 @@ struct Span { * * @return A new Span over the first @p Count elements. */ - template + template Span first() const { MBED_ASSERT(Count <= Size); return Span(_array); @@ -194,7 +194,7 @@ struct Span { * * @return A new Span over the last @p count elements. */ - Span last(std::ptrdiff_t count) const { + Span last(std::size_t count) const { MBED_ASSERT(count <= Size); return Span(_array + (Size - count), count); } @@ -339,7 +339,7 @@ struct Span { * * @return A new Span over the first @p count elements. */ - Span first(std::ptrdiff_t count) const { + Span first(std::size_t count) const { MBED_ASSERT(count <= _size); return Span(_array, count); } @@ -351,7 +351,7 @@ struct Span { * * @return A new Span over the last @p count elements. */ - Span last(std::ptrdiff_t count) const { + Span last(std::size_t count) const { MBED_ASSERT(count <= _size); return Span(_array + (_size - count), count); } From eba1dc6dd6cbe233a862cac3c48dcbbd4d04deb8 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 20 Aug 2018 09:13:31 +0100 Subject: [PATCH 03/23] Span: Improve comparison operator to array by using fixed size Span. --- platform/Span.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/Span.h b/platform/Span.h index 9f07b85d26..0df7eb3a6d 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -441,7 +441,7 @@ bool operator!=(const Span& lhs, const Span& rhs) template bool operator!=(const Span& lhs, T (&rhs)[RhsSize]) { - return !(lhs == Span(rhs)); + return !(lhs == Span(rhs)); } /** @@ -456,7 +456,7 @@ bool operator!=(const Span& lhs, T (&rhs)[RhsSize]) template bool operator!=(T (& lhs)[LhsSize], const Span& rhs) { - return !(Span(lhs) == rhs); + return !(Span(lhs) == rhs); } /** From 43170d21bf60dea6042b55f7db05959a7caa0c62 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 20 Aug 2018 10:29:43 +0100 Subject: [PATCH 04/23] Span: Make name of dynamic span tag consistent with C++ standard. --- platform/Span.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/Span.h b/platform/Span.h index 0df7eb3a6d..54bd27749c 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -30,7 +30,7 @@ namespace mbed { * If the type use this value then the size of the array is stored in the object * at runtime. */ -#define SPAN_DYNAMIC_SIZE -1 +#define SPAN_DYNAMIC_EXTENT -1 /** * View to an array. @@ -55,7 +55,7 @@ namespace mbed { * SPAN_DYNAMIC_SIZE is special as it allows construction of Span objects of * any size (set at runtime). */ -template +template struct Span { MBED_STATIC_ASSERT(Size >= 0, "Invalid size for an ArrayView"); @@ -220,7 +220,7 @@ private: * Span specialisation that handle dynamic array size. */ template -struct Span { +struct Span { /** * Construct a view to an empty array. From 3fb3173876e6b4b012f1a2dc7abfc2c488c49204 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 20 Aug 2018 10:30:35 +0100 Subject: [PATCH 05/23] Span: Fix odd condition in Span::empty. --- platform/Span.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/Span.h b/platform/Span.h index 54bd27749c..17c919cd28 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -111,7 +111,7 @@ struct Span { */ bool empty() const { - return size() ? false : true; + return size() == 0; } /** @@ -281,7 +281,7 @@ struct Span { */ bool empty() const { - return size() ? false : true; + return size() == 0; } /** From 9b9d33a7b4a4e160ff8561c761557c1abc73bb71 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 20 Aug 2018 10:41:47 +0100 Subject: [PATCH 06/23] Span: Fix typo. --- platform/Span.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/Span.h b/platform/Span.h index 17c919cd28..b5770fc45f 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -58,7 +58,7 @@ namespace mbed { template struct Span { - MBED_STATIC_ASSERT(Size >= 0, "Invalid size for an ArrayView"); + MBED_STATIC_ASSERT(Size >= 0, "Invalid size for a Span"); /** * Construct a view to an empty array. @@ -74,7 +74,7 @@ struct Span { * @param array_size Number of elements of T present in the array. * * @post a call to size() will return array_size and data() will return - * array_tpr. + * @p array_ptr. */ Span(T* array_ptr, size_t array_size) : _array(array_ptr) { @@ -236,7 +236,7 @@ struct Span { * @param array_size Number of elements of T present in the array. * * @post a call to size() will return array_size and data() will return - * array_tpr. + * @p array_ptr. */ Span(T* array_ptr, size_t array_size) : _array(array_ptr), _size(array_size) { } From 6fcf1e828413e8ef227fbf60faa1515ebeae39f4 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 20 Aug 2018 10:47:41 +0100 Subject: [PATCH 07/23] Span: Make type pointer and reference declaration consistent with guideline. --- platform/Span.h | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/platform/Span.h b/platform/Span.h index b5770fc45f..273e465121 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -76,7 +76,7 @@ struct Span { * @post a call to size() will return array_size and data() will return * @p array_ptr. */ - Span(T* array_ptr, size_t array_size) : + Span(T *array_ptr, size_t array_size) : _array(array_ptr) { MBED_ASSERT(array_size >= (size_t) Size); } @@ -123,7 +123,7 @@ struct Span { * * @pre index shall be less than size(). */ - T& operator[](size_t index) + T &operator[](size_t index) { return _array[index]; } @@ -137,7 +137,7 @@ struct Span { * * @pre index shall be less than size(). */ - const T& operator[](size_t index) const + const T &operator[](size_t index) const { return _array[index]; } @@ -147,7 +147,7 @@ struct Span { * * @return The raw pointer to the array. */ - T* data() + T *data() { return _array; } @@ -157,7 +157,7 @@ struct Span { * * @return The raw pointer to the array. */ - const T* data() const + const T *data() const { return _array; } @@ -213,7 +213,7 @@ struct Span { } private: - T* _array; + T *_array; }; /** @@ -238,7 +238,7 @@ struct Span { * @post a call to size() will return array_size and data() will return * @p array_ptr. */ - Span(T* array_ptr, size_t array_size) : + Span(T *array_ptr, size_t array_size) : _array(array_ptr), _size(array_size) { } /** @@ -262,7 +262,7 @@ struct Span { * @param other The Span object used to construct this. */ template - Span(const Span& other): + Span(const Span &other): _array(other.data()), _size(other.size()) { } /** @@ -293,7 +293,7 @@ struct Span { * * @pre index shall be less than size(). */ - T& operator[](size_t index) + T &operator[](size_t index) { return _array[index]; } @@ -307,7 +307,7 @@ struct Span { * * @pre index shall be less than size(). */ - const T& operator[](size_t index) const + const T &operator[](size_t index) const { return _array[index]; } @@ -317,7 +317,7 @@ struct Span { * * @return The raw pointer to the array. */ - T* data() + T *data() { return _array; } @@ -327,7 +327,7 @@ struct Span { * * @return The raw pointer to the array. */ - const T* data() const + const T *data() const { return _array; } @@ -357,7 +357,7 @@ struct Span { } private: - T* _array; + T *_array; size_t _size; }; @@ -371,7 +371,7 @@ private: * and false otherwise. */ template -bool operator==(const Span& lhs, const Span& rhs) +bool operator==(const Span &lhs, const Span &rhs) { if (lhs.size() != rhs.size()) { return false; @@ -394,7 +394,7 @@ bool operator==(const Span& lhs, const Span& rhs) * and false otherwise. */ template -bool operator==(const Span& lhs, T (&rhs)[RhsSize]) +bool operator==(const Span &lhs, T (&rhs)[RhsSize]) { return lhs == Span(rhs); } @@ -409,7 +409,7 @@ bool operator==(const Span& lhs, T (&rhs)[RhsSize]) * and false otherwise. */ template -bool operator==(T (& lhs)[LhsSize], const Span& rhs) +bool operator==(T (&lhs)[LhsSize], const Span &rhs) { return Span(lhs) == rhs; } @@ -424,7 +424,7 @@ bool operator==(T (& lhs)[LhsSize], const Span& rhs) * content and false otherwise. */ template -bool operator!=(const Span& lhs, const Span& rhs) +bool operator!=(const Span &lhs, const Span &rhs) { return !(lhs == rhs); } @@ -439,7 +439,7 @@ bool operator!=(const Span& lhs, const Span& rhs) * and false otherwise. */ template -bool operator!=(const Span& lhs, T (&rhs)[RhsSize]) +bool operator!=(const Span &lhs, T (&rhs)[RhsSize]) { return !(lhs == Span(rhs)); } @@ -454,7 +454,7 @@ bool operator!=(const Span& lhs, T (&rhs)[RhsSize]) * and false otherwise. */ template -bool operator!=(T (& lhs)[LhsSize], const Span& rhs) +bool operator!=(T (&lhs)[LhsSize], const Span &rhs) { return !(Span(lhs) == rhs); } @@ -492,7 +492,7 @@ Span make_Span(T (&elements)[Size]) * created 'inline'. */ template -Span make_Span(T* elements) +Span make_Span(T *elements) { return Span(elements, Size); } @@ -511,7 +511,7 @@ Span make_Span(T* elements) * created 'inline'. */ template -Span make_Span(T* array_ptr, size_t array_size) +Span make_Span(T *array_ptr, size_t array_size) { return Span(array_ptr, array_size); } @@ -548,7 +548,7 @@ Span make_const_Span(const T (&elements)[Size]) * created 'inline'. */ template -Span make_const_Span(const T* elements) +Span make_const_Span(const T *elements) { return Span(elements, Size); } @@ -568,7 +568,7 @@ Span make_const_Span(const T* elements) * created 'inline'. */ template -Span make_const_Span(T* array_ptr, size_t array_size) +Span make_const_Span(T *array_ptr, size_t array_size) { return Span(array_ptr, array_size); } From 1f00336c7e1b07582935a7259842dac4921a8ef5 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 20 Aug 2018 11:58:48 +0100 Subject: [PATCH 08/23] Span: replace reference to Size with Extent. --- platform/Span.h | 96 ++++++++++++++++++++++++------------------------- 1 file changed, 47 insertions(+), 49 deletions(-) diff --git a/platform/Span.h b/platform/Span.h index 273e465121..43494e6984 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -26,7 +26,7 @@ namespace mbed { /** - * Special value for the Size parameter of Span. + * Special value for the Extent parameter of Span. * If the type use this value then the size of the array is stored in the object * at runtime. */ @@ -47,18 +47,18 @@ namespace mbed { * @note You can create Span instances with the help of the function * template make_Span() and make_const_Span(). * - * @note Span objects can be implicitly converted to Span objects + * @note Span objects can be implicitly converted to Span objects * where required. * * @tparam T type of objects held by the array. - * @tparam Size The size of the array viewed. The default value + * @tparam Extent The size of the array viewed. The default value * SPAN_DYNAMIC_SIZE is special as it allows construction of Span objects of * any size (set at runtime). */ -template +template struct Span { - MBED_STATIC_ASSERT(Size >= 0, "Invalid size for a Span"); + MBED_STATIC_ASSERT(Extent >= 0, "Invalid extent for a Span"); /** * Construct a view to an empty array. @@ -78,7 +78,7 @@ struct Span { */ Span(T *array_ptr, size_t array_size) : _array(array_ptr) { - MBED_ASSERT(array_size >= (size_t) Size); + MBED_ASSERT(array_size >= (size_t) Extent); } /** @@ -86,12 +86,10 @@ struct Span { * * @param elements Reference to the array viewed. * - * @tparam Size Number of elements of T presents in the array. - * - * @post a call to size() will return Size, and data() will return + * @post a call to size() will return Extent, and data() will return * a pointer to elements. */ - Span(T (&elements)[Size]): + Span(T (&elements)[Extent]): _array(elements) { } /** @@ -101,7 +99,7 @@ struct Span { */ size_t size() const { - return _array ? Size : 0; + return _array ? Extent : 0; } /** @@ -170,7 +168,7 @@ struct Span { * @return A new Span over the first @p count elements. */ Span first(std::size_t count) const { - MBED_ASSERT(count <= Size); + MBED_ASSERT(count <= Extent); return Span(_array, count); } @@ -183,7 +181,7 @@ struct Span { */ template Span first() const { - MBED_ASSERT(Count <= Size); + MBED_ASSERT(Count <= Extent); return Span(_array); } @@ -195,8 +193,8 @@ struct Span { * @return A new Span over the last @p count elements. */ Span last(std::size_t count) const { - MBED_ASSERT(count <= Size); - return Span(_array + (Size - count), count); + MBED_ASSERT(count <= Extent); + return Span(_array + (Extent - count), count); } /** @@ -208,8 +206,8 @@ struct Span { */ template Span last() const { - MBED_ASSERT(Count <= Size); - return Span(_array + (Size - Count)); + MBED_ASSERT(Count <= Extent); + return Span(_array + (Extent - Count)); } private: @@ -261,8 +259,8 @@ struct Span { * static size. * @param other The Span object used to construct this. */ - template - Span(const Span &other): + template + Span(const Span &other): _array(other.data()), _size(other.size()) { } /** @@ -370,8 +368,8 @@ private: * @return True if arrays in input have the same size and the same content * and false otherwise. */ -template -bool operator==(const Span &lhs, const Span &rhs) +template +bool operator==(const Span &lhs, const Span &rhs) { if (lhs.size() != rhs.size()) { return false; @@ -393,8 +391,8 @@ bool operator==(const Span &lhs, const Span &rhs) * @return True if arrays in input have the same size and the same content * and false otherwise. */ -template -bool operator==(const Span &lhs, T (&rhs)[RhsSize]) +template +bool operator==(const Span &lhs, T (&rhs)[RhsExtent]) { return lhs == Span(rhs); } @@ -408,8 +406,8 @@ bool operator==(const Span &lhs, T (&rhs)[RhsSize]) * @return True if arrays in input have the same size and the same content * and false otherwise. */ -template -bool operator==(T (&lhs)[LhsSize], const Span &rhs) +template +bool operator==(T (&lhs)[LhsExtent], const Span &rhs) { return Span(lhs) == rhs; } @@ -423,8 +421,8 @@ bool operator==(T (&lhs)[LhsSize], const Span &rhs) * @return True if arrays in input do not have the same size or the same * content and false otherwise. */ -template -bool operator!=(const Span &lhs, const Span &rhs) +template +bool operator!=(const Span &lhs, const Span &rhs) { return !(lhs == rhs); } @@ -438,10 +436,10 @@ bool operator!=(const Span &lhs, const Span &rhs) * @return True if arrays in input have the same size and the same content * and false otherwise. */ -template -bool operator!=(const Span &lhs, T (&rhs)[RhsSize]) +template +bool operator!=(const Span &lhs, T (&rhs)[RhsExtent]) { - return !(lhs == Span(rhs)); + return !(lhs == Span(rhs)); } /** @@ -453,17 +451,17 @@ bool operator!=(const Span &lhs, T (&rhs)[RhsSize]) * @return True if arrays in input have the same size and the same content * and false otherwise. */ -template -bool operator!=(T (&lhs)[LhsSize], const Span &rhs) +template +bool operator!=(T (&lhs)[LhsExtent], const Span &rhs) { - return !(Span(lhs) == rhs); + return !(Span(lhs) == rhs); } /** * Generate a Span from a reference to a C/C++ array. * * @tparam T Type of elements held in elements. - * @tparam Size Number of items held in elements. + * @tparam Extent Number of items held in elements. * * @param elements The reference to the array viewed. * @@ -472,16 +470,16 @@ bool operator!=(T (&lhs)[LhsSize], const Span &rhs) * @note This helper avoids the typing of template parameter when Span is * created 'inline'. */ -template -Span make_Span(T (&elements)[Size]) +template +Span make_Span(T (&elements)[Extent]) { - return Span(elements); + return Span(elements); } /** * Generate a Span from a pointer to a C/C++ array. * - * @tparam Size Number of items held in elements. + * @tparam Extent Number of items held in elements. * @tparam T Type of elements held in elements. * * @param elements The reference to the array viewed. @@ -491,10 +489,10 @@ Span make_Span(T (&elements)[Size]) * @note This helper avoids the typing of template parameter when Span is * created 'inline'. */ -template -Span make_Span(T *elements) +template +Span make_Span(T *elements) { - return Span(elements, Size); + return Span(elements, Extent); } /** @@ -520,7 +518,7 @@ Span make_Span(T *array_ptr, size_t array_size) * Generate a Span to a const content from a reference to a C/C++ array. * * @tparam T Type of elements held in elements. - * @tparam Size Number of items held in elements. + * @tparam Extent Number of items held in elements. * * @param elements The array viewed. * @return The Span to elements. @@ -528,16 +526,16 @@ Span make_Span(T *array_ptr, size_t array_size) * @note This helper avoids the typing of template parameter when Span is * created 'inline'. */ -template -Span make_const_Span(const T (&elements)[Size]) +template +Span make_const_Span(const T (&elements)[Extent]) { - return Span(elements); + return Span(elements); } /** * Generate a Span to a const content from a pointer to a C/C++ array. * - * @tparam Size Number of items held in elements. + * @tparam Extent Number of items held in elements. * @tparam T Type of elements held in elements. * * @param elements The reference to the array viewed. @@ -547,10 +545,10 @@ Span make_const_Span(const T (&elements)[Size]) * @note This helper avoids the typing of template parameter when Span is * created 'inline'. */ -template -Span make_const_Span(const T *elements) +template +Span make_const_Span(const T *elements) { - return Span(elements, Size); + return Span(elements, Extent); } /** From 3985fb8d62adbe859c959f4e6f4444ed6958f4a4 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 20 Aug 2018 12:00:20 +0100 Subject: [PATCH 09/23] Span: Fix documentation error. --- platform/Span.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/Span.h b/platform/Span.h index 43494e6984..2e2541ae18 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -73,7 +73,7 @@ struct Span { * @param array_ptr Pointer to the array data * @param array_size Number of elements of T present in the array. * - * @post a call to size() will return array_size and data() will return + * @post a call to size() will return Extent and data() will return * @p array_ptr. */ Span(T *array_ptr, size_t array_size) : From 54e2d92c953a668f802893641dbcdbddbc87d5cb Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 21 Aug 2018 18:20:58 +0100 Subject: [PATCH 10/23] Span: Improve consistency with standard. This commit aims to make Span implementation more in line with what is present in N4762: - use appropiate index types where applicable. - use typedefed type inside the class (index_type, reference, pointer, element_type) - assertion where applicable - restrict default construction to Span with extent == 0 or extent == dynamic. - construct span from a range of pointer - remove non const overload of the subscript operator - remove non const overload of the data function - implement subspan function - implement missing first and last function of dynamic span --- platform/Span.h | 655 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 436 insertions(+), 219 deletions(-) diff --git a/platform/Span.h b/platform/Span.h index 2e2541ae18..a502301f2c 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -35,50 +35,107 @@ namespace mbed { /** * View to an array. * - * Spans encapsulate the pointer to an array and its size into a single object - * or type; however, it does not manage the lifetime of the array viewed. - * You can use instances of Span to replace the traditional pair of pointer and - * size arguments in function calls. + * Spans encapsulate the pointer to an array and its size into a single object. + * However, it does not manage the lifetime of the array viewed. You can use + * instances of Span to replace the traditional pair of pointer and size + * arguments in function calls. * * You can use the size member function to query the number of elements present - * in the array, and overloads of the subscript operator allow code using - * this object to access to the content of the array viewed. + * in the array, and the subscript operator allow code using this object to + * access the content of the array viewed. * - * @note You can create Span instances with the help of the function - * template make_Span() and make_const_Span(). + * Subspans can be created with the help of the functions first(), last() and + * subspan(). + * + * @note You can create Span instances with the help of the function template + * make_Span() and make_const_Span(). * * @note Span objects can be implicitly converted to Span objects * where required. * - * @tparam T type of objects held by the array. + * @tparam ElementType type of objects held in the array viewed. + * * @tparam Extent The size of the array viewed. The default value * SPAN_DYNAMIC_SIZE is special as it allows construction of Span objects of * any size (set at runtime). */ -template +template struct Span { + /** + * Type of the element contained + */ + typedef ElementType element_type; + + /** + * Type of the index. + */ + typedef ptrdiff_t index_type; + + /** + * Pointer to an ElementType + */ + typedef element_type *pointer; + + /** + * Reference to an ElementType + */ + typedef element_type &reference; + + /** + * Size of the Extent; -1 if dynamic. + */ + static const index_type extent = Extent; + MBED_STATIC_ASSERT(Extent >= 0, "Invalid extent for a Span"); /** - * Construct a view to an empty array. + * Construct an empty span. * * @post a call to size() will return 0, and data() will return NULL. + * + * @note This function is not accessible if Extent != SPAN_DYNAMIC_EXTENT or + * Extent != 0 . */ - Span() : _array(NULL) { } + Span() : _data(NULL) { + MBED_STATIC_ASSERT(Extent == 0, "Invalid extent for a Span"); + } /** - * Construct a Span from a pointer to a buffer. + * Construct a Span from a pointer to a buffer and its size. * - * @param array_ptr Pointer to the array data - * @param array_size Number of elements of T present in the array. + * @param ptr Pointer to the beginning of the data viewed. * - * @post a call to size() will return Extent and data() will return - * @p array_ptr. + * @param count Number of elements viewed. + * + * @pre [ptr, ptr + count) must be be a valid range. + * @pre count must be equal to extent. + * + * @post a call to size() will return Extent and data() will return @p ptr. */ - Span(T *array_ptr, size_t array_size) : - _array(array_ptr) { - MBED_ASSERT(array_size >= (size_t) Extent); + Span(pointer ptr, index_type count) : + _data(ptr) { + MBED_ASSERT(count == Extent); + MBED_ASSERT(Extent == 0 || ptr != NULL); + } + + /** + * Construct a Span from the range [first, last) + * + * @param first Pointer to the beginning of the data viewed. + * @param last End of the range (element after the last element). + * + * @pre [first, last) must be be a valid range. + * @pre first <= last + * @pre last - first must be equal to Extent. + * + * @post a call to size() will return Extent and data() will return @p first. + */ + Span(pointer first, pointer last) : + _data(first) { + MBED_ASSERT(first <= last); + MBED_ASSERT((last - first) == Extent); + MBED_ASSERT(Extent == 0 || first != NULL); } /** @@ -86,20 +143,20 @@ struct Span { * * @param elements Reference to the array viewed. * - * @post a call to size() will return Extent, and data() will return - * a pointer to elements. + * @post a call to size() will return Extent, and data() will return a + * pointer to elements. */ - Span(T (&elements)[Extent]): - _array(elements) { } + Span(element_type (&elements)[Extent]): + _data(elements) { } /** * Return the size of the array viewed. * * @return The number of elements present in the array viewed. */ - size_t size() const + index_type size() const { - return _array ? Extent : 0; + return Extent; } /** @@ -113,63 +170,28 @@ struct Span { } /** - * Access to a mutable element of the array. + * Returns a reference to the element at position @p index * - * @param index Element index to access. + * @param index Index of the element to access. * * @return A reference to the element at the index specified in input. * - * @pre index shall be less than size(). + * @pre 0 <= index < Extent */ - T &operator[](size_t index) + reference operator[](index_type index) const { - return _array[index]; + return _data[index]; } /** - * Access to an immutable element of the array. + * Return a pointer to the first element of the sequence or NULL if the span + * is empty(). * - * @param index Element index to access. - * - * @return A const reference to the element at the index specified in input. - * - * @pre index shall be less than size(). + * @return The pointer to the first element of the span. */ - const T &operator[](size_t index) const + pointer data() const { - return _array[index]; - } - - /** - * Get the raw pointer to the array. - * - * @return The raw pointer to the array. - */ - T *data() - { - return _array; - } - - /** - * Get the raw const pointer to the array. - * - * @return The raw pointer to the array. - */ - const T *data() const - { - return _array; - } - - /** - * Create a new Span over the first @p count elements of the existing view. - * - * @param count The number of element viewed by the new Span - * - * @return A new Span over the first @p count elements. - */ - Span first(std::size_t count) const { - MBED_ASSERT(count <= Extent); - return Span(_array, count); + return _data; } /** @@ -178,23 +200,16 @@ struct Span { * @tparam Count The number of element viewed by the new Span * * @return A new Span over the first @p Count elements. - */ - template - Span first() const { - MBED_ASSERT(Count <= Extent); - return Span(_array); - } - - /** - * Create a new span over the last @p count elements of the existing view. * - * @param count The number of element viewed by the new Span - * - * @return A new Span over the last @p count elements. + * @pre Count >= 0 && Count <= size(). */ - Span last(std::size_t count) const { - MBED_ASSERT(count <= Extent); - return Span(_array + (Extent - count), count); + template + Span first() const { + MBED_STATIC_ASSERT( + (Count >= 0) && (Count <= Extent), + "Invalid subspan extent" + ); + return Span(_data, Count); } /** @@ -203,131 +218,45 @@ struct Span { * @tparam Count The number of element viewed by the new Span * * @return A new Span over the last @p Count elements. + * + * @pre Count >= 0 && Count <= size(). */ - template - Span last() const { - MBED_ASSERT(Count <= Extent); - return Span(_array + (Extent - Count)); - } - -private: - T *_array; -}; - -/** - * Span specialisation that handle dynamic array size. - */ -template -struct Span { - - /** - * Construct a view to an empty array. - * - * @post a call to size() will return 0, and data() will return NULL. - */ - Span() : _array(0), _size(0) { } - - /** - * Construct a Span from a pointer to a buffer and its size. - * - * @param array_ptr Pointer to the array data - * @param array_size Number of elements of T present in the array. - * - * @post a call to size() will return array_size and data() will return - * @p array_ptr. - */ - Span(T *array_ptr, size_t array_size) : - _array(array_ptr), _size(array_size) { } - - /** - * Construct a Span from the reference to an array. - * - * @param elements Reference to the array viewed. - * - * @tparam Size Number of elements of T presents in the array. - * - * @post a call to size() will return Size, and data() will return - * a pointer to elements. - */ - template - Span(T (&elements)[Size]): - _array(elements), _size(Size) { } - - - /** - * Construct a Span object with a dynamic size from a Span object with a - * static size. - * @param other The Span object used to construct this. - */ - template - Span(const Span &other): - _array(other.data()), _size(other.size()) { } - - /** - * Return the size of the array viewed. - * - * @return The number of elements present in the array viewed. - */ - size_t size() const - { - return _size; + template + Span last() const { + MBED_STATIC_ASSERT( + (Count >= 0) && (Count <= Extent), + "Invalid subspan extent" + ); + return Span(_data + (Extent - Count), Count); } /** - * Return if the array is empty or not - * @return true if the array is empty and false otherwise + * Create a subspan that is a view other Count elements; the view starts at + * element Offset. + * + * @tparam Offset The offset of the first element viewed by the subspan. + * + * @tparam Count The number of elements present in the subspan. If Count + * is equal to SPAN_DYNAMIC_EXTENT then a span starting at offset and + * containing the rest of the elements is returned. + * + * @return */ - bool empty() const - { - return size() == 0; - } - - /** - * Access to a mutable element of the array. - * - * @param index Element index to access. - * - * @return A reference to the element at the index specified in input. - * - * @pre index shall be less than size(). - */ - T &operator[](size_t index) - { - return _array[index]; - } - - /** - * Access to an immutable element of the array. - * - * @param index Element index to access. - * - * @return A const reference to the element at the index specified in input. - * - * @pre index shall be less than size(). - */ - const T &operator[](size_t index) const - { - return _array[index]; - } - - /** - * Get the raw pointer to the array. - * - * @return The raw pointer to the array. - */ - T *data() - { - return _array; - } - - /** - * Get the raw const pointer to the array. - * - * @return The raw pointer to the array. - */ - const T *data() const - { - return _array; + template + Span subspan() const { + MBED_STATIC_ASSERT( + Offset == 0 || (Offset > 0 && Offset < Extent), + "Invalid subspan offset" + ); + MBED_STATIC_ASSERT( + (Count == SPAN_DYNAMIC_EXTENT) || + (Count >= 0 && Offset + Count <= Extent), + "Invalid subspan count" + ); + return Span( + _data + Offset, + Count == SPAN_DYNAMIC_EXTENT ? Extent - Offset : Count + ); } /** @@ -337,9 +266,9 @@ struct Span { * * @return A new Span over the first @p count elements. */ - Span first(std::size_t count) const { - MBED_ASSERT(count <= _size); - return Span(_array, count); + Span first(index_type count) const { + MBED_ASSERT(0 <= count && count <= Extent); + return Span(_data, count); } /** @@ -349,14 +278,302 @@ struct Span { * * @return A new Span over the last @p count elements. */ - Span last(std::size_t count) const { - MBED_ASSERT(count <= _size); - return Span(_array + (_size - count), count); + Span last(index_type count) const { + MBED_ASSERT(0 <= count && count <= Extent); + return Span( + _data + (Extent - count), + count + ); + } + + /** + * Create a subspan that is a view other count elements; the view starts at + * element offset. + * + * @param offset The offset of the first element viewed by the subspan. + * + * @param count The number of elements present in the subspan. If Count + * is equal to SPAN_DYNAMIC_EXTENT then a span starting at offset and + * containing the rest of the elements is returned. + * + * @return + */ + Span subspan( + index_type offset, index_type count = SPAN_DYNAMIC_EXTENT + ) const { + MBED_ASSERT(0 <= offset && offset <= Extent); + MBED_ASSERT( + (count == SPAN_DYNAMIC_EXTENT) || + (count >= 0 && (offset + count <= Extent)) + ); + return Span( + _data + offset, + count == SPAN_DYNAMIC_EXTENT ? Extent - offset : count + ); } private: - T *_array; - size_t _size; + pointer _data; +}; + +/** + * Span specialisation that handle dynamic array size. + */ +template +struct Span { + + /** + * Type of the element contained + */ + typedef ElementType element_type; + + /** + * Type of the index. + */ + typedef ptrdiff_t index_type; + + /** + * Pointer to an ElementType + */ + typedef element_type *pointer; + + /** + * Reference to an ElementType + */ + typedef element_type &reference; + + /** + * Size of the Extent; -1 if dynamic. + */ + static const index_type extent = SPAN_DYNAMIC_EXTENT; + + /** + * Construct an empty span. + * + * @post a call to size() will return 0, and data() will return NULL. + * + * @note This function is not accessible if Extent != SPAN_DYNAMIC_EXTENT or + * Extent != 0 . + */ + Span() : _data(NULL), _size(0) { } + + /** + * Construct a Span from a pointer to a buffer and its size. + * + * @param ptr Pointer to the beginning of the data viewed. + * + * @param count Number of elements viewed. + * + * @pre [ptr, ptr + count) must be be a valid range. + * @pre count must be equal to extent. + * + * @post a call to size() will return count and data() will return @p ptr. + */ + Span(pointer ptr, index_type count) : + _data(ptr), _size(count) { + MBED_ASSERT(count >= 0); + MBED_ASSERT(ptr != NULL || count == 0); + } + + /** + * Construct a Span from the range [first, last) + * + * @param first Pointer to the beginning of the data viewed. + * @param last End of the range (element after the last element). + * + * @pre [first, last) must be be a valid range. + * @pre first <= last + * + * @post a call to size() will return the result of (last - first) and + * data() will return @p first. + */ + Span(pointer first, pointer last) : + _data(first), _size(last - first) { + MBED_ASSERT(first <= last); + MBED_ASSERT(first != NULL || (last - first) == 0); + } + + /** + * Construct a Span from the reference to an array. + * + * @param elements Reference to the array viewed. + * + * @tparam Count Number of elements of T presents in the array. + * + * @post a call to size() will return Count, and data() will return a + * pointer to elements. + */ + template + Span(element_type (&elements)[Count]): + _data(elements), _size(Count) { } + + + /** + * Construct a Span object from another Span. + * + * @param other The Span object used to construct this. + * + * @note For span with a positive extent, this function is not accessible. + */ + template + Span(const Span &other): + _data(other.data()), _size(other.size()) { } + + /** + * Return the size of the array viewed. + * + * @return The number of elements present in the array viewed. + */ + index_type size() const + { + return _size; + } + + /** + * Return if the array is empty or not. + * + * @return true if the array is empty and false otherwise + */ + bool empty() const + { + return size() == 0; + } + + /** + * Access to an element of the array. + * + * @param index Element index to access. + * + * @return A reference to the element at the index specified in input. + * + * @pre index shall be less than size(). + */ + reference operator[](index_type index) const + { + return _data[index]; + } + + /** + * Get the raw pointer to the array. + * + * @return The raw pointer to the array. + */ + pointer data() const + { + return _data; + } + + /** + * Create a new span over the first @p Count elements of the existing view. + * + * @tparam Count The number of element viewed by the new Span + * + * @return A new Span over the first @p Count elements. + * + * @pre Count >= 0 && Count <= size(). + */ + template + Span first() const { + MBED_ASSERT((Count >= 0) && (Count <= _size)); + return Span(_data, Count); + } + + /** + * Create a new span over the last @p Count elements of the existing view. + * + * @tparam Count The number of element viewed by the new Span + * + * @return A new Span over the last @p Count elements. + * + * @pre Count >= 0 && Count <= size(). + */ + template + Span last() const { + MBED_ASSERT((Count >= 0) && (Count <= _size)); + return Span(_data + (_size - Count), Count); + } + + /** + * Create a subspan that is a view other Count elements; the view starts at + * element Offset. + * + * @tparam Offset The offset of the first element viewed by the subspan. + * + * @tparam Count The number of elements present in the subspan. If Count + * is equal to SPAN_DYNAMIC_EXTENT then a span starting at offset and + * containing the rest of the elements is returned. + * + * @return + */ + template + Span subspan() const { + MBED_ASSERT(Offset == 0 || (Offset > 0 && Offset < _size)); + MBED_ASSERT( + (Count == SPAN_DYNAMIC_EXTENT) || + (Count >= 0 && Offset + Count <= _size) + ); + return Span( + _data + Offset, + Count == SPAN_DYNAMIC_EXTENT ? _size - Offset : Count + ); + } + + /** + * Create a new Span over the first @p count elements of the existing view. + * + * @param count The number of element viewed by the new Span + * + * @return A new Span over the first @p count elements. + */ + Span first(index_type count) const { + MBED_ASSERT(0 <= count && count <= _size); + return Span(_data, count); + } + + /** + * Create a new span over the last @p count elements of the existing view. + * + * @param count The number of element viewed by the new Span + * + * @return A new Span over the last @p count elements. + */ + Span last(index_type count) const { + MBED_ASSERT(0 <= count && count <= _size); + return Span( + _data + (_size - count), + count + ); + } + + /** + * Create a subspan that is a view other count elements; the view starts at + * element offset. + * + * @param offset The offset of the first element viewed by the subspan. + * + * @param count The number of elements present in the subspan. If Count + * is equal to SPAN_DYNAMIC_EXTENT then a span starting at offset and + * containing the rest of the elements is returned. + * + * @return + */ + Span subspan( + index_type offset, index_type count = SPAN_DYNAMIC_EXTENT + ) const { + MBED_ASSERT(0 <= offset && offset <= _size); + MBED_ASSERT( + (count == SPAN_DYNAMIC_EXTENT) || + (count >= 0 && (offset + count <= _size)) + ); + return Span( + _data + offset, + count == SPAN_DYNAMIC_EXTENT ? _size - offset : count + ); + } + +private: + pointer _data; + index_type _size; }; /** @@ -470,10 +687,10 @@ bool operator!=(T (&lhs)[LhsExtent], const Span &rhs) * @note This helper avoids the typing of template parameter when Span is * created 'inline'. */ -template -Span make_Span(T (&elements)[Extent]) +template +Span make_Span(T (&elements)[Size]) { - return Span(elements); + return Span(elements); } /** @@ -489,7 +706,7 @@ Span make_Span(T (&elements)[Extent]) * @note This helper avoids the typing of template parameter when Span is * created 'inline'. */ -template +template Span make_Span(T *elements) { return Span(elements, Extent); @@ -509,7 +726,7 @@ Span make_Span(T *elements) * created 'inline'. */ template -Span make_Span(T *array_ptr, size_t array_size) +Span make_Span(T *array_ptr, ptrdiff_t array_size) { return Span(array_ptr, array_size); } From 938d802ea061f81579553b98cc12a24f19070671 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 22 Aug 2018 09:35:17 +0100 Subject: [PATCH 11/23] Span: Fix subspan return type --- platform/Span.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/platform/Span.h b/platform/Span.h index a502301f2c..50dde38459 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -243,7 +243,8 @@ struct Span { * @return */ template - Span subspan() const { + Span + subspan() const { MBED_STATIC_ASSERT( Offset == 0 || (Offset > 0 && Offset < Extent), "Invalid subspan offset" @@ -253,7 +254,7 @@ struct Span { (Count >= 0 && Offset + Count <= Extent), "Invalid subspan count" ); - return Span( + return Span( _data + Offset, Count == SPAN_DYNAMIC_EXTENT ? Extent - Offset : Count ); @@ -506,13 +507,14 @@ struct Span { * @return */ template - Span subspan() const { - MBED_ASSERT(Offset == 0 || (Offset > 0 && Offset < _size)); + Span + subspan() const { + MBED_ASSERT(0 <= Offset && Offset <= _size); MBED_ASSERT( (Count == SPAN_DYNAMIC_EXTENT) || (Count >= 0 && Offset + Count <= _size) ); - return Span( + return Span( _data + Offset, Count == SPAN_DYNAMIC_EXTENT ? _size - Offset : Count ); From 26b546bab39153a78a411de9411c133de7cb7e94 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 22 Aug 2018 09:40:13 +0100 Subject: [PATCH 12/23] Span: Improve readability of precondition checks --- platform/Span.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/platform/Span.h b/platform/Span.h index 50dde38459..2fb1673449 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -206,7 +206,7 @@ struct Span { template Span first() const { MBED_STATIC_ASSERT( - (Count >= 0) && (Count <= Extent), + (0 <= Count) && (Count <= Extent), "Invalid subspan extent" ); return Span(_data, Count); @@ -224,7 +224,7 @@ struct Span { template Span last() const { MBED_STATIC_ASSERT( - (Count >= 0) && (Count <= Extent), + (0 <= Count) && (Count <= Extent), "Invalid subspan extent" ); return Span(_data + (Extent - Count), Count); @@ -246,12 +246,12 @@ struct Span { Span subspan() const { MBED_STATIC_ASSERT( - Offset == 0 || (Offset > 0 && Offset < Extent), + 0 <= Offset && Offset <= Extent, "Invalid subspan offset" ); MBED_STATIC_ASSERT( (Count == SPAN_DYNAMIC_EXTENT) || - (Count >= 0 && Offset + Count <= Extent), + (0 <= Count && (Count + Offset) <= Extent), "Invalid subspan count" ); return Span( @@ -305,7 +305,7 @@ struct Span { MBED_ASSERT(0 <= offset && offset <= Extent); MBED_ASSERT( (count == SPAN_DYNAMIC_EXTENT) || - (count >= 0 && (offset + count <= Extent)) + (0 <= count && (count + offset) <= Extent) ); return Span( _data + offset, @@ -490,7 +490,7 @@ struct Span { */ template Span last() const { - MBED_ASSERT((Count >= 0) && (Count <= _size)); + MBED_ASSERT((0 <= Count) && (Count <= _size)); return Span(_data + (_size - Count), Count); } @@ -512,7 +512,7 @@ struct Span { MBED_ASSERT(0 <= Offset && Offset <= _size); MBED_ASSERT( (Count == SPAN_DYNAMIC_EXTENT) || - (Count >= 0 && Offset + Count <= _size) + (0 <= Count && (Count + Offset) <= _size) ); return Span( _data + Offset, @@ -565,7 +565,7 @@ struct Span { MBED_ASSERT(0 <= offset && offset <= _size); MBED_ASSERT( (count == SPAN_DYNAMIC_EXTENT) || - (count >= 0 && (offset + count <= _size)) + (0 <= count && (count + offset) <= _size) ); return Span( _data + offset, From f6dd5eaa316fdd6fb05e77289878ec5b50249c81 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 22 Aug 2018 13:31:26 +0100 Subject: [PATCH 13/23] Span: Fix static assert message in default constructor. --- platform/Span.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/Span.h b/platform/Span.h index 2fb1673449..0c06a30165 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -98,7 +98,10 @@ struct Span { * Extent != 0 . */ Span() : _data(NULL) { - MBED_STATIC_ASSERT(Extent == 0, "Invalid extent for a Span"); + MBED_STATIC_ASSERT( + Extent == 0, + "Cannot default construct a static-extent Span (unless Extent is 0)" + ); } /** From 95fc284a8334070c977b4c476de74a7c7922f6e6 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 22 Aug 2018 13:32:54 +0100 Subject: [PATCH 14/23] Span: add boundary check in subscript operator for debug profile --- platform/Span.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform/Span.h b/platform/Span.h index 0c06a30165..41e25ce18c 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -183,6 +183,9 @@ struct Span { */ reference operator[](index_type index) const { +#ifdef MBED_DEBUG + MBED_ASSERT(0 <= index && index < Extent); +#endif return _data[index]; } @@ -454,6 +457,9 @@ struct Span { */ reference operator[](index_type index) const { +#ifdef MBED_DEBUG + MBED_ASSERT(0 <= index && index < _size); +#endif return _data[index]; } From 4e7fa91b9470b1a764a3ebae7e6cfc92215d9323 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 22 Aug 2018 15:11:27 +0100 Subject: [PATCH 15/23] Span: amend documentation --- platform/Span.h | 203 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 157 insertions(+), 46 deletions(-) diff --git a/platform/Span.h b/platform/Span.h index 41e25ce18c..c4d7608eec 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -33,19 +33,130 @@ namespace mbed { #define SPAN_DYNAMIC_EXTENT -1 /** - * View to an array. + * Non owning view to a sequence of contiguous elements. * - * Spans encapsulate the pointer to an array and its size into a single object. - * However, it does not manage the lifetime of the array viewed. You can use - * instances of Span to replace the traditional pair of pointer and size - * arguments in function calls. + * Spans encapsulate a pointer to a sequence of contiguous elements and its size + * into a single object. Span can replace the traditional pair of pointer and + * size arguments passed as array definition in function calls. * - * You can use the size member function to query the number of elements present - * in the array, and the subscript operator allow code using this object to - * access the content of the array viewed. + * @paragraph Operations * - * Subspans can be created with the help of the functions first(), last() and - * subspan(). + * Span objects can be copied and assigned like regular value types with the help + * of copy constructor and copy assignment (=) operator. + * + * Elements of the object can be retrieved with the subscript ([]) operator. The + * pointer to the first element of the sequence viewed can be accessed with data() + * while the function size() returns the number of elements in the sequence and + * empty() informs if the there is any element in the sequence. + * + * Span can be sliced from the beginning of the sequence (first()), from the end + * of the sequence (last()) or from an arbitrary point of the sequence (subspan()). + * + * @paragraph Size encoding + * + * The size of the sequence can be encoded in the type itself or in the value of + * the instance with the help of the template parameter Extent: + * + * - Span: Span over a sequence of 6 element + * - Span: Span over an arbitrary long sequence. + * + * When the size is encoded in the type itself, it is guaranteed that the Span + * view a valid sequence (not empty() and not NULL). The type system also prevent + * automatic conversion from Span of different sizes. Finally, the size of the + * span object is a single pointer. + * + * When the size of the sequence viewed is encoded in the Span value, span + * instances can view invalid sequence (empty and NULL pointer). The function + * empty() helps client code to decide if valid content is being viewed or not. + * + * @paragraph Example + * + * - Encoding fixed size array: Array values in parameter decays automatically + * to pointer which leaves room for subtitle bugs: + * + * @code + * typedef uint8_t mac_address_t[6]; + * void process_mac(mac_address_t); + * + * // compile just fine + * uint8_t* invalid_value = NULL; + * process_mac(invalid_value); + * + * + * // correct way + * typedef Span mac_address_t; + * void process_mac(mac_address_t); + * + * // compilation error + * uint8_t* invalid_value = NULL; + * process_mac(invalid_value); + * + * // compilation ok + * uint8_t valid_value[6]; + * process_mac(valid_value); + * @endcode + * + * - Arbitrary buffer: When dealing with multiple buffers, it becomes painful to + * keep track of every buffer size and pointer. + * + * @code + * const uint8_t options_tag[OPTIONS_TAG_SIZE]; + * + * struct parsed_value_t { + * uint8_t* header; + * uint8_t* options; + * uint8_t* payload; + * size_t payload_size; + * } + * + * parsed_value_t parse(uint8_t* buffer, size_t buffer_size) { + * parsed_value_t parsed_value { 0 }; + * + * if (buffer != NULL && buffer_size <= MINIMAL_BUFFER_SIZE) { + * return parsed_value; + * } + * + * parsed_value.header = buffer; + * parsed_value.header_size = BUFFER_HEADER_SIZE; + * + * if (memcmp(buffer + HEADER_OPTIONS_INDEX, options_tag, sizeof(options_tag)) == 0) { + * options = buffer + BUFFER_HEADER_SIZE; + * payload = buffer + BUFFER_HEADER_SIZE + OPTIONS_SIZE; + * payload_size = buffer_size - BUFFER_HEADER_SIZE + OPTIONS_SIZE; + * } else { + * payload = buffer + BUFFER_HEADER_SIZE; + * payload_size = buffer_size - BUFFER_HEADER_SIZE; + * } + * + * return parsed_value; + * } + * + * + * //with span + * struct parsed_value_t { + * Span header; + * Span options; + * Span payload; + * } + * + * parsed_value_t parse(Span buffer) { + * parsed_value_t parsed_value; + * + * if (buffer.size() <= MINIMAL_BUFFER_SIZE) { + * return parsed_value; + * } + * + * parsed_value.header = buffer.first(BUFFER_HEADER_SIZE); + * + * if (buffer.subspan() == option_tag) { + * options = buffer.supspan(parsed_value.header.size(), OPTIONS_SIZE); + * } + * + * payload = buffer.subspan(parsed_value.header.size() + parsed_value.options.size()); + * + * return parsed_value; + * } + * @endcode * * @note You can create Span instances with the help of the function template * make_Span() and make_const_Span(). @@ -53,9 +164,9 @@ namespace mbed { * @note Span objects can be implicitly converted to Span objects * where required. * - * @tparam ElementType type of objects held in the array viewed. + * @tparam ElementType type of objects viewed by the Span. * - * @tparam Extent The size of the array viewed. The default value + * @tparam Extent The size of the contiguous sequence viewed. The default value * SPAN_DYNAMIC_SIZE is special as it allows construction of Span objects of * any size (set at runtime). */ @@ -90,7 +201,7 @@ struct Span { MBED_STATIC_ASSERT(Extent >= 0, "Invalid extent for a Span"); /** - * Construct an empty span. + * Construct an empty Span. * * @post a call to size() will return 0, and data() will return NULL. * @@ -112,7 +223,7 @@ struct Span { * @param count Number of elements viewed. * * @pre [ptr, ptr + count) must be be a valid range. - * @pre count must be equal to extent. + * @pre count must be equal to Extent. * * @post a call to size() will return Extent and data() will return @p ptr. */ @@ -153,9 +264,9 @@ struct Span { _data(elements) { } /** - * Return the size of the array viewed. + * Return the size of the sequence viewed. * - * @return The number of elements present in the array viewed. + * @return The size of the sequence viewed. */ index_type size() const { @@ -163,9 +274,9 @@ struct Span { } /** - * Return if the array is empty or not. + * Return if the sequence is empty or not. * - * @return true if the array is empty and false otherwise + * @return true if the sequence is empty and false otherwise */ bool empty() const { @@ -190,10 +301,10 @@ struct Span { } /** - * Return a pointer to the first element of the sequence or NULL if the span + * Return a pointer to the first element of the sequence or NULL if the Span * is empty(). * - * @return The pointer to the first element of the span. + * @return The pointer to the first element of the Span. */ pointer data() const { @@ -246,7 +357,7 @@ struct Span { * is equal to SPAN_DYNAMIC_EXTENT then a span starting at offset and * containing the rest of the elements is returned. * - * @return + * @return A subspan of this starting at Offset and Count long. */ template Span @@ -324,7 +435,7 @@ private: }; /** - * Span specialisation that handle dynamic array size. + * Span specialisation that handle dynamic size. */ template struct Span { @@ -355,7 +466,7 @@ struct Span { static const index_type extent = SPAN_DYNAMIC_EXTENT; /** - * Construct an empty span. + * Construct an empty Span. * * @post a call to size() will return 0, and data() will return NULL. * @@ -437,9 +548,9 @@ struct Span { } /** - * Return if the array is empty or not. + * Return if the sequence viewed is empty or not. * - * @return true if the array is empty and false otherwise + * @return true if the sequence is empty and false otherwise */ bool empty() const { @@ -447,7 +558,7 @@ struct Span { } /** - * Access to an element of the array. + * Access to an element of the sequence. * * @param index Element index to access. * @@ -464,9 +575,9 @@ struct Span { } /** - * Get the raw pointer to the array. + * Get the raw pointer to the sequence viewed. * - * @return The raw pointer to the array. + * @return The raw pointer to the first element viewed. */ pointer data() const { @@ -474,7 +585,7 @@ struct Span { } /** - * Create a new span over the first @p Count elements of the existing view. + * Create a new Span over the first @p Count elements of the existing view. * * @tparam Count The number of element viewed by the new Span * @@ -489,7 +600,7 @@ struct Span { } /** - * Create a new span over the last @p Count elements of the existing view. + * Create a new Span over the last @p Count elements of the existing view. * * @tparam Count The number of element viewed by the new Span * @@ -513,7 +624,7 @@ struct Span { * is equal to SPAN_DYNAMIC_EXTENT then a span starting at offset and * containing the rest of the elements is returned. * - * @return + * @return A subspan of this starting at Offset and Count long. */ template Span @@ -542,7 +653,7 @@ struct Span { } /** - * Create a new span over the last @p count elements of the existing view. + * Create a new Span over the last @p count elements of the existing view. * * @param count The number of element viewed by the new Span * @@ -566,7 +677,7 @@ struct Span { * is equal to SPAN_DYNAMIC_EXTENT then a span starting at offset and * containing the rest of the elements is returned. * - * @return + * @return A subspan of this starting at offset and count long. */ Span subspan( index_type offset, index_type count = SPAN_DYNAMIC_EXTENT @@ -593,8 +704,8 @@ private: * @param lhs Left hand side of the binary operation. * @param rhs Right hand side of the binary operation. * - * @return True if arrays in input have the same size and the same content - * and false otherwise. + * @return True if Spans in input have the same size and the same content and + * false otherwise. */ template bool operator==(const Span &lhs, const Span &rhs) @@ -616,8 +727,8 @@ bool operator==(const Span &lhs, const Span &rhs) * @param lhs Left hand side of the binary operation. * @param rhs Right hand side of the binary operation. * - * @return True if arrays in input have the same size and the same content - * and false otherwise. + * @return True if elements in input have the same size and the same content and + * false otherwise. */ template bool operator==(const Span &lhs, T (&rhs)[RhsExtent]) @@ -626,12 +737,12 @@ bool operator==(const Span &lhs, T (&rhs)[RhsExtent]) } /** - * Equality operation between a span and a reference to a C++ array. + * Equality operation between a Span and a reference to a C++ array. * * @param lhs Left hand side of the binary operation. * @param rhs Right hand side of the binary operation. * - * @return True if arrays in input have the same size and the same content + * @return True if elements in input have the same size and the same content * and false otherwise. */ template @@ -646,8 +757,8 @@ bool operator==(T (&lhs)[LhsExtent], const Span &rhs) * @param lhs Left hand side of the binary operation. * @param rhs Right hand side of the binary operation. * - * @return True if arrays in input do not have the same size or the same - * content and false otherwise. + * @return True if arrays in input do not have the same size or the same content + * and false otherwise. */ template bool operator!=(const Span &lhs, const Span &rhs) @@ -656,12 +767,12 @@ bool operator!=(const Span &lhs, const Span &rhs) } /** - * Not Equal operation between a span and a reference to a C++ array. + * Not Equal operation between a Span and a reference to a C++ array. * * @param lhs Left hand side of the binary operation. * @param rhs Right hand side of the binary operation. * - * @return True if arrays in input have the same size and the same content + * @return True if elements in input have the same size and the same content * and false otherwise. */ template @@ -671,12 +782,12 @@ bool operator!=(const Span &lhs, T (&rhs)[RhsExtent]) } /** - * Not Equal operation between a span and a reference to a C++ array. + * Not Equal operation between a Span and a reference to a C++ array. * * @param lhs Left hand side of the binary operation. * @param rhs Right hand side of the binary operation. * - * @return True if arrays in input have the same size and the same content + * @return True if elements in input have the same size and the same content * and false otherwise. */ template @@ -728,7 +839,7 @@ Span make_Span(T *elements) * * @tparam T Type of elements held in array_ptr. * - * @param array_ptr The pointer to the array to viewed. + * @param array_ptr The pointer to the array viewed. * @param array_size The number of T elements in the array. * * @return The Span to array_ptr with a size of array_size. From 6b08320573b72b7ea30023dfed4989694f75bf7e Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 23 Aug 2018 09:02:28 +0100 Subject: [PATCH 16/23] Span: Fix doxygen tags. --- platform/Span.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/Span.h b/platform/Span.h index c4d7608eec..64b4546a15 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -39,7 +39,7 @@ namespace mbed { * into a single object. Span can replace the traditional pair of pointer and * size arguments passed as array definition in function calls. * - * @paragraph Operations + * @par Operations * * Span objects can be copied and assigned like regular value types with the help * of copy constructor and copy assignment (=) operator. @@ -52,7 +52,7 @@ namespace mbed { * Span can be sliced from the beginning of the sequence (first()), from the end * of the sequence (last()) or from an arbitrary point of the sequence (subspan()). * - * @paragraph Size encoding + * @par Size encoding * * The size of the sequence can be encoded in the type itself or in the value of * the instance with the help of the template parameter Extent: @@ -69,7 +69,7 @@ namespace mbed { * instances can view invalid sequence (empty and NULL pointer). The function * empty() helps client code to decide if valid content is being viewed or not. * - * @paragraph Example + * @par Example * * - Encoding fixed size array: Array values in parameter decays automatically * to pointer which leaves room for subtitle bugs: From 33ca10192da6bf55335d05962508ab25fbe5ab94 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 23 Aug 2018 11:38:32 +0100 Subject: [PATCH 17/23] Span: Fix documentation. --- platform/Span.h | 164 ++++++++++++++++++++++++------------------------ 1 file changed, 82 insertions(+), 82 deletions(-) diff --git a/platform/Span.h b/platform/Span.h index 64b4546a15..0b3177a80e 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -57,17 +57,17 @@ namespace mbed { * The size of the sequence can be encoded in the type itself or in the value of * the instance with the help of the template parameter Extent: * - * - Span: Span over a sequence of 6 element + * - Span: Span over a sequence of 6 elements. * - Span: Span over an arbitrary long sequence. * * When the size is encoded in the type itself, it is guaranteed that the Span - * view a valid sequence (not empty() and not NULL). The type system also prevent - * automatic conversion from Span of different sizes. Finally, the size of the - * span object is a single pointer. + * view a valid sequence (not empty() and not NULL) - unless Extent equals 0. + * The type system also prevents automatic conversion from Span of different + * sizes. Finally, the Span object is internally represented as a single pointer. * - * When the size of the sequence viewed is encoded in the Span value, span - * instances can view invalid sequence (empty and NULL pointer). The function - * empty() helps client code to decide if valid content is being viewed or not. + * When the size of the sequence viewed is encoded in the Span value, Span + * instances can view an empty sequence. The function empty() helps client code + * to decide if valid content is being viewed or not. * * @par Example * @@ -75,87 +75,87 @@ namespace mbed { * to pointer which leaves room for subtitle bugs: * * @code - * typedef uint8_t mac_address_t[6]; - * void process_mac(mac_address_t); - * - * // compile just fine - * uint8_t* invalid_value = NULL; - * process_mac(invalid_value); - * - * - * // correct way - * typedef Span mac_address_t; - * void process_mac(mac_address_t); - * - * // compilation error - * uint8_t* invalid_value = NULL; - * process_mac(invalid_value); - * - * // compilation ok - * uint8_t valid_value[6]; - * process_mac(valid_value); + typedef uint8_t mac_address_t[6]; + void process_mac(mac_address_t); + + // compile just fine + uint8_t* invalid_value = NULL; + process_mac(invalid_value); + + + // correct way + typedef Span mac_address_t; + void process_mac(mac_address_t); + + // compilation error + uint8_t* invalid_value = NULL; + process_mac(invalid_value); + + // compilation ok + uint8_t valid_value[6]; + process_mac(valid_value); * @endcode * * - Arbitrary buffer: When dealing with multiple buffers, it becomes painful to * keep track of every buffer size and pointer. * * @code - * const uint8_t options_tag[OPTIONS_TAG_SIZE]; - * - * struct parsed_value_t { - * uint8_t* header; - * uint8_t* options; - * uint8_t* payload; - * size_t payload_size; - * } - * - * parsed_value_t parse(uint8_t* buffer, size_t buffer_size) { - * parsed_value_t parsed_value { 0 }; - * - * if (buffer != NULL && buffer_size <= MINIMAL_BUFFER_SIZE) { - * return parsed_value; - * } - * - * parsed_value.header = buffer; - * parsed_value.header_size = BUFFER_HEADER_SIZE; - * - * if (memcmp(buffer + HEADER_OPTIONS_INDEX, options_tag, sizeof(options_tag)) == 0) { - * options = buffer + BUFFER_HEADER_SIZE; - * payload = buffer + BUFFER_HEADER_SIZE + OPTIONS_SIZE; - * payload_size = buffer_size - BUFFER_HEADER_SIZE + OPTIONS_SIZE; - * } else { - * payload = buffer + BUFFER_HEADER_SIZE; - * payload_size = buffer_size - BUFFER_HEADER_SIZE; - * } - * - * return parsed_value; - * } - * - * - * //with span - * struct parsed_value_t { - * Span header; - * Span options; - * Span payload; - * } - * - * parsed_value_t parse(Span buffer) { - * parsed_value_t parsed_value; - * - * if (buffer.size() <= MINIMAL_BUFFER_SIZE) { - * return parsed_value; - * } - * - * parsed_value.header = buffer.first(BUFFER_HEADER_SIZE); - * - * if (buffer.subspan() == option_tag) { - * options = buffer.supspan(parsed_value.header.size(), OPTIONS_SIZE); - * } - * - * payload = buffer.subspan(parsed_value.header.size() + parsed_value.options.size()); - * - * return parsed_value; - * } + const uint8_t options_tag[OPTIONS_TAG_SIZE]; + + struct parsed_value_t { + uint8_t* header; + uint8_t* options; + uint8_t* payload; + size_t payload_size; + } + + parsed_value_t parse(uint8_t* buffer, size_t buffer_size) { + parsed_value_t parsed_value { 0 }; + + if (buffer != NULL && buffer_size <= MINIMAL_BUFFER_SIZE) { + return parsed_value; + } + + parsed_value.header = buffer; + parsed_value.header_size = BUFFER_HEADER_SIZE; + + if (memcmp(buffer + HEADER_OPTIONS_INDEX, options_tag, sizeof(options_tag)) == 0) { + options = buffer + BUFFER_HEADER_SIZE; + payload = buffer + BUFFER_HEADER_SIZE + OPTIONS_SIZE; + payload_size = buffer_size - BUFFER_HEADER_SIZE + OPTIONS_SIZE; + } else { + payload = buffer + BUFFER_HEADER_SIZE; + payload_size = buffer_size - BUFFER_HEADER_SIZE; + } + + return parsed_value; + } + + + //with span + struct parsed_value_t { + Span header; + Span options; + Span payload; + } + + parsed_value_t parse(Span buffer) { + parsed_value_t parsed_value; + + if (buffer.size() <= MINIMAL_BUFFER_SIZE) { + return parsed_value; + } + + parsed_value.header = buffer.first(BUFFER_HEADER_SIZE); + + if (buffer.subspan() == option_tag) { + options = buffer.supspan(parsed_value.header.size(), OPTIONS_SIZE); + } + + payload = buffer.subspan(parsed_value.header.size() + parsed_value.options.size()); + + return parsed_value; + } * @endcode * * @note You can create Span instances with the help of the function template From 2a6c6d5985b89bac6c5aea9347fc864f8bca9f13 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 23 Aug 2018 12:41:04 +0100 Subject: [PATCH 18/23] Span: Use mbed way of writing types in documentation example. --- platform/Span.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/platform/Span.h b/platform/Span.h index 0b3177a80e..274dfb09ee 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -79,7 +79,7 @@ namespace mbed { void process_mac(mac_address_t); // compile just fine - uint8_t* invalid_value = NULL; + uint8_t *invalid_value = NULL; process_mac(invalid_value); @@ -88,7 +88,7 @@ namespace mbed { void process_mac(mac_address_t); // compilation error - uint8_t* invalid_value = NULL; + uint8_t *invalid_value = NULL; process_mac(invalid_value); // compilation ok @@ -103,13 +103,13 @@ namespace mbed { const uint8_t options_tag[OPTIONS_TAG_SIZE]; struct parsed_value_t { - uint8_t* header; - uint8_t* options; - uint8_t* payload; + uint8_t *header; + uint8_t *options; + uint8_t *payload; size_t payload_size; } - parsed_value_t parse(uint8_t* buffer, size_t buffer_size) { + parsed_value_t parse(uint8_t *buffer, size_t buffer_size) { parsed_value_t parsed_value { 0 }; if (buffer != NULL && buffer_size <= MINIMAL_BUFFER_SIZE) { @@ -139,7 +139,7 @@ namespace mbed { Span payload; } - parsed_value_t parse(Span buffer) { + parsed_value_t parse(const Span &buffer) { parsed_value_t parsed_value; if (buffer.size() <= MINIMAL_BUFFER_SIZE) { From b7f074ef68e8f2ff528a40d3dc72e5f0368807d3 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 23 Aug 2018 14:02:26 +0100 Subject: [PATCH 19/23] Span: Fix opening brace position. --- platform/Span.h | 61 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/platform/Span.h b/platform/Span.h index 274dfb09ee..325a0e8878 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -109,7 +109,8 @@ namespace mbed { size_t payload_size; } - parsed_value_t parse(uint8_t *buffer, size_t buffer_size) { + parsed_value_t parse(uint8_t *buffer, size_t buffer_size) + { parsed_value_t parsed_value { 0 }; if (buffer != NULL && buffer_size <= MINIMAL_BUFFER_SIZE) { @@ -139,7 +140,8 @@ namespace mbed { Span payload; } - parsed_value_t parse(const Span &buffer) { + parsed_value_t parse(const Span &buffer) + { parsed_value_t parsed_value; if (buffer.size() <= MINIMAL_BUFFER_SIZE) { @@ -208,7 +210,9 @@ struct Span { * @note This function is not accessible if Extent != SPAN_DYNAMIC_EXTENT or * Extent != 0 . */ - Span() : _data(NULL) { + Span() : + _data(NULL) + { MBED_STATIC_ASSERT( Extent == 0, "Cannot default construct a static-extent Span (unless Extent is 0)" @@ -228,7 +232,8 @@ struct Span { * @post a call to size() will return Extent and data() will return @p ptr. */ Span(pointer ptr, index_type count) : - _data(ptr) { + _data(ptr) + { MBED_ASSERT(count == Extent); MBED_ASSERT(Extent == 0 || ptr != NULL); } @@ -246,7 +251,8 @@ struct Span { * @post a call to size() will return Extent and data() will return @p first. */ Span(pointer first, pointer last) : - _data(first) { + _data(first) + { MBED_ASSERT(first <= last); MBED_ASSERT((last - first) == Extent); MBED_ASSERT(Extent == 0 || first != NULL); @@ -321,7 +327,8 @@ struct Span { * @pre Count >= 0 && Count <= size(). */ template - Span first() const { + Span first() const + { MBED_STATIC_ASSERT( (0 <= Count) && (Count <= Extent), "Invalid subspan extent" @@ -339,7 +346,8 @@ struct Span { * @pre Count >= 0 && Count <= size(). */ template - Span last() const { + Span last() const + { MBED_STATIC_ASSERT( (0 <= Count) && (Count <= Extent), "Invalid subspan extent" @@ -361,7 +369,8 @@ struct Span { */ template Span - subspan() const { + subspan() const + { MBED_STATIC_ASSERT( 0 <= Offset && Offset <= Extent, "Invalid subspan offset" @@ -384,7 +393,8 @@ struct Span { * * @return A new Span over the first @p count elements. */ - Span first(index_type count) const { + Span first(index_type count) const + { MBED_ASSERT(0 <= count && count <= Extent); return Span(_data, count); } @@ -396,7 +406,8 @@ struct Span { * * @return A new Span over the last @p count elements. */ - Span last(index_type count) const { + Span last(index_type count) const + { MBED_ASSERT(0 <= count && count <= Extent); return Span( _data + (Extent - count), @@ -418,7 +429,8 @@ struct Span { */ Span subspan( index_type offset, index_type count = SPAN_DYNAMIC_EXTENT - ) const { + ) const + { MBED_ASSERT(0 <= offset && offset <= Extent); MBED_ASSERT( (count == SPAN_DYNAMIC_EXTENT) || @@ -473,7 +485,8 @@ struct Span { * @note This function is not accessible if Extent != SPAN_DYNAMIC_EXTENT or * Extent != 0 . */ - Span() : _data(NULL), _size(0) { } + Span() : + _data(NULL), _size(0) { } /** * Construct a Span from a pointer to a buffer and its size. @@ -488,7 +501,8 @@ struct Span { * @post a call to size() will return count and data() will return @p ptr. */ Span(pointer ptr, index_type count) : - _data(ptr), _size(count) { + _data(ptr), _size(count) + { MBED_ASSERT(count >= 0); MBED_ASSERT(ptr != NULL || count == 0); } @@ -506,7 +520,8 @@ struct Span { * data() will return @p first. */ Span(pointer first, pointer last) : - _data(first), _size(last - first) { + _data(first), _size(last - first) + { MBED_ASSERT(first <= last); MBED_ASSERT(first != NULL || (last - first) == 0); } @@ -594,7 +609,8 @@ struct Span { * @pre Count >= 0 && Count <= size(). */ template - Span first() const { + Span first() const + { MBED_ASSERT((Count >= 0) && (Count <= _size)); return Span(_data, Count); } @@ -609,7 +625,8 @@ struct Span { * @pre Count >= 0 && Count <= size(). */ template - Span last() const { + Span last() const + { MBED_ASSERT((0 <= Count) && (Count <= _size)); return Span(_data + (_size - Count), Count); } @@ -628,7 +645,8 @@ struct Span { */ template Span - subspan() const { + subspan() const + { MBED_ASSERT(0 <= Offset && Offset <= _size); MBED_ASSERT( (Count == SPAN_DYNAMIC_EXTENT) || @@ -647,7 +665,8 @@ struct Span { * * @return A new Span over the first @p count elements. */ - Span first(index_type count) const { + Span first(index_type count) const + { MBED_ASSERT(0 <= count && count <= _size); return Span(_data, count); } @@ -659,7 +678,8 @@ struct Span { * * @return A new Span over the last @p count elements. */ - Span last(index_type count) const { + Span last(index_type count) const + { MBED_ASSERT(0 <= count && count <= _size); return Span( _data + (_size - count), @@ -681,7 +701,8 @@ struct Span { */ Span subspan( index_type offset, index_type count = SPAN_DYNAMIC_EXTENT - ) const { + ) const + { MBED_ASSERT(0 <= offset && offset <= _size); MBED_ASSERT( (count == SPAN_DYNAMIC_EXTENT) || From d5051a8ca7acf5d232f0eea257e820fa5c1689c4 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 23 Aug 2018 18:41:53 +0100 Subject: [PATCH 20/23] Span: Allow copy construction from convertible span. Addition of these overloads help when Span is constructed from Span. --- platform/Span.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/platform/Span.h b/platform/Span.h index 325a0e8878..eb46c8afb4 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -25,6 +25,36 @@ namespace mbed { +// Internal details of span +// It is used construct span from span of convertible types (non const -> const) +namespace span_detail { + +// If From type is convertible to To type then the compilation constant value is +// true otherwise it is false. +template +class is_convertible +{ + struct true_type { char x[512]; }; + struct false_type { }; + + static const From& generator(); + static true_type sink(const To &); + static false_type sink(...); + +public: + static const bool value = sizeof(true_type) == sizeof(sink(generator())); +}; + +template +struct enable_if; + +template +struct enable_if { + typedef ResultType type; +}; + +} + /** * Special value for the Extent parameter of Span. * If the type use this value then the size of the array is stored in the object @@ -269,6 +299,24 @@ struct Span { Span(element_type (&elements)[Extent]): _data(elements) { } + /** + * Construct a Span object from another Span of the same size. + * + * @param other The Span object used to construct this. + * + * @note For span with a positive extent, this function is not accessible. + * + * @note OtherElementType(*)[] should be convertible to ElementType(*)[]. + */ + template + Span( + const Span &other, + typename span_detail::enable_if< + span_detail::is_convertible::value + >::type* = 0 + ): + _data(other.data()) { } + /** * Return the size of the sequence viewed. * @@ -540,16 +588,22 @@ struct Span { Span(element_type (&elements)[Count]): _data(elements), _size(Count) { } - /** * Construct a Span object from another Span. * * @param other The Span object used to construct this. * * @note For span with a positive extent, this function is not accessible. + * + * @note OtherElementType(*)[] should be convertible to ElementType(*)[]. */ - template - Span(const Span &other): + template + Span( + const Span &other, + typename span_detail::enable_if< + span_detail::is_convertible::value + >::type* = NULL + ): _data(other.data()), _size(other.size()) { } /** From af69e1fb8bfc2c4f53abc0bffed852a3394eb245 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 24 Aug 2018 11:10:17 +0100 Subject: [PATCH 21/23] Span: use static assert to kill copy construction from an incompatible span type. Copy construction between Span of compatible type is allowed to fulfil the use case Span -> Span. This is achieved by a templated copy constructor like constructor. In p0122, the overload is discarded from the constructor set if the ElementType of the Span in input is not convertible into the ElementType of the Span being constructed. To discard function overload, SFINAE has to be used which polutes the documentation and make the code harder to read and maintain. Unlike p0122, our Span class doesn't exposes (yet) functions with default argument or functions that convert container in input into span the only overload with the a single parameter that we exposes are: - template Span(ElementType (&element)[N]) - Span(const Span& other): <- generated by the compiler. For both of this functions we expect exact match and their resolution should not interfere with the constructor that converts from another type of Span. As a result it is possible to rely solely on C++ default resolution rules as we won't hit cases were constructors convert from another type (std::array, std container, span) and raise an error with a static assert if the element type can't be converted. If another copy - conversion - constructor is added then SFINAE has to be reintroduced. --- platform/Span.h | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/platform/Span.h b/platform/Span.h index eb46c8afb4..3e04b1ea92 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -45,14 +45,6 @@ public: static const bool value = sizeof(true_type) == sizeof(sink(generator())); }; -template -struct enable_if; - -template -struct enable_if { - typedef ResultType type; -}; - } /** @@ -309,13 +301,14 @@ struct Span { * @note OtherElementType(*)[] should be convertible to ElementType(*)[]. */ template - Span( - const Span &other, - typename span_detail::enable_if< - span_detail::is_convertible::value - >::type* = 0 - ): - _data(other.data()) { } + Span(const Span &other): + _data(other.data()) + { + MBED_STATIC_ASSERT( + (span_detail::is_convertible::value), + "OtherElementType(*)[] should be convertible to ElementType (*)[]" + ); + } /** * Return the size of the sequence viewed. @@ -499,7 +492,6 @@ private: */ template struct Span { - /** * Type of the element contained */ @@ -598,13 +590,14 @@ struct Span { * @note OtherElementType(*)[] should be convertible to ElementType(*)[]. */ template - Span( - const Span &other, - typename span_detail::enable_if< - span_detail::is_convertible::value - >::type* = NULL - ): - _data(other.data()), _size(other.size()) { } + Span(const Span &other): + _data(other.data()), _size(other.size()) + { + MBED_STATIC_ASSERT( + (span_detail::is_convertible::value), + "OtherElementType(*)[] should be convertible to ElementType (*)[]" + ); + } /** * Return the size of the array viewed. From bf08651d3af956c4aa82e508264dbb97cdd93e34 Mon Sep 17 00:00:00 2001 From: Amanda Butler Date: Fri, 24 Aug 2018 09:31:10 -0500 Subject: [PATCH 22/23] Copy edit Span.h Copy edit file, mostly for consistent capitalization, punctuation and tense. --- platform/Span.h | 150 ++++++++++++++++++++++++------------------------ 1 file changed, 75 insertions(+), 75 deletions(-) diff --git a/platform/Span.h b/platform/Span.h index 3e04b1ea92..c1b0ce171f 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -25,12 +25,12 @@ namespace mbed { -// Internal details of span -// It is used construct span from span of convertible types (non const -> const) +// Internal details of Span +// It is used construct Span from Span of convertible types (non const -> const) namespace span_detail { -// If From type is convertible to To type then the compilation constant value is -// true otherwise it is false. +// If From type is convertible to To type, then the compilation constant value is +// true; otherwise, it is false. template class is_convertible { @@ -49,29 +49,29 @@ public: /** * Special value for the Extent parameter of Span. - * If the type use this value then the size of the array is stored in the object + * If the type uses this value, then the size of the array is stored in the object * at runtime. */ #define SPAN_DYNAMIC_EXTENT -1 /** - * Non owning view to a sequence of contiguous elements. + * Nonowning view to a sequence of contiguous elements. * * Spans encapsulate a pointer to a sequence of contiguous elements and its size * into a single object. Span can replace the traditional pair of pointer and - * size arguments passed as array definition in function calls. + * size arguments passed as array definitions in function calls. * * @par Operations * * Span objects can be copied and assigned like regular value types with the help - * of copy constructor and copy assignment (=) operator. + * of copy constructor and copy assignment (=) operators. * - * Elements of the object can be retrieved with the subscript ([]) operator. The - * pointer to the first element of the sequence viewed can be accessed with data() - * while the function size() returns the number of elements in the sequence and - * empty() informs if the there is any element in the sequence. + * You can retrieve elements of the object with the subscript ([]) operator. You can access the + * pointer to the first element of the sequence viewed with data(). + * The function size() returns the number of elements in the sequence, and + * empty() informs whether there is any element in the sequence. * - * Span can be sliced from the beginning of the sequence (first()), from the end + * You can splice Span from the beginning of the sequence (first()), from the end * of the sequence (last()) or from an arbitrary point of the sequence (subspan()). * * @par Size encoding @@ -83,18 +83,18 @@ public: * - Span: Span over an arbitrary long sequence. * * When the size is encoded in the type itself, it is guaranteed that the Span - * view a valid sequence (not empty() and not NULL) - unless Extent equals 0. + * view is a valid sequence (not empty() and not NULL) - unless Extent equals 0. * The type system also prevents automatic conversion from Span of different * sizes. Finally, the Span object is internally represented as a single pointer. * * When the size of the sequence viewed is encoded in the Span value, Span * instances can view an empty sequence. The function empty() helps client code - * to decide if valid content is being viewed or not. + * decide whether Span is viewing valid content or not. * * @par Example * * - Encoding fixed size array: Array values in parameter decays automatically - * to pointer which leaves room for subtitle bugs: + * to pointer, which leaves room for subtitle bugs: * * @code typedef uint8_t mac_address_t[6]; @@ -155,7 +155,7 @@ public: } - //with span + //with Span struct parsed_value_t { Span header; Span options; @@ -188,10 +188,10 @@ public: * @note Span objects can be implicitly converted to Span objects * where required. * - * @tparam ElementType type of objects viewed by the Span. + * @tparam ElementType type of objects the Span views. * * @tparam Extent The size of the contiguous sequence viewed. The default value - * SPAN_DYNAMIC_SIZE is special as it allows construction of Span objects of + * SPAN_DYNAMIC_SIZE is special because it allows construction of Span objects of * any size (set at runtime). */ template @@ -227,7 +227,7 @@ struct Span { /** * Construct an empty Span. * - * @post a call to size() will return 0, and data() will return NULL. + * @post a call to size() returns 0, and data() returns NULL. * * @note This function is not accessible if Extent != SPAN_DYNAMIC_EXTENT or * Extent != 0 . @@ -251,7 +251,7 @@ struct Span { * @pre [ptr, ptr + count) must be be a valid range. * @pre count must be equal to Extent. * - * @post a call to size() will return Extent and data() will return @p ptr. + * @post a call to size() returns Extent, and data() returns @p ptr. */ Span(pointer ptr, index_type count) : _data(ptr) @@ -261,16 +261,16 @@ struct Span { } /** - * Construct a Span from the range [first, last) + * Construct a Span from the range [first, last). * * @param first Pointer to the beginning of the data viewed. * @param last End of the range (element after the last element). * * @pre [first, last) must be be a valid range. - * @pre first <= last + * @pre first <= last. * @pre last - first must be equal to Extent. * - * @post a call to size() will return Extent and data() will return @p first. + * @post a call to size() returns Extent, and data() returns @p first. */ Span(pointer first, pointer last) : _data(first) @@ -285,7 +285,7 @@ struct Span { * * @param elements Reference to the array viewed. * - * @post a call to size() will return Extent, and data() will return a + * @post a call to size() returns Extent, and data() returns a * pointer to elements. */ Span(element_type (&elements)[Extent]): @@ -296,9 +296,9 @@ struct Span { * * @param other The Span object used to construct this. * - * @note For span with a positive extent, this function is not accessible. + * @note For Span with a positive extent, this function is not accessible. * - * @note OtherElementType(*)[] should be convertible to ElementType(*)[]. + * @note OtherElementType(*)[] is convertible to ElementType(*)[]. */ template Span(const Span &other): @@ -323,7 +323,7 @@ struct Span { /** * Return if the sequence is empty or not. * - * @return true if the sequence is empty and false otherwise + * @return true if the sequence is empty and false otherwise. */ bool empty() const { @@ -331,13 +331,13 @@ struct Span { } /** - * Returns a reference to the element at position @p index + * Returns a reference to the element at position @p index. * * @param index Index of the element to access. * * @return A reference to the element at the index specified in input. * - * @pre 0 <= index < Extent + * @pre 0 <= index < Extent. */ reference operator[](index_type index) const { @@ -359,7 +359,7 @@ struct Span { } /** - * Create a new span over the first @p Count elements of the existing view. + * Create a new Span over the first @p Count elements of the existing view. * * @tparam Count The number of element viewed by the new Span * @@ -378,9 +378,9 @@ struct Span { } /** - * Create a new span over the last @p Count elements of the existing view. + * Create a new Span over the last @p Count elements of the existing view. * - * @tparam Count The number of element viewed by the new Span + * @tparam Count The number of element viewed by the new Span. * * @return A new Span over the last @p Count elements. * @@ -397,13 +397,13 @@ struct Span { } /** - * Create a subspan that is a view other Count elements; the view starts at + * Create a subspan that is a view of other Count elements; the view starts at * element Offset. * * @tparam Offset The offset of the first element viewed by the subspan. * * @tparam Count The number of elements present in the subspan. If Count - * is equal to SPAN_DYNAMIC_EXTENT then a span starting at offset and + * is equal to SPAN_DYNAMIC_EXTENT, then a Span starting at offset and * containing the rest of the elements is returned. * * @return A subspan of this starting at Offset and Count long. @@ -430,7 +430,7 @@ struct Span { /** * Create a new Span over the first @p count elements of the existing view. * - * @param count The number of element viewed by the new Span + * @param count The number of element viewed by the new Span. * * @return A new Span over the first @p count elements. */ @@ -441,9 +441,9 @@ struct Span { } /** - * Create a new span over the last @p count elements of the existing view. + * Create a new Span over the last @p count elements of the existing view. * - * @param count The number of element viewed by the new Span + * @param count The number of elements viewed by the new Span. * * @return A new Span over the last @p count elements. */ @@ -457,13 +457,13 @@ struct Span { } /** - * Create a subspan that is a view other count elements; the view starts at + * Create a subspan that is a view of other count elements; the view starts at * element offset. * * @param offset The offset of the first element viewed by the subspan. * * @param count The number of elements present in the subspan. If Count - * is equal to SPAN_DYNAMIC_EXTENT then a span starting at offset and + * is equal to SPAN_DYNAMIC_EXTENT, then a span starting at offset and * containing the rest of the elements is returned. * * @return @@ -488,12 +488,12 @@ private: }; /** - * Span specialisation that handle dynamic size. + * Span specialization that handle dynamic size. */ template struct Span { /** - * Type of the element contained + * Type of the element contained. */ typedef ElementType element_type; @@ -503,12 +503,12 @@ struct Span { typedef ptrdiff_t index_type; /** - * Pointer to an ElementType + * Pointer to an ElementType. */ typedef element_type *pointer; /** - * Reference to an ElementType + * Reference to an ElementType. */ typedef element_type &reference; @@ -520,7 +520,7 @@ struct Span { /** * Construct an empty Span. * - * @post a call to size() will return 0, and data() will return NULL. + * @post a call to size() returns 0, and data() returns NULL. * * @note This function is not accessible if Extent != SPAN_DYNAMIC_EXTENT or * Extent != 0 . @@ -538,7 +538,7 @@ struct Span { * @pre [ptr, ptr + count) must be be a valid range. * @pre count must be equal to extent. * - * @post a call to size() will return count and data() will return @p ptr. + * @post a call to size() returns count, and data() returns @p ptr. */ Span(pointer ptr, index_type count) : _data(ptr), _size(count) @@ -548,16 +548,16 @@ struct Span { } /** - * Construct a Span from the range [first, last) + * Construct a Span from the range [first, last). * * @param first Pointer to the beginning of the data viewed. * @param last End of the range (element after the last element). * * @pre [first, last) must be be a valid range. - * @pre first <= last + * @pre first <= last. * - * @post a call to size() will return the result of (last - first) and - * data() will return @p first. + * @post a call to size() returns the result of (last - first), and + * data() returns @p first. */ Span(pointer first, pointer last) : _data(first), _size(last - first) @@ -573,7 +573,7 @@ struct Span { * * @tparam Count Number of elements of T presents in the array. * - * @post a call to size() will return Count, and data() will return a + * @post a call to size() returns Count, and data() returns a * pointer to elements. */ template @@ -585,9 +585,9 @@ struct Span { * * @param other The Span object used to construct this. * - * @note For span with a positive extent, this function is not accessible. + * @note For Span with a positive extent, this function is not accessible. * - * @note OtherElementType(*)[] should be convertible to ElementType(*)[]. + * @note OtherElementType(*)[] is convertible to ElementType(*)[]. */ template Span(const Span &other): @@ -612,7 +612,7 @@ struct Span { /** * Return if the sequence viewed is empty or not. * - * @return true if the sequence is empty and false otherwise + * @return true if the sequence is empty and false otherwise. */ bool empty() const { @@ -626,7 +626,7 @@ struct Span { * * @return A reference to the element at the index specified in input. * - * @pre index shall be less than size(). + * @pre index is less than size(). */ reference operator[](index_type index) const { @@ -649,7 +649,7 @@ struct Span { /** * Create a new Span over the first @p Count elements of the existing view. * - * @tparam Count The number of element viewed by the new Span + * @tparam Count The number of elements viewed by the new Span. * * @return A new Span over the first @p Count elements. * @@ -665,7 +665,7 @@ struct Span { /** * Create a new Span over the last @p Count elements of the existing view. * - * @tparam Count The number of element viewed by the new Span + * @tparam Count The number of elements viewed by the new Span. * * @return A new Span over the last @p Count elements. * @@ -685,7 +685,7 @@ struct Span { * @tparam Offset The offset of the first element viewed by the subspan. * * @tparam Count The number of elements present in the subspan. If Count - * is equal to SPAN_DYNAMIC_EXTENT then a span starting at offset and + * is equal to SPAN_DYNAMIC_EXTENT, then a Span starting at offset and * containing the rest of the elements is returned. * * @return A subspan of this starting at Offset and Count long. @@ -708,7 +708,7 @@ struct Span { /** * Create a new Span over the first @p count elements of the existing view. * - * @param count The number of element viewed by the new Span + * @param count The number of elements viewed by the new Span. * * @return A new Span over the first @p count elements. */ @@ -721,7 +721,7 @@ struct Span { /** * Create a new Span over the last @p count elements of the existing view. * - * @param count The number of element viewed by the new Span + * @param count The number of elements viewed by the new Span. * * @return A new Span over the last @p count elements. */ @@ -735,13 +735,13 @@ struct Span { } /** - * Create a subspan that is a view other count elements; the view starts at + * Create a subspan that is a view of other count elements; the view starts at * element offset. * * @param offset The offset of the first element viewed by the subspan. * * @param count The number of elements present in the subspan. If Count - * is equal to SPAN_DYNAMIC_EXTENT then a span starting at offset and + * is equal to SPAN_DYNAMIC_EXTENT, then a Span starting at offset and * containing the rest of the elements is returned. * * @return A subspan of this starting at offset and count long. @@ -769,8 +769,8 @@ private: /** * Equality operator between two Span objects. * - * @param lhs Left hand side of the binary operation. - * @param rhs Right hand side of the binary operation. + * @param lhs Left side of the binary operation. + * @param rhs Right side of the binary operation. * * @return True if Spans in input have the same size and the same content and * false otherwise. @@ -790,10 +790,10 @@ bool operator==(const Span &lhs, const Span &rhs) } /** - * Equality operation between a span and a reference to a C++ array. + * Equality operation between a Span and a reference to a C++ array. * - * @param lhs Left hand side of the binary operation. - * @param rhs Right hand side of the binary operation. + * @param lhs Left side of the binary operation. + * @param rhs Right side of the binary operation. * * @return True if elements in input have the same size and the same content and * false otherwise. @@ -807,8 +807,8 @@ bool operator==(const Span &lhs, T (&rhs)[RhsExtent]) /** * Equality operation between a Span and a reference to a C++ array. * - * @param lhs Left hand side of the binary operation. - * @param rhs Right hand side of the binary operation. + * @param lhs Left side of the binary operation. + * @param rhs Right side of the binary operation. * * @return True if elements in input have the same size and the same content * and false otherwise. @@ -822,8 +822,8 @@ bool operator==(T (&lhs)[LhsExtent], const Span &rhs) /** * Not equal operator * - * @param lhs Left hand side of the binary operation. - * @param rhs Right hand side of the binary operation. + * @param lhs Left side of the binary operation. + * @param rhs Right side of the binary operation. * * @return True if arrays in input do not have the same size or the same content * and false otherwise. @@ -837,8 +837,8 @@ bool operator!=(const Span &lhs, const Span &rhs) /** * Not Equal operation between a Span and a reference to a C++ array. * - * @param lhs Left hand side of the binary operation. - * @param rhs Right hand side of the binary operation. + * @param lhs Left side of the binary operation. + * @param rhs Right side of the binary operation. * * @return True if elements in input have the same size and the same content * and false otherwise. @@ -852,8 +852,8 @@ bool operator!=(const Span &lhs, T (&rhs)[RhsExtent]) /** * Not Equal operation between a Span and a reference to a C++ array. * - * @param lhs Left hand side of the binary operation. - * @param rhs Right hand side of the binary operation. + * @param lhs Left side of the binary operation. + * @param rhs Right side of the binary operation. * * @return True if elements in input have the same size and the same content * and false otherwise. From 9d1fd9983cea0c1e8a6ed5c6daccb98bf190e881 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 24 Aug 2018 17:51:58 +0100 Subject: [PATCH 23/23] Span: Fix documentation. --- platform/Span.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/Span.h b/platform/Span.h index c1b0ce171f..15eb6e4bc5 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -64,14 +64,14 @@ public: * @par Operations * * Span objects can be copied and assigned like regular value types with the help - * of copy constructor and copy assignment (=) operators. + * of the copy constructor or the copy assignment (=) operator. * * You can retrieve elements of the object with the subscript ([]) operator. You can access the * pointer to the first element of the sequence viewed with data(). * The function size() returns the number of elements in the sequence, and * empty() informs whether there is any element in the sequence. * - * You can splice Span from the beginning of the sequence (first()), from the end + * You can slice Span from the beginning of the sequence (first()), from the end * of the sequence (last()) or from an arbitrary point of the sequence (subspan()). * * @par Size encoding @@ -298,7 +298,7 @@ struct Span { * * @note For Span with a positive extent, this function is not accessible. * - * @note OtherElementType(*)[] is convertible to ElementType(*)[]. + * @note OtherElementType(*)[] must be convertible to ElementType(*)[]. */ template Span(const Span &other): @@ -587,7 +587,7 @@ struct Span { * * @note For Span with a positive extent, this function is not accessible. * - * @note OtherElementType(*)[] is convertible to ElementType(*)[]. + * @note OtherElementType(*)[] must be convertible to ElementType(*)[]. */ template Span(const Span &other):