Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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