takashi kadono
/
Nucleo_446
Color Oled(SSD1331) connect to STMicroelectronics Nucleo-F466
Diff: mbed-os/platform/Span.h
- Revision:
- 0:8fdf9a60065b
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-os/platform/Span.h Wed Oct 10 00:33:53 2018 +0000 @@ -0,0 +1,983 @@ +/* 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 <algorithm> +#include <stddef.h> +#include <stdint.h> + +#include "platform/mbed_assert.h" + +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<typename From, typename To> +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())); +}; + +} + +/** + * Special value for the Extent parameter of Span. + * If the type uses this value, then the size of the array is stored in the object + * at runtime. + */ +#define SPAN_DYNAMIC_EXTENT -1 + +/** + * 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 definitions in function calls. + * + * @par Operations + * + * Span objects can be copied and assigned like regular value types with the help + * 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 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 + * + * 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<uint8_t, 6>: Span over a sequence of 6 elements. + * - Span<uint8_t>: Span over an arbitrary long sequence. + * + * When the size is encoded in the type itself, it is guaranteed that the Span + * 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 + * 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: + * + * @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<uint8_t, 6> 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<uint8_t> header; + Span<uint8_t> options; + Span<uint8_t> payload; + } + + parsed_value_t parse(const Span<uint8_t> &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<HEADER_OPTIONS_INDEX, sizeof(options_tag)>() == 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(). + * + * @note Span<T, Extent> objects can be implicitly converted to Span<T> objects + * where required. + * + * @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 because it allows construction of Span objects of + * any size (set at runtime). + */ +template<typename ElementType, ptrdiff_t Extent = SPAN_DYNAMIC_EXTENT> +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 an empty Span. + * + * @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 . + */ + Span() : + _data(NULL) + { + MBED_STATIC_ASSERT( + Extent == 0, + "Cannot default construct a static-extent Span (unless Extent is 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() returns Extent, and data() returns @p ptr. + */ + 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() returns Extent, and data() returns @p first. + */ + Span(pointer first, pointer last) : + _data(first) + { + MBED_ASSERT(first <= last); + MBED_ASSERT((last - first) == Extent); + MBED_ASSERT(Extent == 0 || first != NULL); + } + + /** + * Construct a Span from the reference to an array. + * + * @param elements Reference to the array viewed. + * + * @post a call to size() returns Extent, and data() returns a + * pointer to elements. + */ + 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(*)[] must be convertible to ElementType(*)[]. + */ + template<typename OtherElementType> + Span(const Span<OtherElementType, Extent> &other): + _data(other.data()) + { + MBED_STATIC_ASSERT( + (span_detail::is_convertible<OtherElementType (*)[1], ElementType (*)[1]>::value), + "OtherElementType(*)[] should be convertible to ElementType (*)[]" + ); + } + + /** + * Return the size of the sequence viewed. + * + * @return The size of the sequence viewed. + */ + index_type size() const + { + return Extent; + } + + /** + * Return if the sequence is empty or not. + * + * @return true if the sequence is empty and false otherwise. + */ + bool empty() const + { + return size() == 0; + } + + /** + * 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. + */ + reference operator[](index_type index) const + { +#ifdef MBED_DEBUG + MBED_ASSERT(0 <= index && index < Extent); +#endif + return _data[index]; + } + + /** + * 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. + */ + 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<ptrdiff_t Count> + Span<element_type, Count> first() const + { + MBED_STATIC_ASSERT( + (0 <= Count) && (Count <= Extent), + "Invalid subspan extent" + ); + return Span<element_type, Count>(_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<ptrdiff_t Count> + Span<element_type, Count> last() const + { + MBED_STATIC_ASSERT( + (0 <= Count) && (Count <= Extent), + "Invalid subspan extent" + ); + return Span<element_type, Count>(_data + (Extent - Count), Count); + } + + /** + * 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 + * containing the rest of the elements is returned. + * + * @return A subspan of this starting at Offset and Count long. + */ + template<std::ptrdiff_t Offset, std::ptrdiff_t Count> + Span<element_type, Count == SPAN_DYNAMIC_EXTENT ? Extent - Offset : Count> + subspan() const + { + MBED_STATIC_ASSERT( + 0 <= Offset && Offset <= Extent, + "Invalid subspan offset" + ); + MBED_STATIC_ASSERT( + (Count == SPAN_DYNAMIC_EXTENT) || + (0 <= Count && (Count + Offset) <= Extent), + "Invalid subspan count" + ); + return Span<element_type, Count == SPAN_DYNAMIC_EXTENT ? Extent - Offset : Count>( + _data + Offset, + Count == SPAN_DYNAMIC_EXTENT ? Extent - 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<element_type, SPAN_DYNAMIC_EXTENT> first(index_type count) const + { + MBED_ASSERT(0 <= count && count <= Extent); + return Span<element_type, SPAN_DYNAMIC_EXTENT>(_data, count); + } + + /** + * Create a new Span over the last @p count elements of the existing view. + * + * @param count The number of elements viewed by the new Span. + * + * @return A new Span over the last @p count elements. + */ + Span<element_type, SPAN_DYNAMIC_EXTENT> last(index_type count) const + { + MBED_ASSERT(0 <= count && count <= Extent); + return Span<element_type, SPAN_DYNAMIC_EXTENT>( + _data + (Extent - count), + count + ); + } + + /** + * 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 + * containing the rest of the elements is returned. + * + * @return + */ + Span<element_type, SPAN_DYNAMIC_EXTENT> subspan( + index_type offset, index_type count = SPAN_DYNAMIC_EXTENT + ) const + { + MBED_ASSERT(0 <= offset && offset <= Extent); + MBED_ASSERT( + (count == SPAN_DYNAMIC_EXTENT) || + (0 <= count && (count + offset) <= Extent) + ); + return Span<element_type, SPAN_DYNAMIC_EXTENT>( + _data + offset, + count == SPAN_DYNAMIC_EXTENT ? Extent - offset : count + ); + } + +private: + pointer _data; +}; + +/** + * Span specialization that handle dynamic size. + */ +template<typename ElementType> +struct Span<ElementType, SPAN_DYNAMIC_EXTENT> { + /** + * 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() returns 0, and data() returns 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() returns count, and data() returns @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() returns the result of (last - first), and + * data() returns @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() returns Count, and data() returns a + * pointer to elements. + */ + template<size_t Count> + 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(*)[] must be convertible to ElementType(*)[]. + */ + template<typename OtherElementType, ptrdiff_t OtherExtent> + Span(const Span<OtherElementType, OtherExtent> &other): + _data(other.data()), _size(other.size()) + { + MBED_STATIC_ASSERT( + (span_detail::is_convertible<OtherElementType (*)[1], ElementType (*)[1]>::value), + "OtherElementType(*)[] should be convertible to ElementType (*)[]" + ); + } + + /** + * 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 sequence viewed is empty or not. + * + * @return true if the sequence is empty and false otherwise. + */ + bool empty() const + { + return size() == 0; + } + + /** + * Access to an element of the sequence. + * + * @param index Element index to access. + * + * @return A reference to the element at the index specified in input. + * + * @pre index is less than size(). + */ + reference operator[](index_type index) const + { +#ifdef MBED_DEBUG + MBED_ASSERT(0 <= index && index < _size); +#endif + return _data[index]; + } + + /** + * Get the raw pointer to the sequence viewed. + * + * @return The raw pointer to the first element viewed. + */ + pointer data() const + { + return _data; + } + + /** + * Create a new Span over the first @p Count elements of the existing view. + * + * @tparam Count The number of elements viewed by the new Span. + * + * @return A new Span over the first @p Count elements. + * + * @pre Count >= 0 && Count <= size(). + */ + template<ptrdiff_t Count> + Span<element_type, Count> first() const + { + MBED_ASSERT((Count >= 0) && (Count <= _size)); + return Span<element_type, Count>(_data, Count); + } + + /** + * Create a new Span over the last @p Count elements of the existing view. + * + * @tparam Count The number of elements viewed by the new Span. + * + * @return A new Span over the last @p Count elements. + * + * @pre Count >= 0 && Count <= size(). + */ + template<ptrdiff_t Count> + Span<element_type, Count> last() const + { + MBED_ASSERT((0 <= Count) && (Count <= _size)); + return Span<element_type, Count>(_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 A subspan of this starting at Offset and Count long. + */ + template<std::ptrdiff_t Offset, std::ptrdiff_t Count> + Span<element_type, Count == SPAN_DYNAMIC_EXTENT ? SPAN_DYNAMIC_EXTENT : Count> + subspan() const + { + MBED_ASSERT(0 <= Offset && Offset <= _size); + MBED_ASSERT( + (Count == SPAN_DYNAMIC_EXTENT) || + (0 <= Count && (Count + Offset) <= _size) + ); + return Span<element_type, Count == SPAN_DYNAMIC_EXTENT ? SPAN_DYNAMIC_EXTENT : Count>( + _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 elements viewed by the new Span. + * + * @return A new Span over the first @p count elements. + */ + Span<element_type, SPAN_DYNAMIC_EXTENT> first(index_type count) const + { + MBED_ASSERT(0 <= count && count <= _size); + return Span<element_type, SPAN_DYNAMIC_EXTENT>(_data, count); + } + + /** + * Create a new Span over the last @p count elements of the existing view. + * + * @param count The number of elements viewed by the new Span. + * + * @return A new Span over the last @p count elements. + */ + Span<element_type, SPAN_DYNAMIC_EXTENT> last(index_type count) const + { + MBED_ASSERT(0 <= count && count <= _size); + return Span<element_type, SPAN_DYNAMIC_EXTENT>( + _data + (_size - count), + count + ); + } + + /** + * 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 + * containing the rest of the elements is returned. + * + * @return A subspan of this starting at offset and count long. + */ + Span<element_type, SPAN_DYNAMIC_EXTENT> subspan( + index_type offset, index_type count = SPAN_DYNAMIC_EXTENT + ) const + { + MBED_ASSERT(0 <= offset && offset <= _size); + MBED_ASSERT( + (count == SPAN_DYNAMIC_EXTENT) || + (0 <= count && (count + offset) <= _size) + ); + return Span<element_type, SPAN_DYNAMIC_EXTENT>( + _data + offset, + count == SPAN_DYNAMIC_EXTENT ? _size - offset : count + ); + } + +private: + pointer _data; + index_type _size; +}; + +/** + * Equality operator between two Span objects. + * + * @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. + */ +template<typename T, typename U, ptrdiff_t LhsExtent, ptrdiff_t RhsExtent> +bool operator==(const Span<T, LhsExtent> &lhs, const Span<U, RhsExtent> &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 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. + */ +template<typename T, ptrdiff_t LhsExtent, ptrdiff_t RhsExtent> +bool operator==(const Span<T, LhsExtent> &lhs, T (&rhs)[RhsExtent]) +{ + return lhs == Span<T>(rhs); +} + +/** + * Equality operation between a Span and a reference to a C++ array. + * + * @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. + */ +template<typename T, ptrdiff_t LhsExtent, ptrdiff_t RhsExtent> +bool operator==(T (&lhs)[LhsExtent], const Span<T, RhsExtent> &rhs) +{ + return Span<T>(lhs) == rhs; +} + +/** + * Not equal operator + * + * @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. + */ +template<typename T, typename U, ptrdiff_t LhsExtent, ptrdiff_t RhsExtent> +bool operator!=(const Span<T, LhsExtent> &lhs, const Span<U, RhsExtent> &rhs) +{ + return !(lhs == rhs); +} + +/** + * Not Equal operation between a Span and a reference to a C++ array. + * + * @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. + */ +template<typename T, ptrdiff_t LhsExtent, ptrdiff_t RhsExtent> +bool operator!=(const Span<T, LhsExtent> &lhs, T (&rhs)[RhsExtent]) +{ + return !(lhs == Span<T, RhsExtent>(rhs)); +} + +/** + * Not Equal operation between a Span and a reference to a C++ array. + * + * @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. + */ +template<typename T, ptrdiff_t LhsExtent, ptrdiff_t RhsExtent> +bool operator!=(T (&lhs)[LhsExtent], const Span<T, RhsExtent> &rhs) +{ + return !(Span<T, LhsExtent>(lhs) == rhs); +} + +/** + * Generate a Span from a reference to a C/C++ array. + * + * @tparam T Type of elements held in elements. + * @tparam Extent 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<typename T, size_t Size> +Span<T, Size> make_Span(T (&elements)[Size]) +{ + return Span<T, Size>(elements); +} + +/** + * Generate a Span from a pointer to a C/C++ array. + * + * @tparam Extent 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<ptrdiff_t Extent, typename T> +Span<T, Extent> make_Span(T *elements) +{ + return Span<T, Extent>(elements, Extent); +} + +/** + * 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 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<typename T> +Span<T> make_Span(T *array_ptr, ptrdiff_t array_size) +{ + return Span<T>(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 Extent 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<typename T, size_t Extent> +Span<const T, Extent> make_const_Span(const T (&elements)[Extent]) +{ + return Span<const T, Extent>(elements); +} + +/** + * Generate a Span to a const content from a pointer to a C/C++ array. + * + * @tparam Extent 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<size_t Extent, typename T> +Span<const T, Extent> make_const_Span(const T *elements) +{ + return Span<const T, Extent>(elements, Extent); +} + +/** + * 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<typename T> +Span<const T> make_const_Span(T *array_ptr, size_t array_size) +{ + return Span<const T>(array_ptr, array_size); +} + +} // namespace mbed + +#endif /* MBED_PLATFORM_SPAN_H_ */