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