Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: mbed/platform/Span.h
- Revision:
- 11:32eeb052cda5
- Parent:
- 0:d383e2dee0f7
diff -r 0b7f23df690a -r 32eeb052cda5 mbed/platform/Span.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed/platform/Span.h Wed Aug 26 14:26:27 2020 +0530
@@ -0,0 +1,1025 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2018-2018 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 {
+
+/** \addtogroup platform */
+/** @{*/
+/**
+ * \defgroup platform_Span Span class
+ * @{
+ */
+
+// 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()));
+};
+
+}
+
+#if defined(DOXYGEN_ONLY)
+/**
+ * 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.
+ *
+ * @relates Span
+ */
+const ptrdiff_t SPAN_DYNAMIC_EXTENT = -1;
+#else
+#define SPAN_DYNAMIC_EXTENT -1
+#endif
+
+/**
+ * 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);
+ }
+
+ // AStyle ignore, not handling correctly below
+ // *INDENT-OFF*
+ /**
+ * 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 (*)[]"
+ );
+ }
+ // *INDENT-ON*
+
+ /**
+ * 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);
+ }
+
+ // AStyle ignore, not handling correctly below
+ // *INDENT-OFF*
+ /**
+ * 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
+ );
+ }
+ // *INDENT-ON*
+
+ /**
+ * 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);
+ }
+
+ // AStyle ignore, not handling correctly below
+ // *INDENT-OFF*
+ /**
+ * 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 (*)[]"
+ );
+ }
+ // *INDENT-ON*
+
+ /**
+ * 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>
+ subspan() const
+ {
+ MBED_ASSERT(0 <= Offset && Offset <= _size);
+ MBED_ASSERT(
+ (Count == SPAN_DYNAMIC_EXTENT) ||
+ (0 <= Count && (Count + Offset) <= _size)
+ );
+ return Span<element_type, 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.
+ *
+ * @relates Span
+ */
+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());
+}
+
+// AStyle ignore, not handling correctly below
+// *INDENT-OFF*
+/**
+ * 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.
+ *
+ * @relates Span
+ */
+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'.
+ *
+ * @relates Span
+ */
+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'.
+ *
+ * @relates Span
+ */
+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);
+}
+// *INDENT-ON*
+/**
+ * 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'.
+ *
+ * @relates Span
+ */
+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'.
+ *
+ * @relates Span
+ */
+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_ */