takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

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