Kenji Arai / TYBLE16_mbedlized_os5_several_examples_1st

Dependencies:   nRF51_Vdd TextLCD BME280

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