mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Revision:
188:bcfe06ba3d64
Child:
189:f392fc9709a3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/Span.h	Thu Nov 08 11:46:34 2018 +0000
@@ -0,0 +1,1012 @@
+/* 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 {
+
+/** \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);
+    }
+
+    /**
+     * 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>
+    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());
+}
+
+/**
+ * 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);
+}
+
+/**
+ * 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_ */