mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			
		
			
				
	
	
		
			1026 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			1026 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C++
		
	
	
/* 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_ */
 |