mbed library sources. Supersedes mbed-src.

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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Span.h Source File

Span.h

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2018-2018 ARM Limited
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #ifndef MBED_PLATFORM_SPAN_H_
00019 #define MBED_PLATFORM_SPAN_H_
00020 
00021 #include <algorithm>
00022 #include <stddef.h>
00023 #include <stdint.h>
00024 
00025 #include "platform/mbed_assert.h"
00026 
00027 namespace mbed {
00028 
00029 /** \addtogroup platform */
00030 /** @{*/
00031 /**
00032  * \defgroup platform_Span Span class
00033  * @{
00034  */
00035 
00036 // Internal details of Span
00037 // It is used construct Span from Span of convertible types (non const -> const)
00038 namespace span_detail {
00039 
00040 // If From type is convertible to To type, then the compilation constant value is
00041 // true; otherwise, it is false.
00042 template<typename From, typename To>
00043 class is_convertible {
00044     struct true_type {
00045         char x[512];
00046     };
00047     struct false_type { };
00048 
00049     static const From &generator();
00050     static true_type sink(const To &);
00051     static false_type sink(...);
00052 
00053 public:
00054     static const bool value = sizeof(true_type) == sizeof(sink(generator()));
00055 };
00056 
00057 }
00058 
00059 #if defined(DOXYGEN_ONLY)
00060 /**
00061  * Special value for the Extent parameter of Span.
00062  * If the type uses this value, then the size of the array is stored in the object
00063  * at runtime.
00064  *
00065  * @relates Span
00066  */
00067 const ptrdiff_t SPAN_DYNAMIC_EXTENT = -1;
00068 #else
00069 #define SPAN_DYNAMIC_EXTENT -1
00070 #endif
00071 
00072 /**
00073  * Nonowning view to a sequence of contiguous elements.
00074  *
00075  * Spans encapsulate a pointer to a sequence of contiguous elements and its size
00076  * into a single object. Span can replace the traditional pair of pointer and
00077  * size arguments passed as array definitions in function calls.
00078  *
00079  * @par Operations
00080  *
00081  * Span objects can be copied and assigned like regular value types with the help
00082  * of the copy constructor or the copy assignment (=) operator.
00083  *
00084  * You can retrieve elements of the object with the subscript ([]) operator. You can access the
00085  * pointer to the first element of the sequence viewed with data().
00086  * The function size() returns the number of elements in the sequence, and
00087  * empty() informs whether there is any element in the sequence.
00088  *
00089  * You can slice Span from the beginning of the sequence (first()), from the end
00090  * of the sequence (last()) or from an arbitrary point of the sequence (subspan()).
00091  *
00092  * @par Size encoding
00093  *
00094  * The size of the sequence can be encoded in the type itself or in the value of
00095  * the instance with the help of the template parameter Extent:
00096  *
00097  *   - Span<uint8_t, 6>: Span over a sequence of 6 elements.
00098  *   - Span<uint8_t>: Span over an arbitrary long sequence.
00099  *
00100  * When the size is encoded in the type itself, it is guaranteed that the Span
00101  * view is a valid sequence (not empty() and not NULL) - unless Extent equals 0.
00102  * The type system also prevents automatic conversion from Span of different
00103  * sizes. Finally, the Span object is internally represented as a single pointer.
00104  *
00105  * When the size of the sequence viewed is encoded in the Span value, Span
00106  * instances can view an empty sequence. The function empty() helps client code
00107  * decide whether Span is viewing valid content or not.
00108  *
00109  * @par Example
00110  *
00111  * - Encoding fixed size array: Array values in parameter decays automatically
00112  * to pointer, which leaves room for subtitle bugs:
00113  *
00114  * @code
00115     typedef uint8_t mac_address_t[6];
00116     void process_mac(mac_address_t);
00117 
00118     // compile just fine
00119     uint8_t *invalid_value = NULL;
00120     process_mac(invalid_value);
00121 
00122 
00123     // correct way
00124     typedef Span<uint8_t, 6> mac_address_t;
00125     void process_mac(mac_address_t);
00126 
00127     // compilation error
00128     uint8_t *invalid_value = NULL;
00129     process_mac(invalid_value);
00130 
00131     // compilation ok
00132     uint8_t valid_value[6];
00133     process_mac(valid_value);
00134  * @endcode
00135  *
00136  * - Arbitrary buffer: When dealing with multiple buffers, it becomes painful to
00137  * keep track of every buffer size and pointer.
00138  *
00139  * @code
00140     const uint8_t options_tag[OPTIONS_TAG_SIZE];
00141 
00142     struct parsed_value_t {
00143        uint8_t *header;
00144        uint8_t *options;
00145        uint8_t *payload;
00146        size_t payload_size;
00147     }
00148 
00149     parsed_value_t parse(uint8_t *buffer, size_t buffer_size)
00150     {
00151        parsed_value_t parsed_value { 0 };
00152 
00153        if (buffer != NULL && buffer_size <= MINIMAL_BUFFER_SIZE) {
00154            return parsed_value;
00155        }
00156 
00157        parsed_value.header = buffer;
00158        parsed_value.header_size = BUFFER_HEADER_SIZE;
00159 
00160        if (memcmp(buffer + HEADER_OPTIONS_INDEX, options_tag, sizeof(options_tag)) == 0) {
00161            options = buffer + BUFFER_HEADER_SIZE;
00162            payload = buffer + BUFFER_HEADER_SIZE + OPTIONS_SIZE;
00163            payload_size = buffer_size - BUFFER_HEADER_SIZE + OPTIONS_SIZE;
00164        } else {
00165            payload = buffer + BUFFER_HEADER_SIZE;
00166            payload_size = buffer_size - BUFFER_HEADER_SIZE;
00167        }
00168 
00169        return parsed_value;
00170     }
00171 
00172 
00173     //with Span
00174     struct parsed_value_t {
00175        Span<uint8_t> header;
00176        Span<uint8_t> options;
00177        Span<uint8_t> payload;
00178     }
00179 
00180     parsed_value_t parse(const Span<uint8_t> &buffer)
00181     {
00182        parsed_value_t parsed_value;
00183 
00184        if (buffer.size() <= MINIMAL_BUFFER_SIZE) {
00185            return parsed_value;
00186        }
00187 
00188        parsed_value.header = buffer.first(BUFFER_HEADER_SIZE);
00189 
00190        if (buffer.subspan<HEADER_OPTIONS_INDEX, sizeof(options_tag)>() == option_tag) {
00191            options = buffer.supspan(parsed_value.header.size(), OPTIONS_SIZE);
00192        }
00193 
00194        payload = buffer.subspan(parsed_value.header.size() + parsed_value.options.size());
00195 
00196        return parsed_value;
00197     }
00198  * @endcode
00199  *
00200  * @note You can create Span instances with the help of the function template
00201  * make_Span() and make_const_Span().
00202  *
00203  * @note Span<T, Extent> objects can be implicitly converted to Span<T> objects
00204  * where required.
00205  *
00206  * @tparam ElementType type of objects the Span views.
00207  *
00208  * @tparam Extent The size of the contiguous sequence viewed. The default value
00209  * SPAN_DYNAMIC_SIZE  is special because it allows construction of Span objects of
00210  * any size (set at runtime).
00211  */
00212 template<typename ElementType, ptrdiff_t Extent = SPAN_DYNAMIC_EXTENT>
00213 struct Span {
00214 
00215     /**
00216      * Type of the element contained
00217      */
00218     typedef ElementType element_type;
00219 
00220     /**
00221      * Type of the index.
00222      */
00223     typedef ptrdiff_t index_type;
00224 
00225     /**
00226      * Pointer to an ElementType
00227      */
00228     typedef element_type *pointer;
00229 
00230     /**
00231      * Reference to an ElementType
00232      */
00233     typedef element_type &reference;
00234 
00235     /**
00236      * Size of the Extent; -1 if dynamic.
00237      */
00238     static const index_type extent = Extent;
00239 
00240     MBED_STATIC_ASSERT(Extent >= 0, "Invalid extent for a Span");
00241 
00242     /**
00243      * Construct an empty Span.
00244      *
00245      * @post a call to size() returns 0, and data() returns NULL.
00246      *
00247      * @note This function is not accessible if Extent != SPAN_DYNAMIC_EXTENT or
00248      * Extent != 0 .
00249      */
00250     Span() :
00251         _data(NULL)
00252     {
00253         MBED_STATIC_ASSERT(
00254             Extent == 0,
00255             "Cannot default construct a static-extent Span (unless Extent is 0)"
00256         );
00257     }
00258 
00259     /**
00260      * Construct a Span from a pointer to a buffer and its size.
00261      *
00262      * @param ptr Pointer to the beginning of the data viewed.
00263      *
00264      * @param count Number of elements viewed.
00265      *
00266      * @pre [ptr, ptr + count) must be be a valid range.
00267      * @pre count must be equal to Extent.
00268      *
00269      * @post a call to size() returns Extent, and data() returns @p ptr.
00270      */
00271     Span(pointer ptr, index_type count) :
00272         _data(ptr)
00273     {
00274         MBED_ASSERT(count == Extent);
00275         MBED_ASSERT(Extent == 0 || ptr != NULL);
00276     }
00277 
00278     /**
00279      * Construct a Span from the range [first, last).
00280      *
00281      * @param first Pointer to the beginning of the data viewed.
00282      * @param last End of the range (element after the last element).
00283      *
00284      * @pre [first, last) must be be a valid range.
00285      * @pre first <= last.
00286      * @pre last - first must be equal to Extent.
00287      *
00288      * @post a call to size() returns Extent, and data() returns @p first.
00289      */
00290     Span(pointer first, pointer last) :
00291         _data(first)
00292     {
00293         MBED_ASSERT(first <= last);
00294         MBED_ASSERT((last - first) == Extent);
00295         MBED_ASSERT(Extent == 0 || first != NULL);
00296     }
00297 
00298     // AStyle ignore, not handling correctly below
00299     // *INDENT-OFF*
00300     /**
00301      * Construct a Span from the reference to an array.
00302      *
00303      * @param elements Reference to the array viewed.
00304      *
00305      * @post a call to size() returns Extent, and data() returns a
00306      * pointer to elements.
00307      */
00308     Span(element_type (&elements)[Extent]):
00309         _data(elements) { }
00310 
00311     /**
00312      * Construct a Span object from another Span of the same size.
00313      *
00314      * @param other The Span object used to construct this.
00315      *
00316      * @note For Span with a positive extent, this function is not accessible.
00317      *
00318      * @note OtherElementType(*)[] must be convertible to ElementType(*)[].
00319      */
00320     template<typename OtherElementType>
00321     Span(const Span<OtherElementType, Extent> &other):
00322         _data(other.data())
00323     {
00324         MBED_STATIC_ASSERT(
00325             (span_detail::is_convertible<OtherElementType (*)[1], ElementType (*)[1]>::value),
00326             "OtherElementType(*)[] should be convertible to ElementType (*)[]"
00327         );
00328     }
00329     // *INDENT-ON*
00330 
00331     /**
00332      * Return the size of the sequence viewed.
00333      *
00334      * @return The size of the sequence viewed.
00335      */
00336     index_type size() const
00337     {
00338         return Extent;
00339     }
00340 
00341     /**
00342      * Return if the sequence is empty or not.
00343      *
00344      * @return true if the sequence is empty and false otherwise.
00345      */
00346     bool empty() const
00347     {
00348         return size() == 0;
00349     }
00350 
00351     /**
00352      * Returns a reference to the element at position @p index.
00353      *
00354      * @param index Index of the element to access.
00355      *
00356      * @return A reference to the element at the index specified in input.
00357      *
00358      * @pre 0 <= index < Extent.
00359      */
00360     reference operator[](index_type index) const
00361     {
00362 #ifdef MBED_DEBUG
00363         MBED_ASSERT(0 <= index && index < Extent);
00364 #endif
00365         return _data[index];
00366     }
00367 
00368     /**
00369      * Return a pointer to the first element of the sequence or NULL if the Span
00370      * is empty().
00371      *
00372      * @return The pointer to the first element of the Span.
00373      */
00374     pointer data() const
00375     {
00376         return _data;
00377     }
00378 
00379     /**
00380      * Create a new Span over the first @p Count elements of the existing view.
00381      *
00382      * @tparam Count The number of element viewed by the new Span
00383      *
00384      * @return A new Span over the first @p Count elements.
00385      *
00386      * @pre Count >= 0 && Count <= size().
00387      */
00388     template<ptrdiff_t Count>
00389     Span<element_type, Count> first() const
00390     {
00391         MBED_STATIC_ASSERT(
00392             (0 <= Count) && (Count <= Extent),
00393             "Invalid subspan extent"
00394         );
00395         return Span<element_type, Count>(_data, Count);
00396     }
00397 
00398     /**
00399      * Create a new Span over the last @p Count elements of the existing view.
00400      *
00401      * @tparam Count The number of element viewed by the new Span.
00402      *
00403      * @return A new Span over the last @p Count elements.
00404      *
00405      * @pre Count >= 0 && Count <= size().
00406      */
00407     template<ptrdiff_t Count>
00408     Span<element_type, Count> last() const
00409     {
00410         MBED_STATIC_ASSERT(
00411             (0 <= Count) && (Count <= Extent),
00412             "Invalid subspan extent"
00413         );
00414         return Span<element_type, Count>(_data + (Extent - Count), Count);
00415     }
00416 
00417     // AStyle ignore, not handling correctly below
00418     // *INDENT-OFF*
00419     /**
00420      * Create a subspan that is a view of other Count elements; the view starts at
00421      * element Offset.
00422      *
00423      * @tparam Offset The offset of the first element viewed by the subspan.
00424      *
00425      * @tparam Count The number of elements present in the subspan. If Count
00426      * is equal to SPAN_DYNAMIC_EXTENT, then a Span starting at offset and
00427      * containing the rest of the elements is returned.
00428      *
00429      * @return A subspan of this starting at Offset and Count long.
00430      */
00431     template<std::ptrdiff_t Offset, std::ptrdiff_t Count>
00432     Span<element_type, Count == SPAN_DYNAMIC_EXTENT ? Extent - Offset : Count>
00433     subspan() const
00434     {
00435         MBED_STATIC_ASSERT(
00436             0 <= Offset && Offset <= Extent,
00437             "Invalid subspan offset"
00438         );
00439         MBED_STATIC_ASSERT(
00440             (Count == SPAN_DYNAMIC_EXTENT) ||
00441             (0 <= Count && (Count + Offset) <= Extent),
00442             "Invalid subspan count"
00443         );
00444         return Span<element_type, Count == SPAN_DYNAMIC_EXTENT ? Extent - Offset : Count>(
00445             _data + Offset,
00446             Count == SPAN_DYNAMIC_EXTENT ? Extent - Offset : Count
00447         );
00448     }
00449     // *INDENT-ON*
00450 
00451     /**
00452      * Create a new Span over the first @p count elements of the existing view.
00453      *
00454      * @param count The number of element viewed by the new Span.
00455      *
00456      * @return A new Span over the first @p count elements.
00457      */
00458     Span<element_type, SPAN_DYNAMIC_EXTENT> first(index_type count) const
00459     {
00460         MBED_ASSERT(0 <= count && count <= Extent);
00461         return Span<element_type, SPAN_DYNAMIC_EXTENT>(_data, count);
00462     }
00463 
00464     /**
00465      * Create a new Span over the last @p count elements of the existing view.
00466      *
00467      * @param count The number of elements viewed by the new Span.
00468      *
00469      * @return A new Span over the last @p count elements.
00470      */
00471     Span<element_type, SPAN_DYNAMIC_EXTENT> last(index_type count) const
00472     {
00473         MBED_ASSERT(0 <= count && count <= Extent);
00474         return Span<element_type, SPAN_DYNAMIC_EXTENT>(
00475                    _data + (Extent - count),
00476                    count
00477                );
00478     }
00479 
00480     /**
00481      * Create a subspan that is a view of other count elements; the view starts at
00482      * element offset.
00483      *
00484      * @param offset The offset of the first element viewed by the subspan.
00485      *
00486      * @param count The number of elements present in the subspan. If Count
00487      * is equal to SPAN_DYNAMIC_EXTENT, then a span starting at offset and
00488      * containing the rest of the elements is returned.
00489      *
00490      * @return
00491      */
00492     Span<element_type, SPAN_DYNAMIC_EXTENT> subspan(
00493         index_type offset, index_type count = SPAN_DYNAMIC_EXTENT
00494     ) const
00495     {
00496         MBED_ASSERT(0 <= offset && offset <= Extent);
00497         MBED_ASSERT(
00498             (count == SPAN_DYNAMIC_EXTENT) ||
00499             (0 <= count && (count + offset) <= Extent)
00500         );
00501         return Span<element_type, SPAN_DYNAMIC_EXTENT>(
00502                    _data + offset,
00503                    count == SPAN_DYNAMIC_EXTENT ? Extent - offset : count
00504                );
00505     }
00506 
00507 private:
00508     pointer _data;
00509 };
00510 
00511 /**
00512  * Span specialization that handle dynamic size.
00513  */
00514 template<typename ElementType>
00515 struct Span<ElementType, SPAN_DYNAMIC_EXTENT> {
00516     /**
00517      * Type of the element contained.
00518      */
00519     typedef ElementType element_type;
00520 
00521     /**
00522      * Type of the index.
00523      */
00524     typedef ptrdiff_t index_type;
00525 
00526     /**
00527      * Pointer to an ElementType.
00528      */
00529     typedef element_type *pointer;
00530 
00531     /**
00532      * Reference to an ElementType.
00533      */
00534     typedef element_type &reference;
00535 
00536     /**
00537      * Size of the Extent; -1 if dynamic.
00538      */
00539     static const index_type extent = SPAN_DYNAMIC_EXTENT;
00540 
00541     /**
00542      * Construct an empty Span.
00543      *
00544      * @post a call to size() returns 0, and data() returns NULL.
00545      *
00546      * @note This function is not accessible if Extent != SPAN_DYNAMIC_EXTENT or
00547      * Extent != 0 .
00548      */
00549     Span() :
00550         _data(NULL), _size(0) { }
00551 
00552     /**
00553      * Construct a Span from a pointer to a buffer and its size.
00554      *
00555      * @param ptr Pointer to the beginning of the data viewed.
00556      *
00557      * @param count Number of elements viewed.
00558      *
00559      * @pre [ptr, ptr + count) must be be a valid range.
00560      * @pre count must be equal to extent.
00561      *
00562      * @post a call to size() returns count, and data() returns @p ptr.
00563      */
00564     Span(pointer ptr, index_type count) :
00565         _data(ptr), _size(count)
00566     {
00567         MBED_ASSERT(count >= 0);
00568         MBED_ASSERT(ptr != NULL || count == 0);
00569     }
00570 
00571     /**
00572      * Construct a Span from the range [first, last).
00573      *
00574      * @param first Pointer to the beginning of the data viewed.
00575      * @param last End of the range (element after the last element).
00576      *
00577      * @pre [first, last) must be be a valid range.
00578      * @pre first <= last.
00579      *
00580      * @post a call to size() returns the result of (last - first), and
00581      * data() returns @p first.
00582      */
00583     Span(pointer first, pointer last) :
00584         _data(first), _size(last - first)
00585     {
00586         MBED_ASSERT(first <= last);
00587         MBED_ASSERT(first != NULL  || (last - first) == 0);
00588     }
00589 
00590     // AStyle ignore, not handling correctly below
00591     // *INDENT-OFF*
00592     /**
00593      * Construct a Span from the reference to an array.
00594      *
00595      * @param elements Reference to the array viewed.
00596      *
00597      * @tparam Count Number of elements of T presents in the array.
00598      *
00599      * @post a call to size() returns Count, and data() returns a
00600      * pointer to elements.
00601      */
00602     template<size_t Count>
00603     Span(element_type (&elements)[Count]):
00604         _data(elements), _size(Count) { }
00605 
00606     /**
00607      * Construct a Span object from another Span.
00608      *
00609      * @param other The Span object used to construct this.
00610      *
00611      * @note For Span with a positive extent, this function is not accessible.
00612      *
00613      * @note OtherElementType(*)[] must be convertible to ElementType(*)[].
00614      */
00615     template<typename OtherElementType, ptrdiff_t OtherExtent>
00616     Span(const Span<OtherElementType, OtherExtent> &other):
00617         _data(other.data()), _size(other.size())
00618     {
00619         MBED_STATIC_ASSERT(
00620             (span_detail::is_convertible<OtherElementType (*)[1], ElementType (*)[1]>::value),
00621             "OtherElementType(*)[] should be convertible to ElementType (*)[]"
00622         );
00623     }
00624     // *INDENT-ON*
00625 
00626     /**
00627      * Return the size of the array viewed.
00628      *
00629      * @return The number of elements present in the array viewed.
00630      */
00631     index_type size() const
00632     {
00633         return _size;
00634     }
00635 
00636     /**
00637      * Return if the sequence viewed is empty or not.
00638      *
00639      * @return true if the sequence is empty and false otherwise.
00640      */
00641     bool empty() const
00642     {
00643         return size() == 0;
00644     }
00645 
00646     /**
00647      * Access to an element of the sequence.
00648      *
00649      * @param index Element index to access.
00650      *
00651      * @return A reference to the element at the index specified in input.
00652      *
00653      * @pre index is less than size().
00654      */
00655     reference operator[](index_type index) const
00656     {
00657 #ifdef MBED_DEBUG
00658         MBED_ASSERT(0 <= index && index < _size);
00659 #endif
00660         return _data[index];
00661     }
00662 
00663     /**
00664      * Get the raw pointer to the sequence viewed.
00665      *
00666      * @return The raw pointer to the first element viewed.
00667      */
00668     pointer data() const
00669     {
00670         return _data;
00671     }
00672 
00673     /**
00674      * Create a new Span over the first @p Count elements of the existing view.
00675      *
00676      * @tparam Count The number of elements viewed by the new Span.
00677      *
00678      * @return A new Span over the first @p Count elements.
00679      *
00680      * @pre Count >= 0 && Count <= size().
00681      */
00682     template<ptrdiff_t Count>
00683     Span<element_type, Count> first() const
00684     {
00685         MBED_ASSERT((Count >= 0) && (Count <= _size));
00686         return Span<element_type, Count>(_data, Count);
00687     }
00688 
00689     /**
00690      * Create a new Span over the last @p Count elements of the existing view.
00691      *
00692      * @tparam Count The number of elements viewed by the new Span.
00693      *
00694      * @return A new Span over the last @p Count elements.
00695      *
00696      * @pre Count >= 0 && Count <= size().
00697      */
00698     template<ptrdiff_t Count>
00699     Span<element_type, Count> last() const
00700     {
00701         MBED_ASSERT((0 <= Count) && (Count <= _size));
00702         return Span<element_type, Count>(_data + (_size - Count), Count);
00703     }
00704 
00705     /**
00706      * Create a subspan that is a view other Count elements; the view starts at
00707      * element Offset.
00708      *
00709      * @tparam Offset The offset of the first element viewed by the subspan.
00710      *
00711      * @tparam Count The number of elements present in the subspan. If Count
00712      * is equal to SPAN_DYNAMIC_EXTENT, then a Span starting at offset and
00713      * containing the rest of the elements is returned.
00714      *
00715      * @return A subspan of this starting at Offset and Count long.
00716      */
00717     template<std::ptrdiff_t Offset, std::ptrdiff_t Count>
00718     Span<element_type, Count>
00719     subspan() const
00720     {
00721         MBED_ASSERT(0 <= Offset && Offset <= _size);
00722         MBED_ASSERT(
00723             (Count == SPAN_DYNAMIC_EXTENT) ||
00724             (0 <= Count && (Count + Offset) <= _size)
00725         );
00726         return Span<element_type, Count>(
00727                    _data + Offset,
00728                    Count == SPAN_DYNAMIC_EXTENT ? _size - Offset : Count
00729                );
00730     }
00731 
00732     /**
00733      * Create a new Span over the first @p count elements of the existing view.
00734      *
00735      * @param count The number of elements viewed by the new Span.
00736      *
00737      * @return A new Span over the first @p count elements.
00738      */
00739     Span<element_type, SPAN_DYNAMIC_EXTENT> first(index_type count) const
00740     {
00741         MBED_ASSERT(0 <= count && count <= _size);
00742         return Span<element_type, SPAN_DYNAMIC_EXTENT>(_data, count);
00743     }
00744 
00745     /**
00746      * Create a new Span over the last @p count elements of the existing view.
00747      *
00748      * @param count The number of elements viewed by the new Span.
00749      *
00750      * @return A new Span over the last @p count elements.
00751      */
00752     Span<element_type, SPAN_DYNAMIC_EXTENT> last(index_type count) const
00753     {
00754         MBED_ASSERT(0 <= count && count <= _size);
00755         return Span<element_type, SPAN_DYNAMIC_EXTENT>(
00756                    _data + (_size - count),
00757                    count
00758                );
00759     }
00760 
00761     /**
00762      * Create a subspan that is a view of other count elements; the view starts at
00763      * element offset.
00764      *
00765      * @param offset The offset of the first element viewed by the subspan.
00766      *
00767      * @param count The number of elements present in the subspan. If Count
00768      * is equal to SPAN_DYNAMIC_EXTENT, then a Span starting at offset and
00769      * containing the rest of the elements is returned.
00770      *
00771      * @return A subspan of this starting at offset and count long.
00772      */
00773     Span<element_type, SPAN_DYNAMIC_EXTENT> subspan(
00774         index_type offset, index_type count = SPAN_DYNAMIC_EXTENT
00775     ) const
00776     {
00777         MBED_ASSERT(0 <= offset && offset <= _size);
00778         MBED_ASSERT(
00779             (count == SPAN_DYNAMIC_EXTENT) ||
00780             (0 <= count && (count + offset) <= _size)
00781         );
00782         return Span<element_type, SPAN_DYNAMIC_EXTENT>(
00783                    _data + offset,
00784                    count == SPAN_DYNAMIC_EXTENT ? _size - offset : count
00785                );
00786     }
00787 
00788 private:
00789     pointer _data;
00790     index_type _size;
00791 };
00792 
00793 /**
00794  * Equality operator between two Span objects.
00795  *
00796  * @param lhs Left side of the binary operation.
00797  * @param rhs Right side of the binary operation.
00798  *
00799  * @return True if Spans in input have the same size and the same content and
00800  * false otherwise.
00801  *
00802  * @relates Span
00803  */
00804 template<typename T, typename U, ptrdiff_t LhsExtent, ptrdiff_t RhsExtent>
00805 bool operator==(const Span<T, LhsExtent> &lhs, const Span<U, RhsExtent> &rhs)
00806 {
00807     if (lhs.size() != rhs.size()) {
00808         return false;
00809     }
00810 
00811     if (lhs.data() == rhs.data()) {
00812         return true;
00813     }
00814 
00815     return std::equal(lhs.data(), lhs.data() + lhs.size(), rhs.data());
00816 }
00817 
00818 // AStyle ignore, not handling correctly below
00819 // *INDENT-OFF*
00820 /**
00821  * Equality operation between a Span and a reference to a C++ array.
00822  *
00823  * @param lhs Left side of the binary operation.
00824  * @param rhs Right side of the binary operation.
00825  *
00826  * @return True if elements in input have the same size and the same content and
00827  * false otherwise.
00828  */
00829 template<typename T, ptrdiff_t LhsExtent, ptrdiff_t RhsExtent>
00830 bool operator==(const Span<T, LhsExtent> &lhs, T (&rhs)[RhsExtent])
00831 {
00832     return lhs == Span<T>(rhs);
00833 }
00834 
00835 /**
00836  * Equality operation between a Span and a reference to a C++ array.
00837  *
00838  * @param lhs Left side of the binary operation.
00839  * @param rhs Right side of the binary operation.
00840  *
00841  * @return True if elements in input have the same size and the same content
00842  * and false otherwise.
00843  */
00844 template<typename T, ptrdiff_t LhsExtent, ptrdiff_t RhsExtent>
00845 bool operator==(T (&lhs)[LhsExtent], const Span<T, RhsExtent> &rhs)
00846 {
00847     return Span<T>(lhs) == rhs;
00848 }
00849 
00850 /**
00851  * Not equal operator
00852  *
00853  * @param lhs Left side of the binary operation.
00854  * @param rhs Right side of the binary operation.
00855  *
00856  * @return True if arrays in input do not have the same size or the same content
00857  * and false otherwise.
00858  *
00859  * @relates Span
00860  */
00861 template<typename T, typename U, ptrdiff_t LhsExtent, ptrdiff_t RhsExtent>
00862 bool operator!=(const Span<T, LhsExtent> &lhs, const Span<U, RhsExtent> &rhs)
00863 {
00864     return !(lhs == rhs);
00865 }
00866 
00867 /**
00868  * Not Equal operation between a Span and a reference to a C++ array.
00869  *
00870  * @param lhs Left side of the binary operation.
00871  * @param rhs Right side of the binary operation.
00872  *
00873  * @return True if elements in input have the same size and the same content
00874  * and false otherwise.
00875  */
00876 template<typename T, ptrdiff_t LhsExtent, ptrdiff_t RhsExtent>
00877 bool operator!=(const Span<T, LhsExtent> &lhs, T (&rhs)[RhsExtent])
00878 {
00879     return !(lhs == Span<T, RhsExtent>(rhs));
00880 }
00881 
00882 /**
00883  * Not Equal operation between a Span and a reference to a C++ array.
00884  *
00885  * @param lhs Left side of the binary operation.
00886  * @param rhs Right side of the binary operation.
00887  *
00888  * @return True if elements in input have the same size and the same content
00889  * and false otherwise.
00890  */
00891 template<typename T, ptrdiff_t LhsExtent, ptrdiff_t RhsExtent>
00892 bool operator!=(T (&lhs)[LhsExtent], const Span<T, RhsExtent> &rhs)
00893 {
00894     return !(Span<T, LhsExtent>(lhs) == rhs);
00895 }
00896 
00897 /**
00898  * Generate a Span from a reference to a C/C++ array.
00899  *
00900  * @tparam T Type of elements held in elements.
00901  * @tparam Extent Number of items held in elements.
00902  *
00903  * @param elements The reference to the array viewed.
00904  *
00905  * @return The Span to elements.
00906  *
00907  * @note This helper avoids the typing of template parameter when Span is
00908  * created 'inline'.
00909  *
00910  * @relates Span
00911  */
00912 template<typename T, size_t Size>
00913 Span<T, Size> make_Span(T (&elements)[Size])
00914 {
00915     return Span<T, Size>(elements);
00916 }
00917 
00918 /**
00919  * Generate a Span from a pointer to a C/C++ array.
00920  *
00921  * @tparam Extent Number of items held in elements.
00922  * @tparam T Type of elements held in elements.
00923  *
00924  * @param elements The reference to the array viewed.
00925  *
00926  * @return The Span to elements.
00927  *
00928  * @note This helper avoids the typing of template parameter when Span is
00929  * created 'inline'.
00930  */
00931 template<ptrdiff_t Extent, typename T>
00932 Span<T, Extent> make_Span(T *elements)
00933 {
00934     return Span<T, Extent>(elements, Extent);
00935 }
00936 
00937 /**
00938  * Generate a Span from a C/C++ pointer and the size of the array.
00939  *
00940  * @tparam T Type of elements held in array_ptr.
00941  *
00942  * @param array_ptr The pointer to the array viewed.
00943  * @param array_size The number of T elements in the array.
00944  *
00945  * @return The Span to array_ptr with a size of array_size.
00946  *
00947  * @note This helper avoids the typing of template parameter when Span is
00948  * created 'inline'.
00949  * 
00950  * @relates Span
00951  */
00952 template<typename T>
00953 Span<T> make_Span(T *array_ptr, ptrdiff_t array_size)
00954 {
00955     return Span<T>(array_ptr, array_size);
00956 }
00957 
00958 /**
00959  * Generate a Span to a const content from a reference to a C/C++ array.
00960  *
00961  * @tparam T Type of elements held in elements.
00962  * @tparam Extent Number of items held in elements.
00963  *
00964  * @param elements The array viewed.
00965  * @return The Span to elements.
00966  *
00967  * @note This helper avoids the typing of template parameter when Span is
00968  * created 'inline'.
00969  */
00970 template<typename T, size_t Extent>
00971 Span<const T, Extent> make_const_Span(const T (&elements)[Extent])
00972 {
00973     return Span<const T, Extent>(elements);
00974 }
00975 // *INDENT-ON*
00976 /**
00977  * Generate a Span to a const content from a pointer to a C/C++ array.
00978  *
00979  * @tparam Extent Number of items held in elements.
00980  * @tparam T Type of elements held in elements.
00981  *
00982  * @param elements The reference to the array viewed.
00983  *
00984  * @return The Span to elements.
00985  *
00986  * @note This helper avoids the typing of template parameter when Span is
00987  * created 'inline'.
00988  *
00989  * @relates Span
00990  */
00991 template<size_t Extent, typename T>
00992 Span<const T, Extent> make_const_Span(const T *elements)
00993 {
00994     return Span<const T, Extent>(elements, Extent);
00995 }
00996 
00997 /**
00998  * Generate a Span to a const content from a C/C++ pointer and the size of the
00999  * array.
01000  *
01001  * @tparam T Type of elements held in array_ptr.
01002  *
01003  * @param array_ptr The pointer to the array to viewed.
01004  * @param array_size The number of T elements in the array.
01005  *
01006  * @return The Span to array_ptr with a size of array_size.
01007  *
01008  * @note This helper avoids the typing of template parameter when Span is
01009  * created 'inline'.
01010  *
01011  * @relates Span
01012  */
01013 template<typename T>
01014 Span<const T> make_const_Span(T *array_ptr, size_t array_size)
01015 {
01016     return Span<const T>(array_ptr, array_size);
01017 }
01018 
01019 /**@}*/
01020 
01021 /**@}*/
01022 
01023 } // namespace mbed
01024 
01025 #endif /* MBED_PLATFORM_SPAN_H_ */