Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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_ */
Generated on Tue Jul 12 2022 20:52:57 by
1.7.2