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 // 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_ */
Generated on Tue Aug 9 2022 00:37:19 by
1.7.2