test

Dependencies:   mbed Watchdog

Dependents:   STM32-MC_node

Committer:
ommpy
Date:
Mon Jul 06 17:18:59 2020 +0530
Revision:
0:d383e2dee0f7
first commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ommpy 0:d383e2dee0f7 1 /* mbed Microcontroller Library
ommpy 0:d383e2dee0f7 2 * Copyright (c) 2018-2018 ARM Limited
ommpy 0:d383e2dee0f7 3 * SPDX-License-Identifier: Apache-2.0
ommpy 0:d383e2dee0f7 4 *
ommpy 0:d383e2dee0f7 5 * Licensed under the Apache License, Version 2.0 (the "License");
ommpy 0:d383e2dee0f7 6 * you may not use this file except in compliance with the License.
ommpy 0:d383e2dee0f7 7 * You may obtain a copy of the License at
ommpy 0:d383e2dee0f7 8 *
ommpy 0:d383e2dee0f7 9 * http://www.apache.org/licenses/LICENSE-2.0
ommpy 0:d383e2dee0f7 10 *
ommpy 0:d383e2dee0f7 11 * Unless required by applicable law or agreed to in writing, software
ommpy 0:d383e2dee0f7 12 * distributed under the License is distributed on an "AS IS" BASIS,
ommpy 0:d383e2dee0f7 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ommpy 0:d383e2dee0f7 14 * See the License for the specific language governing permissions and
ommpy 0:d383e2dee0f7 15 * limitations under the License.
ommpy 0:d383e2dee0f7 16 */
ommpy 0:d383e2dee0f7 17
ommpy 0:d383e2dee0f7 18 #ifndef MBED_PLATFORM_SPAN_H_
ommpy 0:d383e2dee0f7 19 #define MBED_PLATFORM_SPAN_H_
ommpy 0:d383e2dee0f7 20
ommpy 0:d383e2dee0f7 21 #include <algorithm>
ommpy 0:d383e2dee0f7 22 #include <stddef.h>
ommpy 0:d383e2dee0f7 23 #include <stdint.h>
ommpy 0:d383e2dee0f7 24
ommpy 0:d383e2dee0f7 25 #include "platform/mbed_assert.h"
ommpy 0:d383e2dee0f7 26
ommpy 0:d383e2dee0f7 27 namespace mbed {
ommpy 0:d383e2dee0f7 28
ommpy 0:d383e2dee0f7 29 /** \addtogroup platform */
ommpy 0:d383e2dee0f7 30 /** @{*/
ommpy 0:d383e2dee0f7 31 /**
ommpy 0:d383e2dee0f7 32 * \defgroup platform_Span Span class
ommpy 0:d383e2dee0f7 33 * @{
ommpy 0:d383e2dee0f7 34 */
ommpy 0:d383e2dee0f7 35
ommpy 0:d383e2dee0f7 36 // Internal details of Span
ommpy 0:d383e2dee0f7 37 // It is used construct Span from Span of convertible types (non const -> const)
ommpy 0:d383e2dee0f7 38 namespace span_detail {
ommpy 0:d383e2dee0f7 39
ommpy 0:d383e2dee0f7 40 // If From type is convertible to To type, then the compilation constant value is
ommpy 0:d383e2dee0f7 41 // true; otherwise, it is false.
ommpy 0:d383e2dee0f7 42 template<typename From, typename To>
ommpy 0:d383e2dee0f7 43 class is_convertible {
ommpy 0:d383e2dee0f7 44 struct true_type {
ommpy 0:d383e2dee0f7 45 char x[512];
ommpy 0:d383e2dee0f7 46 };
ommpy 0:d383e2dee0f7 47 struct false_type { };
ommpy 0:d383e2dee0f7 48
ommpy 0:d383e2dee0f7 49 static const From &generator();
ommpy 0:d383e2dee0f7 50 static true_type sink(const To &);
ommpy 0:d383e2dee0f7 51 static false_type sink(...);
ommpy 0:d383e2dee0f7 52
ommpy 0:d383e2dee0f7 53 public:
ommpy 0:d383e2dee0f7 54 static const bool value = sizeof(true_type) == sizeof(sink(generator()));
ommpy 0:d383e2dee0f7 55 };
ommpy 0:d383e2dee0f7 56
ommpy 0:d383e2dee0f7 57 }
ommpy 0:d383e2dee0f7 58
ommpy 0:d383e2dee0f7 59 #if defined(DOXYGEN_ONLY)
ommpy 0:d383e2dee0f7 60 /**
ommpy 0:d383e2dee0f7 61 * Special value for the Extent parameter of Span.
ommpy 0:d383e2dee0f7 62 * If the type uses this value, then the size of the array is stored in the object
ommpy 0:d383e2dee0f7 63 * at runtime.
ommpy 0:d383e2dee0f7 64 *
ommpy 0:d383e2dee0f7 65 * @relates Span
ommpy 0:d383e2dee0f7 66 */
ommpy 0:d383e2dee0f7 67 const ptrdiff_t SPAN_DYNAMIC_EXTENT = -1;
ommpy 0:d383e2dee0f7 68 #else
ommpy 0:d383e2dee0f7 69 #define SPAN_DYNAMIC_EXTENT -1
ommpy 0:d383e2dee0f7 70 #endif
ommpy 0:d383e2dee0f7 71
ommpy 0:d383e2dee0f7 72 /**
ommpy 0:d383e2dee0f7 73 * Nonowning view to a sequence of contiguous elements.
ommpy 0:d383e2dee0f7 74 *
ommpy 0:d383e2dee0f7 75 * Spans encapsulate a pointer to a sequence of contiguous elements and its size
ommpy 0:d383e2dee0f7 76 * into a single object. Span can replace the traditional pair of pointer and
ommpy 0:d383e2dee0f7 77 * size arguments passed as array definitions in function calls.
ommpy 0:d383e2dee0f7 78 *
ommpy 0:d383e2dee0f7 79 * @par Operations
ommpy 0:d383e2dee0f7 80 *
ommpy 0:d383e2dee0f7 81 * Span objects can be copied and assigned like regular value types with the help
ommpy 0:d383e2dee0f7 82 * of the copy constructor or the copy assignment (=) operator.
ommpy 0:d383e2dee0f7 83 *
ommpy 0:d383e2dee0f7 84 * You can retrieve elements of the object with the subscript ([]) operator. You can access the
ommpy 0:d383e2dee0f7 85 * pointer to the first element of the sequence viewed with data().
ommpy 0:d383e2dee0f7 86 * The function size() returns the number of elements in the sequence, and
ommpy 0:d383e2dee0f7 87 * empty() informs whether there is any element in the sequence.
ommpy 0:d383e2dee0f7 88 *
ommpy 0:d383e2dee0f7 89 * You can slice Span from the beginning of the sequence (first()), from the end
ommpy 0:d383e2dee0f7 90 * of the sequence (last()) or from an arbitrary point of the sequence (subspan()).
ommpy 0:d383e2dee0f7 91 *
ommpy 0:d383e2dee0f7 92 * @par Size encoding
ommpy 0:d383e2dee0f7 93 *
ommpy 0:d383e2dee0f7 94 * The size of the sequence can be encoded in the type itself or in the value of
ommpy 0:d383e2dee0f7 95 * the instance with the help of the template parameter Extent:
ommpy 0:d383e2dee0f7 96 *
ommpy 0:d383e2dee0f7 97 * - Span<uint8_t, 6>: Span over a sequence of 6 elements.
ommpy 0:d383e2dee0f7 98 * - Span<uint8_t>: Span over an arbitrary long sequence.
ommpy 0:d383e2dee0f7 99 *
ommpy 0:d383e2dee0f7 100 * When the size is encoded in the type itself, it is guaranteed that the Span
ommpy 0:d383e2dee0f7 101 * view is a valid sequence (not empty() and not NULL) - unless Extent equals 0.
ommpy 0:d383e2dee0f7 102 * The type system also prevents automatic conversion from Span of different
ommpy 0:d383e2dee0f7 103 * sizes. Finally, the Span object is internally represented as a single pointer.
ommpy 0:d383e2dee0f7 104 *
ommpy 0:d383e2dee0f7 105 * When the size of the sequence viewed is encoded in the Span value, Span
ommpy 0:d383e2dee0f7 106 * instances can view an empty sequence. The function empty() helps client code
ommpy 0:d383e2dee0f7 107 * decide whether Span is viewing valid content or not.
ommpy 0:d383e2dee0f7 108 *
ommpy 0:d383e2dee0f7 109 * @par Example
ommpy 0:d383e2dee0f7 110 *
ommpy 0:d383e2dee0f7 111 * - Encoding fixed size array: Array values in parameter decays automatically
ommpy 0:d383e2dee0f7 112 * to pointer, which leaves room for subtitle bugs:
ommpy 0:d383e2dee0f7 113 *
ommpy 0:d383e2dee0f7 114 * @code
ommpy 0:d383e2dee0f7 115 typedef uint8_t mac_address_t[6];
ommpy 0:d383e2dee0f7 116 void process_mac(mac_address_t);
ommpy 0:d383e2dee0f7 117
ommpy 0:d383e2dee0f7 118 // compile just fine
ommpy 0:d383e2dee0f7 119 uint8_t *invalid_value = NULL;
ommpy 0:d383e2dee0f7 120 process_mac(invalid_value);
ommpy 0:d383e2dee0f7 121
ommpy 0:d383e2dee0f7 122
ommpy 0:d383e2dee0f7 123 // correct way
ommpy 0:d383e2dee0f7 124 typedef Span<uint8_t, 6> mac_address_t;
ommpy 0:d383e2dee0f7 125 void process_mac(mac_address_t);
ommpy 0:d383e2dee0f7 126
ommpy 0:d383e2dee0f7 127 // compilation error
ommpy 0:d383e2dee0f7 128 uint8_t *invalid_value = NULL;
ommpy 0:d383e2dee0f7 129 process_mac(invalid_value);
ommpy 0:d383e2dee0f7 130
ommpy 0:d383e2dee0f7 131 // compilation ok
ommpy 0:d383e2dee0f7 132 uint8_t valid_value[6];
ommpy 0:d383e2dee0f7 133 process_mac(valid_value);
ommpy 0:d383e2dee0f7 134 * @endcode
ommpy 0:d383e2dee0f7 135 *
ommpy 0:d383e2dee0f7 136 * - Arbitrary buffer: When dealing with multiple buffers, it becomes painful to
ommpy 0:d383e2dee0f7 137 * keep track of every buffer size and pointer.
ommpy 0:d383e2dee0f7 138 *
ommpy 0:d383e2dee0f7 139 * @code
ommpy 0:d383e2dee0f7 140 const uint8_t options_tag[OPTIONS_TAG_SIZE];
ommpy 0:d383e2dee0f7 141
ommpy 0:d383e2dee0f7 142 struct parsed_value_t {
ommpy 0:d383e2dee0f7 143 uint8_t *header;
ommpy 0:d383e2dee0f7 144 uint8_t *options;
ommpy 0:d383e2dee0f7 145 uint8_t *payload;
ommpy 0:d383e2dee0f7 146 size_t payload_size;
ommpy 0:d383e2dee0f7 147 }
ommpy 0:d383e2dee0f7 148
ommpy 0:d383e2dee0f7 149 parsed_value_t parse(uint8_t *buffer, size_t buffer_size)
ommpy 0:d383e2dee0f7 150 {
ommpy 0:d383e2dee0f7 151 parsed_value_t parsed_value { 0 };
ommpy 0:d383e2dee0f7 152
ommpy 0:d383e2dee0f7 153 if (buffer != NULL && buffer_size <= MINIMAL_BUFFER_SIZE) {
ommpy 0:d383e2dee0f7 154 return parsed_value;
ommpy 0:d383e2dee0f7 155 }
ommpy 0:d383e2dee0f7 156
ommpy 0:d383e2dee0f7 157 parsed_value.header = buffer;
ommpy 0:d383e2dee0f7 158 parsed_value.header_size = BUFFER_HEADER_SIZE;
ommpy 0:d383e2dee0f7 159
ommpy 0:d383e2dee0f7 160 if (memcmp(buffer + HEADER_OPTIONS_INDEX, options_tag, sizeof(options_tag)) == 0) {
ommpy 0:d383e2dee0f7 161 options = buffer + BUFFER_HEADER_SIZE;
ommpy 0:d383e2dee0f7 162 payload = buffer + BUFFER_HEADER_SIZE + OPTIONS_SIZE;
ommpy 0:d383e2dee0f7 163 payload_size = buffer_size - BUFFER_HEADER_SIZE + OPTIONS_SIZE;
ommpy 0:d383e2dee0f7 164 } else {
ommpy 0:d383e2dee0f7 165 payload = buffer + BUFFER_HEADER_SIZE;
ommpy 0:d383e2dee0f7 166 payload_size = buffer_size - BUFFER_HEADER_SIZE;
ommpy 0:d383e2dee0f7 167 }
ommpy 0:d383e2dee0f7 168
ommpy 0:d383e2dee0f7 169 return parsed_value;
ommpy 0:d383e2dee0f7 170 }
ommpy 0:d383e2dee0f7 171
ommpy 0:d383e2dee0f7 172
ommpy 0:d383e2dee0f7 173 //with Span
ommpy 0:d383e2dee0f7 174 struct parsed_value_t {
ommpy 0:d383e2dee0f7 175 Span<uint8_t> header;
ommpy 0:d383e2dee0f7 176 Span<uint8_t> options;
ommpy 0:d383e2dee0f7 177 Span<uint8_t> payload;
ommpy 0:d383e2dee0f7 178 }
ommpy 0:d383e2dee0f7 179
ommpy 0:d383e2dee0f7 180 parsed_value_t parse(const Span<uint8_t> &buffer)
ommpy 0:d383e2dee0f7 181 {
ommpy 0:d383e2dee0f7 182 parsed_value_t parsed_value;
ommpy 0:d383e2dee0f7 183
ommpy 0:d383e2dee0f7 184 if (buffer.size() <= MINIMAL_BUFFER_SIZE) {
ommpy 0:d383e2dee0f7 185 return parsed_value;
ommpy 0:d383e2dee0f7 186 }
ommpy 0:d383e2dee0f7 187
ommpy 0:d383e2dee0f7 188 parsed_value.header = buffer.first(BUFFER_HEADER_SIZE);
ommpy 0:d383e2dee0f7 189
ommpy 0:d383e2dee0f7 190 if (buffer.subspan<HEADER_OPTIONS_INDEX, sizeof(options_tag)>() == option_tag) {
ommpy 0:d383e2dee0f7 191 options = buffer.supspan(parsed_value.header.size(), OPTIONS_SIZE);
ommpy 0:d383e2dee0f7 192 }
ommpy 0:d383e2dee0f7 193
ommpy 0:d383e2dee0f7 194 payload = buffer.subspan(parsed_value.header.size() + parsed_value.options.size());
ommpy 0:d383e2dee0f7 195
ommpy 0:d383e2dee0f7 196 return parsed_value;
ommpy 0:d383e2dee0f7 197 }
ommpy 0:d383e2dee0f7 198 * @endcode
ommpy 0:d383e2dee0f7 199 *
ommpy 0:d383e2dee0f7 200 * @note You can create Span instances with the help of the function template
ommpy 0:d383e2dee0f7 201 * make_Span() and make_const_Span().
ommpy 0:d383e2dee0f7 202 *
ommpy 0:d383e2dee0f7 203 * @note Span<T, Extent> objects can be implicitly converted to Span<T> objects
ommpy 0:d383e2dee0f7 204 * where required.
ommpy 0:d383e2dee0f7 205 *
ommpy 0:d383e2dee0f7 206 * @tparam ElementType type of objects the Span views.
ommpy 0:d383e2dee0f7 207 *
ommpy 0:d383e2dee0f7 208 * @tparam Extent The size of the contiguous sequence viewed. The default value
ommpy 0:d383e2dee0f7 209 * SPAN_DYNAMIC_SIZE is special because it allows construction of Span objects of
ommpy 0:d383e2dee0f7 210 * any size (set at runtime).
ommpy 0:d383e2dee0f7 211 */
ommpy 0:d383e2dee0f7 212 template<typename ElementType, ptrdiff_t Extent = SPAN_DYNAMIC_EXTENT>
ommpy 0:d383e2dee0f7 213 struct Span {
ommpy 0:d383e2dee0f7 214
ommpy 0:d383e2dee0f7 215 /**
ommpy 0:d383e2dee0f7 216 * Type of the element contained
ommpy 0:d383e2dee0f7 217 */
ommpy 0:d383e2dee0f7 218 typedef ElementType element_type;
ommpy 0:d383e2dee0f7 219
ommpy 0:d383e2dee0f7 220 /**
ommpy 0:d383e2dee0f7 221 * Type of the index.
ommpy 0:d383e2dee0f7 222 */
ommpy 0:d383e2dee0f7 223 typedef ptrdiff_t index_type;
ommpy 0:d383e2dee0f7 224
ommpy 0:d383e2dee0f7 225 /**
ommpy 0:d383e2dee0f7 226 * Pointer to an ElementType
ommpy 0:d383e2dee0f7 227 */
ommpy 0:d383e2dee0f7 228 typedef element_type *pointer;
ommpy 0:d383e2dee0f7 229
ommpy 0:d383e2dee0f7 230 /**
ommpy 0:d383e2dee0f7 231 * Reference to an ElementType
ommpy 0:d383e2dee0f7 232 */
ommpy 0:d383e2dee0f7 233 typedef element_type &reference;
ommpy 0:d383e2dee0f7 234
ommpy 0:d383e2dee0f7 235 /**
ommpy 0:d383e2dee0f7 236 * Size of the Extent; -1 if dynamic.
ommpy 0:d383e2dee0f7 237 */
ommpy 0:d383e2dee0f7 238 static const index_type extent = Extent;
ommpy 0:d383e2dee0f7 239
ommpy 0:d383e2dee0f7 240 MBED_STATIC_ASSERT(Extent >= 0, "Invalid extent for a Span");
ommpy 0:d383e2dee0f7 241
ommpy 0:d383e2dee0f7 242 /**
ommpy 0:d383e2dee0f7 243 * Construct an empty Span.
ommpy 0:d383e2dee0f7 244 *
ommpy 0:d383e2dee0f7 245 * @post a call to size() returns 0, and data() returns NULL.
ommpy 0:d383e2dee0f7 246 *
ommpy 0:d383e2dee0f7 247 * @note This function is not accessible if Extent != SPAN_DYNAMIC_EXTENT or
ommpy 0:d383e2dee0f7 248 * Extent != 0 .
ommpy 0:d383e2dee0f7 249 */
ommpy 0:d383e2dee0f7 250 Span() :
ommpy 0:d383e2dee0f7 251 _data(NULL)
ommpy 0:d383e2dee0f7 252 {
ommpy 0:d383e2dee0f7 253 MBED_STATIC_ASSERT(
ommpy 0:d383e2dee0f7 254 Extent == 0,
ommpy 0:d383e2dee0f7 255 "Cannot default construct a static-extent Span (unless Extent is 0)"
ommpy 0:d383e2dee0f7 256 );
ommpy 0:d383e2dee0f7 257 }
ommpy 0:d383e2dee0f7 258
ommpy 0:d383e2dee0f7 259 /**
ommpy 0:d383e2dee0f7 260 * Construct a Span from a pointer to a buffer and its size.
ommpy 0:d383e2dee0f7 261 *
ommpy 0:d383e2dee0f7 262 * @param ptr Pointer to the beginning of the data viewed.
ommpy 0:d383e2dee0f7 263 *
ommpy 0:d383e2dee0f7 264 * @param count Number of elements viewed.
ommpy 0:d383e2dee0f7 265 *
ommpy 0:d383e2dee0f7 266 * @pre [ptr, ptr + count) must be be a valid range.
ommpy 0:d383e2dee0f7 267 * @pre count must be equal to Extent.
ommpy 0:d383e2dee0f7 268 *
ommpy 0:d383e2dee0f7 269 * @post a call to size() returns Extent, and data() returns @p ptr.
ommpy 0:d383e2dee0f7 270 */
ommpy 0:d383e2dee0f7 271 Span(pointer ptr, index_type count) :
ommpy 0:d383e2dee0f7 272 _data(ptr)
ommpy 0:d383e2dee0f7 273 {
ommpy 0:d383e2dee0f7 274 MBED_ASSERT(count == Extent);
ommpy 0:d383e2dee0f7 275 MBED_ASSERT(Extent == 0 || ptr != NULL);
ommpy 0:d383e2dee0f7 276 }
ommpy 0:d383e2dee0f7 277
ommpy 0:d383e2dee0f7 278 /**
ommpy 0:d383e2dee0f7 279 * Construct a Span from the range [first, last).
ommpy 0:d383e2dee0f7 280 *
ommpy 0:d383e2dee0f7 281 * @param first Pointer to the beginning of the data viewed.
ommpy 0:d383e2dee0f7 282 * @param last End of the range (element after the last element).
ommpy 0:d383e2dee0f7 283 *
ommpy 0:d383e2dee0f7 284 * @pre [first, last) must be be a valid range.
ommpy 0:d383e2dee0f7 285 * @pre first <= last.
ommpy 0:d383e2dee0f7 286 * @pre last - first must be equal to Extent.
ommpy 0:d383e2dee0f7 287 *
ommpy 0:d383e2dee0f7 288 * @post a call to size() returns Extent, and data() returns @p first.
ommpy 0:d383e2dee0f7 289 */
ommpy 0:d383e2dee0f7 290 Span(pointer first, pointer last) :
ommpy 0:d383e2dee0f7 291 _data(first)
ommpy 0:d383e2dee0f7 292 {
ommpy 0:d383e2dee0f7 293 MBED_ASSERT(first <= last);
ommpy 0:d383e2dee0f7 294 MBED_ASSERT((last - first) == Extent);
ommpy 0:d383e2dee0f7 295 MBED_ASSERT(Extent == 0 || first != NULL);
ommpy 0:d383e2dee0f7 296 }
ommpy 0:d383e2dee0f7 297
ommpy 0:d383e2dee0f7 298 // AStyle ignore, not handling correctly below
ommpy 0:d383e2dee0f7 299 // *INDENT-OFF*
ommpy 0:d383e2dee0f7 300 /**
ommpy 0:d383e2dee0f7 301 * Construct a Span from the reference to an array.
ommpy 0:d383e2dee0f7 302 *
ommpy 0:d383e2dee0f7 303 * @param elements Reference to the array viewed.
ommpy 0:d383e2dee0f7 304 *
ommpy 0:d383e2dee0f7 305 * @post a call to size() returns Extent, and data() returns a
ommpy 0:d383e2dee0f7 306 * pointer to elements.
ommpy 0:d383e2dee0f7 307 */
ommpy 0:d383e2dee0f7 308 Span(element_type (&elements)[Extent]):
ommpy 0:d383e2dee0f7 309 _data(elements) { }
ommpy 0:d383e2dee0f7 310
ommpy 0:d383e2dee0f7 311 /**
ommpy 0:d383e2dee0f7 312 * Construct a Span object from another Span of the same size.
ommpy 0:d383e2dee0f7 313 *
ommpy 0:d383e2dee0f7 314 * @param other The Span object used to construct this.
ommpy 0:d383e2dee0f7 315 *
ommpy 0:d383e2dee0f7 316 * @note For Span with a positive extent, this function is not accessible.
ommpy 0:d383e2dee0f7 317 *
ommpy 0:d383e2dee0f7 318 * @note OtherElementType(*)[] must be convertible to ElementType(*)[].
ommpy 0:d383e2dee0f7 319 */
ommpy 0:d383e2dee0f7 320 template<typename OtherElementType>
ommpy 0:d383e2dee0f7 321 Span(const Span<OtherElementType, Extent> &other):
ommpy 0:d383e2dee0f7 322 _data(other.data())
ommpy 0:d383e2dee0f7 323 {
ommpy 0:d383e2dee0f7 324 MBED_STATIC_ASSERT(
ommpy 0:d383e2dee0f7 325 (span_detail::is_convertible<OtherElementType (*)[1], ElementType (*)[1]>::value),
ommpy 0:d383e2dee0f7 326 "OtherElementType(*)[] should be convertible to ElementType (*)[]"
ommpy 0:d383e2dee0f7 327 );
ommpy 0:d383e2dee0f7 328 }
ommpy 0:d383e2dee0f7 329 // *INDENT-ON*
ommpy 0:d383e2dee0f7 330
ommpy 0:d383e2dee0f7 331 /**
ommpy 0:d383e2dee0f7 332 * Return the size of the sequence viewed.
ommpy 0:d383e2dee0f7 333 *
ommpy 0:d383e2dee0f7 334 * @return The size of the sequence viewed.
ommpy 0:d383e2dee0f7 335 */
ommpy 0:d383e2dee0f7 336 index_type size() const
ommpy 0:d383e2dee0f7 337 {
ommpy 0:d383e2dee0f7 338 return Extent;
ommpy 0:d383e2dee0f7 339 }
ommpy 0:d383e2dee0f7 340
ommpy 0:d383e2dee0f7 341 /**
ommpy 0:d383e2dee0f7 342 * Return if the sequence is empty or not.
ommpy 0:d383e2dee0f7 343 *
ommpy 0:d383e2dee0f7 344 * @return true if the sequence is empty and false otherwise.
ommpy 0:d383e2dee0f7 345 */
ommpy 0:d383e2dee0f7 346 bool empty() const
ommpy 0:d383e2dee0f7 347 {
ommpy 0:d383e2dee0f7 348 return size() == 0;
ommpy 0:d383e2dee0f7 349 }
ommpy 0:d383e2dee0f7 350
ommpy 0:d383e2dee0f7 351 /**
ommpy 0:d383e2dee0f7 352 * Returns a reference to the element at position @p index.
ommpy 0:d383e2dee0f7 353 *
ommpy 0:d383e2dee0f7 354 * @param index Index of the element to access.
ommpy 0:d383e2dee0f7 355 *
ommpy 0:d383e2dee0f7 356 * @return A reference to the element at the index specified in input.
ommpy 0:d383e2dee0f7 357 *
ommpy 0:d383e2dee0f7 358 * @pre 0 <= index < Extent.
ommpy 0:d383e2dee0f7 359 */
ommpy 0:d383e2dee0f7 360 reference operator[](index_type index) const
ommpy 0:d383e2dee0f7 361 {
ommpy 0:d383e2dee0f7 362 #ifdef MBED_DEBUG
ommpy 0:d383e2dee0f7 363 MBED_ASSERT(0 <= index && index < Extent);
ommpy 0:d383e2dee0f7 364 #endif
ommpy 0:d383e2dee0f7 365 return _data[index];
ommpy 0:d383e2dee0f7 366 }
ommpy 0:d383e2dee0f7 367
ommpy 0:d383e2dee0f7 368 /**
ommpy 0:d383e2dee0f7 369 * Return a pointer to the first element of the sequence or NULL if the Span
ommpy 0:d383e2dee0f7 370 * is empty().
ommpy 0:d383e2dee0f7 371 *
ommpy 0:d383e2dee0f7 372 * @return The pointer to the first element of the Span.
ommpy 0:d383e2dee0f7 373 */
ommpy 0:d383e2dee0f7 374 pointer data() const
ommpy 0:d383e2dee0f7 375 {
ommpy 0:d383e2dee0f7 376 return _data;
ommpy 0:d383e2dee0f7 377 }
ommpy 0:d383e2dee0f7 378
ommpy 0:d383e2dee0f7 379 /**
ommpy 0:d383e2dee0f7 380 * Create a new Span over the first @p Count elements of the existing view.
ommpy 0:d383e2dee0f7 381 *
ommpy 0:d383e2dee0f7 382 * @tparam Count The number of element viewed by the new Span
ommpy 0:d383e2dee0f7 383 *
ommpy 0:d383e2dee0f7 384 * @return A new Span over the first @p Count elements.
ommpy 0:d383e2dee0f7 385 *
ommpy 0:d383e2dee0f7 386 * @pre Count >= 0 && Count <= size().
ommpy 0:d383e2dee0f7 387 */
ommpy 0:d383e2dee0f7 388 template<ptrdiff_t Count>
ommpy 0:d383e2dee0f7 389 Span<element_type, Count> first() const
ommpy 0:d383e2dee0f7 390 {
ommpy 0:d383e2dee0f7 391 MBED_STATIC_ASSERT(
ommpy 0:d383e2dee0f7 392 (0 <= Count) && (Count <= Extent),
ommpy 0:d383e2dee0f7 393 "Invalid subspan extent"
ommpy 0:d383e2dee0f7 394 );
ommpy 0:d383e2dee0f7 395 return Span<element_type, Count>(_data, Count);
ommpy 0:d383e2dee0f7 396 }
ommpy 0:d383e2dee0f7 397
ommpy 0:d383e2dee0f7 398 /**
ommpy 0:d383e2dee0f7 399 * Create a new Span over the last @p Count elements of the existing view.
ommpy 0:d383e2dee0f7 400 *
ommpy 0:d383e2dee0f7 401 * @tparam Count The number of element viewed by the new Span.
ommpy 0:d383e2dee0f7 402 *
ommpy 0:d383e2dee0f7 403 * @return A new Span over the last @p Count elements.
ommpy 0:d383e2dee0f7 404 *
ommpy 0:d383e2dee0f7 405 * @pre Count >= 0 && Count <= size().
ommpy 0:d383e2dee0f7 406 */
ommpy 0:d383e2dee0f7 407 template<ptrdiff_t Count>
ommpy 0:d383e2dee0f7 408 Span<element_type, Count> last() const
ommpy 0:d383e2dee0f7 409 {
ommpy 0:d383e2dee0f7 410 MBED_STATIC_ASSERT(
ommpy 0:d383e2dee0f7 411 (0 <= Count) && (Count <= Extent),
ommpy 0:d383e2dee0f7 412 "Invalid subspan extent"
ommpy 0:d383e2dee0f7 413 );
ommpy 0:d383e2dee0f7 414 return Span<element_type, Count>(_data + (Extent - Count), Count);
ommpy 0:d383e2dee0f7 415 }
ommpy 0:d383e2dee0f7 416
ommpy 0:d383e2dee0f7 417 // AStyle ignore, not handling correctly below
ommpy 0:d383e2dee0f7 418 // *INDENT-OFF*
ommpy 0:d383e2dee0f7 419 /**
ommpy 0:d383e2dee0f7 420 * Create a subspan that is a view of other Count elements; the view starts at
ommpy 0:d383e2dee0f7 421 * element Offset.
ommpy 0:d383e2dee0f7 422 *
ommpy 0:d383e2dee0f7 423 * @tparam Offset The offset of the first element viewed by the subspan.
ommpy 0:d383e2dee0f7 424 *
ommpy 0:d383e2dee0f7 425 * @tparam Count The number of elements present in the subspan. If Count
ommpy 0:d383e2dee0f7 426 * is equal to SPAN_DYNAMIC_EXTENT, then a Span starting at offset and
ommpy 0:d383e2dee0f7 427 * containing the rest of the elements is returned.
ommpy 0:d383e2dee0f7 428 *
ommpy 0:d383e2dee0f7 429 * @return A subspan of this starting at Offset and Count long.
ommpy 0:d383e2dee0f7 430 */
ommpy 0:d383e2dee0f7 431 template<std::ptrdiff_t Offset, std::ptrdiff_t Count>
ommpy 0:d383e2dee0f7 432 Span<element_type, Count == SPAN_DYNAMIC_EXTENT ? Extent - Offset : Count>
ommpy 0:d383e2dee0f7 433 subspan() const
ommpy 0:d383e2dee0f7 434 {
ommpy 0:d383e2dee0f7 435 MBED_STATIC_ASSERT(
ommpy 0:d383e2dee0f7 436 0 <= Offset && Offset <= Extent,
ommpy 0:d383e2dee0f7 437 "Invalid subspan offset"
ommpy 0:d383e2dee0f7 438 );
ommpy 0:d383e2dee0f7 439 MBED_STATIC_ASSERT(
ommpy 0:d383e2dee0f7 440 (Count == SPAN_DYNAMIC_EXTENT) ||
ommpy 0:d383e2dee0f7 441 (0 <= Count && (Count + Offset) <= Extent),
ommpy 0:d383e2dee0f7 442 "Invalid subspan count"
ommpy 0:d383e2dee0f7 443 );
ommpy 0:d383e2dee0f7 444 return Span<element_type, Count == SPAN_DYNAMIC_EXTENT ? Extent - Offset : Count>(
ommpy 0:d383e2dee0f7 445 _data + Offset,
ommpy 0:d383e2dee0f7 446 Count == SPAN_DYNAMIC_EXTENT ? Extent - Offset : Count
ommpy 0:d383e2dee0f7 447 );
ommpy 0:d383e2dee0f7 448 }
ommpy 0:d383e2dee0f7 449 // *INDENT-ON*
ommpy 0:d383e2dee0f7 450
ommpy 0:d383e2dee0f7 451 /**
ommpy 0:d383e2dee0f7 452 * Create a new Span over the first @p count elements of the existing view.
ommpy 0:d383e2dee0f7 453 *
ommpy 0:d383e2dee0f7 454 * @param count The number of element viewed by the new Span.
ommpy 0:d383e2dee0f7 455 *
ommpy 0:d383e2dee0f7 456 * @return A new Span over the first @p count elements.
ommpy 0:d383e2dee0f7 457 */
ommpy 0:d383e2dee0f7 458 Span<element_type, SPAN_DYNAMIC_EXTENT> first(index_type count) const
ommpy 0:d383e2dee0f7 459 {
ommpy 0:d383e2dee0f7 460 MBED_ASSERT(0 <= count && count <= Extent);
ommpy 0:d383e2dee0f7 461 return Span<element_type, SPAN_DYNAMIC_EXTENT>(_data, count);
ommpy 0:d383e2dee0f7 462 }
ommpy 0:d383e2dee0f7 463
ommpy 0:d383e2dee0f7 464 /**
ommpy 0:d383e2dee0f7 465 * Create a new Span over the last @p count elements of the existing view.
ommpy 0:d383e2dee0f7 466 *
ommpy 0:d383e2dee0f7 467 * @param count The number of elements viewed by the new Span.
ommpy 0:d383e2dee0f7 468 *
ommpy 0:d383e2dee0f7 469 * @return A new Span over the last @p count elements.
ommpy 0:d383e2dee0f7 470 */
ommpy 0:d383e2dee0f7 471 Span<element_type, SPAN_DYNAMIC_EXTENT> last(index_type count) const
ommpy 0:d383e2dee0f7 472 {
ommpy 0:d383e2dee0f7 473 MBED_ASSERT(0 <= count && count <= Extent);
ommpy 0:d383e2dee0f7 474 return Span<element_type, SPAN_DYNAMIC_EXTENT>(
ommpy 0:d383e2dee0f7 475 _data + (Extent - count),
ommpy 0:d383e2dee0f7 476 count
ommpy 0:d383e2dee0f7 477 );
ommpy 0:d383e2dee0f7 478 }
ommpy 0:d383e2dee0f7 479
ommpy 0:d383e2dee0f7 480 /**
ommpy 0:d383e2dee0f7 481 * Create a subspan that is a view of other count elements; the view starts at
ommpy 0:d383e2dee0f7 482 * element offset.
ommpy 0:d383e2dee0f7 483 *
ommpy 0:d383e2dee0f7 484 * @param offset The offset of the first element viewed by the subspan.
ommpy 0:d383e2dee0f7 485 *
ommpy 0:d383e2dee0f7 486 * @param count The number of elements present in the subspan. If Count
ommpy 0:d383e2dee0f7 487 * is equal to SPAN_DYNAMIC_EXTENT, then a span starting at offset and
ommpy 0:d383e2dee0f7 488 * containing the rest of the elements is returned.
ommpy 0:d383e2dee0f7 489 *
ommpy 0:d383e2dee0f7 490 * @return
ommpy 0:d383e2dee0f7 491 */
ommpy 0:d383e2dee0f7 492 Span<element_type, SPAN_DYNAMIC_EXTENT> subspan(
ommpy 0:d383e2dee0f7 493 index_type offset, index_type count = SPAN_DYNAMIC_EXTENT
ommpy 0:d383e2dee0f7 494 ) const
ommpy 0:d383e2dee0f7 495 {
ommpy 0:d383e2dee0f7 496 MBED_ASSERT(0 <= offset && offset <= Extent);
ommpy 0:d383e2dee0f7 497 MBED_ASSERT(
ommpy 0:d383e2dee0f7 498 (count == SPAN_DYNAMIC_EXTENT) ||
ommpy 0:d383e2dee0f7 499 (0 <= count && (count + offset) <= Extent)
ommpy 0:d383e2dee0f7 500 );
ommpy 0:d383e2dee0f7 501 return Span<element_type, SPAN_DYNAMIC_EXTENT>(
ommpy 0:d383e2dee0f7 502 _data + offset,
ommpy 0:d383e2dee0f7 503 count == SPAN_DYNAMIC_EXTENT ? Extent - offset : count
ommpy 0:d383e2dee0f7 504 );
ommpy 0:d383e2dee0f7 505 }
ommpy 0:d383e2dee0f7 506
ommpy 0:d383e2dee0f7 507 private:
ommpy 0:d383e2dee0f7 508 pointer _data;
ommpy 0:d383e2dee0f7 509 };
ommpy 0:d383e2dee0f7 510
ommpy 0:d383e2dee0f7 511 /**
ommpy 0:d383e2dee0f7 512 * Span specialization that handle dynamic size.
ommpy 0:d383e2dee0f7 513 */
ommpy 0:d383e2dee0f7 514 template<typename ElementType>
ommpy 0:d383e2dee0f7 515 struct Span<ElementType, SPAN_DYNAMIC_EXTENT> {
ommpy 0:d383e2dee0f7 516 /**
ommpy 0:d383e2dee0f7 517 * Type of the element contained.
ommpy 0:d383e2dee0f7 518 */
ommpy 0:d383e2dee0f7 519 typedef ElementType element_type;
ommpy 0:d383e2dee0f7 520
ommpy 0:d383e2dee0f7 521 /**
ommpy 0:d383e2dee0f7 522 * Type of the index.
ommpy 0:d383e2dee0f7 523 */
ommpy 0:d383e2dee0f7 524 typedef ptrdiff_t index_type;
ommpy 0:d383e2dee0f7 525
ommpy 0:d383e2dee0f7 526 /**
ommpy 0:d383e2dee0f7 527 * Pointer to an ElementType.
ommpy 0:d383e2dee0f7 528 */
ommpy 0:d383e2dee0f7 529 typedef element_type *pointer;
ommpy 0:d383e2dee0f7 530
ommpy 0:d383e2dee0f7 531 /**
ommpy 0:d383e2dee0f7 532 * Reference to an ElementType.
ommpy 0:d383e2dee0f7 533 */
ommpy 0:d383e2dee0f7 534 typedef element_type &reference;
ommpy 0:d383e2dee0f7 535
ommpy 0:d383e2dee0f7 536 /**
ommpy 0:d383e2dee0f7 537 * Size of the Extent; -1 if dynamic.
ommpy 0:d383e2dee0f7 538 */
ommpy 0:d383e2dee0f7 539 static const index_type extent = SPAN_DYNAMIC_EXTENT;
ommpy 0:d383e2dee0f7 540
ommpy 0:d383e2dee0f7 541 /**
ommpy 0:d383e2dee0f7 542 * Construct an empty Span.
ommpy 0:d383e2dee0f7 543 *
ommpy 0:d383e2dee0f7 544 * @post a call to size() returns 0, and data() returns NULL.
ommpy 0:d383e2dee0f7 545 *
ommpy 0:d383e2dee0f7 546 * @note This function is not accessible if Extent != SPAN_DYNAMIC_EXTENT or
ommpy 0:d383e2dee0f7 547 * Extent != 0 .
ommpy 0:d383e2dee0f7 548 */
ommpy 0:d383e2dee0f7 549 Span() :
ommpy 0:d383e2dee0f7 550 _data(NULL), _size(0) { }
ommpy 0:d383e2dee0f7 551
ommpy 0:d383e2dee0f7 552 /**
ommpy 0:d383e2dee0f7 553 * Construct a Span from a pointer to a buffer and its size.
ommpy 0:d383e2dee0f7 554 *
ommpy 0:d383e2dee0f7 555 * @param ptr Pointer to the beginning of the data viewed.
ommpy 0:d383e2dee0f7 556 *
ommpy 0:d383e2dee0f7 557 * @param count Number of elements viewed.
ommpy 0:d383e2dee0f7 558 *
ommpy 0:d383e2dee0f7 559 * @pre [ptr, ptr + count) must be be a valid range.
ommpy 0:d383e2dee0f7 560 * @pre count must be equal to extent.
ommpy 0:d383e2dee0f7 561 *
ommpy 0:d383e2dee0f7 562 * @post a call to size() returns count, and data() returns @p ptr.
ommpy 0:d383e2dee0f7 563 */
ommpy 0:d383e2dee0f7 564 Span(pointer ptr, index_type count) :
ommpy 0:d383e2dee0f7 565 _data(ptr), _size(count)
ommpy 0:d383e2dee0f7 566 {
ommpy 0:d383e2dee0f7 567 MBED_ASSERT(count >= 0);
ommpy 0:d383e2dee0f7 568 MBED_ASSERT(ptr != NULL || count == 0);
ommpy 0:d383e2dee0f7 569 }
ommpy 0:d383e2dee0f7 570
ommpy 0:d383e2dee0f7 571 /**
ommpy 0:d383e2dee0f7 572 * Construct a Span from the range [first, last).
ommpy 0:d383e2dee0f7 573 *
ommpy 0:d383e2dee0f7 574 * @param first Pointer to the beginning of the data viewed.
ommpy 0:d383e2dee0f7 575 * @param last End of the range (element after the last element).
ommpy 0:d383e2dee0f7 576 *
ommpy 0:d383e2dee0f7 577 * @pre [first, last) must be be a valid range.
ommpy 0:d383e2dee0f7 578 * @pre first <= last.
ommpy 0:d383e2dee0f7 579 *
ommpy 0:d383e2dee0f7 580 * @post a call to size() returns the result of (last - first), and
ommpy 0:d383e2dee0f7 581 * data() returns @p first.
ommpy 0:d383e2dee0f7 582 */
ommpy 0:d383e2dee0f7 583 Span(pointer first, pointer last) :
ommpy 0:d383e2dee0f7 584 _data(first), _size(last - first)
ommpy 0:d383e2dee0f7 585 {
ommpy 0:d383e2dee0f7 586 MBED_ASSERT(first <= last);
ommpy 0:d383e2dee0f7 587 MBED_ASSERT(first != NULL || (last - first) == 0);
ommpy 0:d383e2dee0f7 588 }
ommpy 0:d383e2dee0f7 589
ommpy 0:d383e2dee0f7 590 // AStyle ignore, not handling correctly below
ommpy 0:d383e2dee0f7 591 // *INDENT-OFF*
ommpy 0:d383e2dee0f7 592 /**
ommpy 0:d383e2dee0f7 593 * Construct a Span from the reference to an array.
ommpy 0:d383e2dee0f7 594 *
ommpy 0:d383e2dee0f7 595 * @param elements Reference to the array viewed.
ommpy 0:d383e2dee0f7 596 *
ommpy 0:d383e2dee0f7 597 * @tparam Count Number of elements of T presents in the array.
ommpy 0:d383e2dee0f7 598 *
ommpy 0:d383e2dee0f7 599 * @post a call to size() returns Count, and data() returns a
ommpy 0:d383e2dee0f7 600 * pointer to elements.
ommpy 0:d383e2dee0f7 601 */
ommpy 0:d383e2dee0f7 602 template<size_t Count>
ommpy 0:d383e2dee0f7 603 Span(element_type (&elements)[Count]):
ommpy 0:d383e2dee0f7 604 _data(elements), _size(Count) { }
ommpy 0:d383e2dee0f7 605
ommpy 0:d383e2dee0f7 606 /**
ommpy 0:d383e2dee0f7 607 * Construct a Span object from another Span.
ommpy 0:d383e2dee0f7 608 *
ommpy 0:d383e2dee0f7 609 * @param other The Span object used to construct this.
ommpy 0:d383e2dee0f7 610 *
ommpy 0:d383e2dee0f7 611 * @note For Span with a positive extent, this function is not accessible.
ommpy 0:d383e2dee0f7 612 *
ommpy 0:d383e2dee0f7 613 * @note OtherElementType(*)[] must be convertible to ElementType(*)[].
ommpy 0:d383e2dee0f7 614 */
ommpy 0:d383e2dee0f7 615 template<typename OtherElementType, ptrdiff_t OtherExtent>
ommpy 0:d383e2dee0f7 616 Span(const Span<OtherElementType, OtherExtent> &other):
ommpy 0:d383e2dee0f7 617 _data(other.data()), _size(other.size())
ommpy 0:d383e2dee0f7 618 {
ommpy 0:d383e2dee0f7 619 MBED_STATIC_ASSERT(
ommpy 0:d383e2dee0f7 620 (span_detail::is_convertible<OtherElementType (*)[1], ElementType (*)[1]>::value),
ommpy 0:d383e2dee0f7 621 "OtherElementType(*)[] should be convertible to ElementType (*)[]"
ommpy 0:d383e2dee0f7 622 );
ommpy 0:d383e2dee0f7 623 }
ommpy 0:d383e2dee0f7 624 // *INDENT-ON*
ommpy 0:d383e2dee0f7 625
ommpy 0:d383e2dee0f7 626 /**
ommpy 0:d383e2dee0f7 627 * Return the size of the array viewed.
ommpy 0:d383e2dee0f7 628 *
ommpy 0:d383e2dee0f7 629 * @return The number of elements present in the array viewed.
ommpy 0:d383e2dee0f7 630 */
ommpy 0:d383e2dee0f7 631 index_type size() const
ommpy 0:d383e2dee0f7 632 {
ommpy 0:d383e2dee0f7 633 return _size;
ommpy 0:d383e2dee0f7 634 }
ommpy 0:d383e2dee0f7 635
ommpy 0:d383e2dee0f7 636 /**
ommpy 0:d383e2dee0f7 637 * Return if the sequence viewed is empty or not.
ommpy 0:d383e2dee0f7 638 *
ommpy 0:d383e2dee0f7 639 * @return true if the sequence is empty and false otherwise.
ommpy 0:d383e2dee0f7 640 */
ommpy 0:d383e2dee0f7 641 bool empty() const
ommpy 0:d383e2dee0f7 642 {
ommpy 0:d383e2dee0f7 643 return size() == 0;
ommpy 0:d383e2dee0f7 644 }
ommpy 0:d383e2dee0f7 645
ommpy 0:d383e2dee0f7 646 /**
ommpy 0:d383e2dee0f7 647 * Access to an element of the sequence.
ommpy 0:d383e2dee0f7 648 *
ommpy 0:d383e2dee0f7 649 * @param index Element index to access.
ommpy 0:d383e2dee0f7 650 *
ommpy 0:d383e2dee0f7 651 * @return A reference to the element at the index specified in input.
ommpy 0:d383e2dee0f7 652 *
ommpy 0:d383e2dee0f7 653 * @pre index is less than size().
ommpy 0:d383e2dee0f7 654 */
ommpy 0:d383e2dee0f7 655 reference operator[](index_type index) const
ommpy 0:d383e2dee0f7 656 {
ommpy 0:d383e2dee0f7 657 #ifdef MBED_DEBUG
ommpy 0:d383e2dee0f7 658 MBED_ASSERT(0 <= index && index < _size);
ommpy 0:d383e2dee0f7 659 #endif
ommpy 0:d383e2dee0f7 660 return _data[index];
ommpy 0:d383e2dee0f7 661 }
ommpy 0:d383e2dee0f7 662
ommpy 0:d383e2dee0f7 663 /**
ommpy 0:d383e2dee0f7 664 * Get the raw pointer to the sequence viewed.
ommpy 0:d383e2dee0f7 665 *
ommpy 0:d383e2dee0f7 666 * @return The raw pointer to the first element viewed.
ommpy 0:d383e2dee0f7 667 */
ommpy 0:d383e2dee0f7 668 pointer data() const
ommpy 0:d383e2dee0f7 669 {
ommpy 0:d383e2dee0f7 670 return _data;
ommpy 0:d383e2dee0f7 671 }
ommpy 0:d383e2dee0f7 672
ommpy 0:d383e2dee0f7 673 /**
ommpy 0:d383e2dee0f7 674 * Create a new Span over the first @p Count elements of the existing view.
ommpy 0:d383e2dee0f7 675 *
ommpy 0:d383e2dee0f7 676 * @tparam Count The number of elements viewed by the new Span.
ommpy 0:d383e2dee0f7 677 *
ommpy 0:d383e2dee0f7 678 * @return A new Span over the first @p Count elements.
ommpy 0:d383e2dee0f7 679 *
ommpy 0:d383e2dee0f7 680 * @pre Count >= 0 && Count <= size().
ommpy 0:d383e2dee0f7 681 */
ommpy 0:d383e2dee0f7 682 template<ptrdiff_t Count>
ommpy 0:d383e2dee0f7 683 Span<element_type, Count> first() const
ommpy 0:d383e2dee0f7 684 {
ommpy 0:d383e2dee0f7 685 MBED_ASSERT((Count >= 0) && (Count <= _size));
ommpy 0:d383e2dee0f7 686 return Span<element_type, Count>(_data, Count);
ommpy 0:d383e2dee0f7 687 }
ommpy 0:d383e2dee0f7 688
ommpy 0:d383e2dee0f7 689 /**
ommpy 0:d383e2dee0f7 690 * Create a new Span over the last @p Count elements of the existing view.
ommpy 0:d383e2dee0f7 691 *
ommpy 0:d383e2dee0f7 692 * @tparam Count The number of elements viewed by the new Span.
ommpy 0:d383e2dee0f7 693 *
ommpy 0:d383e2dee0f7 694 * @return A new Span over the last @p Count elements.
ommpy 0:d383e2dee0f7 695 *
ommpy 0:d383e2dee0f7 696 * @pre Count >= 0 && Count <= size().
ommpy 0:d383e2dee0f7 697 */
ommpy 0:d383e2dee0f7 698 template<ptrdiff_t Count>
ommpy 0:d383e2dee0f7 699 Span<element_type, Count> last() const
ommpy 0:d383e2dee0f7 700 {
ommpy 0:d383e2dee0f7 701 MBED_ASSERT((0 <= Count) && (Count <= _size));
ommpy 0:d383e2dee0f7 702 return Span<element_type, Count>(_data + (_size - Count), Count);
ommpy 0:d383e2dee0f7 703 }
ommpy 0:d383e2dee0f7 704
ommpy 0:d383e2dee0f7 705 /**
ommpy 0:d383e2dee0f7 706 * Create a subspan that is a view other Count elements; the view starts at
ommpy 0:d383e2dee0f7 707 * element Offset.
ommpy 0:d383e2dee0f7 708 *
ommpy 0:d383e2dee0f7 709 * @tparam Offset The offset of the first element viewed by the subspan.
ommpy 0:d383e2dee0f7 710 *
ommpy 0:d383e2dee0f7 711 * @tparam Count The number of elements present in the subspan. If Count
ommpy 0:d383e2dee0f7 712 * is equal to SPAN_DYNAMIC_EXTENT, then a Span starting at offset and
ommpy 0:d383e2dee0f7 713 * containing the rest of the elements is returned.
ommpy 0:d383e2dee0f7 714 *
ommpy 0:d383e2dee0f7 715 * @return A subspan of this starting at Offset and Count long.
ommpy 0:d383e2dee0f7 716 */
ommpy 0:d383e2dee0f7 717 template<std::ptrdiff_t Offset, std::ptrdiff_t Count>
ommpy 0:d383e2dee0f7 718 Span<element_type, Count>
ommpy 0:d383e2dee0f7 719 subspan() const
ommpy 0:d383e2dee0f7 720 {
ommpy 0:d383e2dee0f7 721 MBED_ASSERT(0 <= Offset && Offset <= _size);
ommpy 0:d383e2dee0f7 722 MBED_ASSERT(
ommpy 0:d383e2dee0f7 723 (Count == SPAN_DYNAMIC_EXTENT) ||
ommpy 0:d383e2dee0f7 724 (0 <= Count && (Count + Offset) <= _size)
ommpy 0:d383e2dee0f7 725 );
ommpy 0:d383e2dee0f7 726 return Span<element_type, Count>(
ommpy 0:d383e2dee0f7 727 _data + Offset,
ommpy 0:d383e2dee0f7 728 Count == SPAN_DYNAMIC_EXTENT ? _size - Offset : Count
ommpy 0:d383e2dee0f7 729 );
ommpy 0:d383e2dee0f7 730 }
ommpy 0:d383e2dee0f7 731
ommpy 0:d383e2dee0f7 732 /**
ommpy 0:d383e2dee0f7 733 * Create a new Span over the first @p count elements of the existing view.
ommpy 0:d383e2dee0f7 734 *
ommpy 0:d383e2dee0f7 735 * @param count The number of elements viewed by the new Span.
ommpy 0:d383e2dee0f7 736 *
ommpy 0:d383e2dee0f7 737 * @return A new Span over the first @p count elements.
ommpy 0:d383e2dee0f7 738 */
ommpy 0:d383e2dee0f7 739 Span<element_type, SPAN_DYNAMIC_EXTENT> first(index_type count) const
ommpy 0:d383e2dee0f7 740 {
ommpy 0:d383e2dee0f7 741 MBED_ASSERT(0 <= count && count <= _size);
ommpy 0:d383e2dee0f7 742 return Span<element_type, SPAN_DYNAMIC_EXTENT>(_data, count);
ommpy 0:d383e2dee0f7 743 }
ommpy 0:d383e2dee0f7 744
ommpy 0:d383e2dee0f7 745 /**
ommpy 0:d383e2dee0f7 746 * Create a new Span over the last @p count elements of the existing view.
ommpy 0:d383e2dee0f7 747 *
ommpy 0:d383e2dee0f7 748 * @param count The number of elements viewed by the new Span.
ommpy 0:d383e2dee0f7 749 *
ommpy 0:d383e2dee0f7 750 * @return A new Span over the last @p count elements.
ommpy 0:d383e2dee0f7 751 */
ommpy 0:d383e2dee0f7 752 Span<element_type, SPAN_DYNAMIC_EXTENT> last(index_type count) const
ommpy 0:d383e2dee0f7 753 {
ommpy 0:d383e2dee0f7 754 MBED_ASSERT(0 <= count && count <= _size);
ommpy 0:d383e2dee0f7 755 return Span<element_type, SPAN_DYNAMIC_EXTENT>(
ommpy 0:d383e2dee0f7 756 _data + (_size - count),
ommpy 0:d383e2dee0f7 757 count
ommpy 0:d383e2dee0f7 758 );
ommpy 0:d383e2dee0f7 759 }
ommpy 0:d383e2dee0f7 760
ommpy 0:d383e2dee0f7 761 /**
ommpy 0:d383e2dee0f7 762 * Create a subspan that is a view of other count elements; the view starts at
ommpy 0:d383e2dee0f7 763 * element offset.
ommpy 0:d383e2dee0f7 764 *
ommpy 0:d383e2dee0f7 765 * @param offset The offset of the first element viewed by the subspan.
ommpy 0:d383e2dee0f7 766 *
ommpy 0:d383e2dee0f7 767 * @param count The number of elements present in the subspan. If Count
ommpy 0:d383e2dee0f7 768 * is equal to SPAN_DYNAMIC_EXTENT, then a Span starting at offset and
ommpy 0:d383e2dee0f7 769 * containing the rest of the elements is returned.
ommpy 0:d383e2dee0f7 770 *
ommpy 0:d383e2dee0f7 771 * @return A subspan of this starting at offset and count long.
ommpy 0:d383e2dee0f7 772 */
ommpy 0:d383e2dee0f7 773 Span<element_type, SPAN_DYNAMIC_EXTENT> subspan(
ommpy 0:d383e2dee0f7 774 index_type offset, index_type count = SPAN_DYNAMIC_EXTENT
ommpy 0:d383e2dee0f7 775 ) const
ommpy 0:d383e2dee0f7 776 {
ommpy 0:d383e2dee0f7 777 MBED_ASSERT(0 <= offset && offset <= _size);
ommpy 0:d383e2dee0f7 778 MBED_ASSERT(
ommpy 0:d383e2dee0f7 779 (count == SPAN_DYNAMIC_EXTENT) ||
ommpy 0:d383e2dee0f7 780 (0 <= count && (count + offset) <= _size)
ommpy 0:d383e2dee0f7 781 );
ommpy 0:d383e2dee0f7 782 return Span<element_type, SPAN_DYNAMIC_EXTENT>(
ommpy 0:d383e2dee0f7 783 _data + offset,
ommpy 0:d383e2dee0f7 784 count == SPAN_DYNAMIC_EXTENT ? _size - offset : count
ommpy 0:d383e2dee0f7 785 );
ommpy 0:d383e2dee0f7 786 }
ommpy 0:d383e2dee0f7 787
ommpy 0:d383e2dee0f7 788 private:
ommpy 0:d383e2dee0f7 789 pointer _data;
ommpy 0:d383e2dee0f7 790 index_type _size;
ommpy 0:d383e2dee0f7 791 };
ommpy 0:d383e2dee0f7 792
ommpy 0:d383e2dee0f7 793 /**
ommpy 0:d383e2dee0f7 794 * Equality operator between two Span objects.
ommpy 0:d383e2dee0f7 795 *
ommpy 0:d383e2dee0f7 796 * @param lhs Left side of the binary operation.
ommpy 0:d383e2dee0f7 797 * @param rhs Right side of the binary operation.
ommpy 0:d383e2dee0f7 798 *
ommpy 0:d383e2dee0f7 799 * @return True if Spans in input have the same size and the same content and
ommpy 0:d383e2dee0f7 800 * false otherwise.
ommpy 0:d383e2dee0f7 801 *
ommpy 0:d383e2dee0f7 802 * @relates Span
ommpy 0:d383e2dee0f7 803 */
ommpy 0:d383e2dee0f7 804 template<typename T, typename U, ptrdiff_t LhsExtent, ptrdiff_t RhsExtent>
ommpy 0:d383e2dee0f7 805 bool operator==(const Span<T, LhsExtent> &lhs, const Span<U, RhsExtent> &rhs)
ommpy 0:d383e2dee0f7 806 {
ommpy 0:d383e2dee0f7 807 if (lhs.size() != rhs.size()) {
ommpy 0:d383e2dee0f7 808 return false;
ommpy 0:d383e2dee0f7 809 }
ommpy 0:d383e2dee0f7 810
ommpy 0:d383e2dee0f7 811 if (lhs.data() == rhs.data()) {
ommpy 0:d383e2dee0f7 812 return true;
ommpy 0:d383e2dee0f7 813 }
ommpy 0:d383e2dee0f7 814
ommpy 0:d383e2dee0f7 815 return std::equal(lhs.data(), lhs.data() + lhs.size(), rhs.data());
ommpy 0:d383e2dee0f7 816 }
ommpy 0:d383e2dee0f7 817
ommpy 0:d383e2dee0f7 818 // AStyle ignore, not handling correctly below
ommpy 0:d383e2dee0f7 819 // *INDENT-OFF*
ommpy 0:d383e2dee0f7 820 /**
ommpy 0:d383e2dee0f7 821 * Equality operation between a Span and a reference to a C++ array.
ommpy 0:d383e2dee0f7 822 *
ommpy 0:d383e2dee0f7 823 * @param lhs Left side of the binary operation.
ommpy 0:d383e2dee0f7 824 * @param rhs Right side of the binary operation.
ommpy 0:d383e2dee0f7 825 *
ommpy 0:d383e2dee0f7 826 * @return True if elements in input have the same size and the same content and
ommpy 0:d383e2dee0f7 827 * false otherwise.
ommpy 0:d383e2dee0f7 828 */
ommpy 0:d383e2dee0f7 829 template<typename T, ptrdiff_t LhsExtent, ptrdiff_t RhsExtent>
ommpy 0:d383e2dee0f7 830 bool operator==(const Span<T, LhsExtent> &lhs, T (&rhs)[RhsExtent])
ommpy 0:d383e2dee0f7 831 {
ommpy 0:d383e2dee0f7 832 return lhs == Span<T>(rhs);
ommpy 0:d383e2dee0f7 833 }
ommpy 0:d383e2dee0f7 834
ommpy 0:d383e2dee0f7 835 /**
ommpy 0:d383e2dee0f7 836 * Equality operation between a Span and a reference to a C++ array.
ommpy 0:d383e2dee0f7 837 *
ommpy 0:d383e2dee0f7 838 * @param lhs Left side of the binary operation.
ommpy 0:d383e2dee0f7 839 * @param rhs Right side of the binary operation.
ommpy 0:d383e2dee0f7 840 *
ommpy 0:d383e2dee0f7 841 * @return True if elements in input have the same size and the same content
ommpy 0:d383e2dee0f7 842 * and false otherwise.
ommpy 0:d383e2dee0f7 843 */
ommpy 0:d383e2dee0f7 844 template<typename T, ptrdiff_t LhsExtent, ptrdiff_t RhsExtent>
ommpy 0:d383e2dee0f7 845 bool operator==(T (&lhs)[LhsExtent], const Span<T, RhsExtent> &rhs)
ommpy 0:d383e2dee0f7 846 {
ommpy 0:d383e2dee0f7 847 return Span<T>(lhs) == rhs;
ommpy 0:d383e2dee0f7 848 }
ommpy 0:d383e2dee0f7 849
ommpy 0:d383e2dee0f7 850 /**
ommpy 0:d383e2dee0f7 851 * Not equal operator
ommpy 0:d383e2dee0f7 852 *
ommpy 0:d383e2dee0f7 853 * @param lhs Left side of the binary operation.
ommpy 0:d383e2dee0f7 854 * @param rhs Right side of the binary operation.
ommpy 0:d383e2dee0f7 855 *
ommpy 0:d383e2dee0f7 856 * @return True if arrays in input do not have the same size or the same content
ommpy 0:d383e2dee0f7 857 * and false otherwise.
ommpy 0:d383e2dee0f7 858 *
ommpy 0:d383e2dee0f7 859 * @relates Span
ommpy 0:d383e2dee0f7 860 */
ommpy 0:d383e2dee0f7 861 template<typename T, typename U, ptrdiff_t LhsExtent, ptrdiff_t RhsExtent>
ommpy 0:d383e2dee0f7 862 bool operator!=(const Span<T, LhsExtent> &lhs, const Span<U, RhsExtent> &rhs)
ommpy 0:d383e2dee0f7 863 {
ommpy 0:d383e2dee0f7 864 return !(lhs == rhs);
ommpy 0:d383e2dee0f7 865 }
ommpy 0:d383e2dee0f7 866
ommpy 0:d383e2dee0f7 867 /**
ommpy 0:d383e2dee0f7 868 * Not Equal operation between a Span and a reference to a C++ array.
ommpy 0:d383e2dee0f7 869 *
ommpy 0:d383e2dee0f7 870 * @param lhs Left side of the binary operation.
ommpy 0:d383e2dee0f7 871 * @param rhs Right side of the binary operation.
ommpy 0:d383e2dee0f7 872 *
ommpy 0:d383e2dee0f7 873 * @return True if elements in input have the same size and the same content
ommpy 0:d383e2dee0f7 874 * and false otherwise.
ommpy 0:d383e2dee0f7 875 */
ommpy 0:d383e2dee0f7 876 template<typename T, ptrdiff_t LhsExtent, ptrdiff_t RhsExtent>
ommpy 0:d383e2dee0f7 877 bool operator!=(const Span<T, LhsExtent> &lhs, T (&rhs)[RhsExtent])
ommpy 0:d383e2dee0f7 878 {
ommpy 0:d383e2dee0f7 879 return !(lhs == Span<T, RhsExtent>(rhs));
ommpy 0:d383e2dee0f7 880 }
ommpy 0:d383e2dee0f7 881
ommpy 0:d383e2dee0f7 882 /**
ommpy 0:d383e2dee0f7 883 * Not Equal operation between a Span and a reference to a C++ array.
ommpy 0:d383e2dee0f7 884 *
ommpy 0:d383e2dee0f7 885 * @param lhs Left side of the binary operation.
ommpy 0:d383e2dee0f7 886 * @param rhs Right side of the binary operation.
ommpy 0:d383e2dee0f7 887 *
ommpy 0:d383e2dee0f7 888 * @return True if elements in input have the same size and the same content
ommpy 0:d383e2dee0f7 889 * and false otherwise.
ommpy 0:d383e2dee0f7 890 */
ommpy 0:d383e2dee0f7 891 template<typename T, ptrdiff_t LhsExtent, ptrdiff_t RhsExtent>
ommpy 0:d383e2dee0f7 892 bool operator!=(T (&lhs)[LhsExtent], const Span<T, RhsExtent> &rhs)
ommpy 0:d383e2dee0f7 893 {
ommpy 0:d383e2dee0f7 894 return !(Span<T, LhsExtent>(lhs) == rhs);
ommpy 0:d383e2dee0f7 895 }
ommpy 0:d383e2dee0f7 896
ommpy 0:d383e2dee0f7 897 /**
ommpy 0:d383e2dee0f7 898 * Generate a Span from a reference to a C/C++ array.
ommpy 0:d383e2dee0f7 899 *
ommpy 0:d383e2dee0f7 900 * @tparam T Type of elements held in elements.
ommpy 0:d383e2dee0f7 901 * @tparam Extent Number of items held in elements.
ommpy 0:d383e2dee0f7 902 *
ommpy 0:d383e2dee0f7 903 * @param elements The reference to the array viewed.
ommpy 0:d383e2dee0f7 904 *
ommpy 0:d383e2dee0f7 905 * @return The Span to elements.
ommpy 0:d383e2dee0f7 906 *
ommpy 0:d383e2dee0f7 907 * @note This helper avoids the typing of template parameter when Span is
ommpy 0:d383e2dee0f7 908 * created 'inline'.
ommpy 0:d383e2dee0f7 909 *
ommpy 0:d383e2dee0f7 910 * @relates Span
ommpy 0:d383e2dee0f7 911 */
ommpy 0:d383e2dee0f7 912 template<typename T, size_t Size>
ommpy 0:d383e2dee0f7 913 Span<T, Size> make_Span(T (&elements)[Size])
ommpy 0:d383e2dee0f7 914 {
ommpy 0:d383e2dee0f7 915 return Span<T, Size>(elements);
ommpy 0:d383e2dee0f7 916 }
ommpy 0:d383e2dee0f7 917
ommpy 0:d383e2dee0f7 918 /**
ommpy 0:d383e2dee0f7 919 * Generate a Span from a pointer to a C/C++ array.
ommpy 0:d383e2dee0f7 920 *
ommpy 0:d383e2dee0f7 921 * @tparam Extent Number of items held in elements.
ommpy 0:d383e2dee0f7 922 * @tparam T Type of elements held in elements.
ommpy 0:d383e2dee0f7 923 *
ommpy 0:d383e2dee0f7 924 * @param elements The reference to the array viewed.
ommpy 0:d383e2dee0f7 925 *
ommpy 0:d383e2dee0f7 926 * @return The Span to elements.
ommpy 0:d383e2dee0f7 927 *
ommpy 0:d383e2dee0f7 928 * @note This helper avoids the typing of template parameter when Span is
ommpy 0:d383e2dee0f7 929 * created 'inline'.
ommpy 0:d383e2dee0f7 930 */
ommpy 0:d383e2dee0f7 931 template<ptrdiff_t Extent, typename T>
ommpy 0:d383e2dee0f7 932 Span<T, Extent> make_Span(T *elements)
ommpy 0:d383e2dee0f7 933 {
ommpy 0:d383e2dee0f7 934 return Span<T, Extent>(elements, Extent);
ommpy 0:d383e2dee0f7 935 }
ommpy 0:d383e2dee0f7 936
ommpy 0:d383e2dee0f7 937 /**
ommpy 0:d383e2dee0f7 938 * Generate a Span from a C/C++ pointer and the size of the array.
ommpy 0:d383e2dee0f7 939 *
ommpy 0:d383e2dee0f7 940 * @tparam T Type of elements held in array_ptr.
ommpy 0:d383e2dee0f7 941 *
ommpy 0:d383e2dee0f7 942 * @param array_ptr The pointer to the array viewed.
ommpy 0:d383e2dee0f7 943 * @param array_size The number of T elements in the array.
ommpy 0:d383e2dee0f7 944 *
ommpy 0:d383e2dee0f7 945 * @return The Span to array_ptr with a size of array_size.
ommpy 0:d383e2dee0f7 946 *
ommpy 0:d383e2dee0f7 947 * @note This helper avoids the typing of template parameter when Span is
ommpy 0:d383e2dee0f7 948 * created 'inline'.
ommpy 0:d383e2dee0f7 949 *
ommpy 0:d383e2dee0f7 950 * @relates Span
ommpy 0:d383e2dee0f7 951 */
ommpy 0:d383e2dee0f7 952 template<typename T>
ommpy 0:d383e2dee0f7 953 Span<T> make_Span(T *array_ptr, ptrdiff_t array_size)
ommpy 0:d383e2dee0f7 954 {
ommpy 0:d383e2dee0f7 955 return Span<T>(array_ptr, array_size);
ommpy 0:d383e2dee0f7 956 }
ommpy 0:d383e2dee0f7 957
ommpy 0:d383e2dee0f7 958 /**
ommpy 0:d383e2dee0f7 959 * Generate a Span to a const content from a reference to a C/C++ array.
ommpy 0:d383e2dee0f7 960 *
ommpy 0:d383e2dee0f7 961 * @tparam T Type of elements held in elements.
ommpy 0:d383e2dee0f7 962 * @tparam Extent Number of items held in elements.
ommpy 0:d383e2dee0f7 963 *
ommpy 0:d383e2dee0f7 964 * @param elements The array viewed.
ommpy 0:d383e2dee0f7 965 * @return The Span to elements.
ommpy 0:d383e2dee0f7 966 *
ommpy 0:d383e2dee0f7 967 * @note This helper avoids the typing of template parameter when Span is
ommpy 0:d383e2dee0f7 968 * created 'inline'.
ommpy 0:d383e2dee0f7 969 */
ommpy 0:d383e2dee0f7 970 template<typename T, size_t Extent>
ommpy 0:d383e2dee0f7 971 Span<const T, Extent> make_const_Span(const T (&elements)[Extent])
ommpy 0:d383e2dee0f7 972 {
ommpy 0:d383e2dee0f7 973 return Span<const T, Extent>(elements);
ommpy 0:d383e2dee0f7 974 }
ommpy 0:d383e2dee0f7 975 // *INDENT-ON*
ommpy 0:d383e2dee0f7 976 /**
ommpy 0:d383e2dee0f7 977 * Generate a Span to a const content from a pointer to a C/C++ array.
ommpy 0:d383e2dee0f7 978 *
ommpy 0:d383e2dee0f7 979 * @tparam Extent Number of items held in elements.
ommpy 0:d383e2dee0f7 980 * @tparam T Type of elements held in elements.
ommpy 0:d383e2dee0f7 981 *
ommpy 0:d383e2dee0f7 982 * @param elements The reference to the array viewed.
ommpy 0:d383e2dee0f7 983 *
ommpy 0:d383e2dee0f7 984 * @return The Span to elements.
ommpy 0:d383e2dee0f7 985 *
ommpy 0:d383e2dee0f7 986 * @note This helper avoids the typing of template parameter when Span is
ommpy 0:d383e2dee0f7 987 * created 'inline'.
ommpy 0:d383e2dee0f7 988 *
ommpy 0:d383e2dee0f7 989 * @relates Span
ommpy 0:d383e2dee0f7 990 */
ommpy 0:d383e2dee0f7 991 template<size_t Extent, typename T>
ommpy 0:d383e2dee0f7 992 Span<const T, Extent> make_const_Span(const T *elements)
ommpy 0:d383e2dee0f7 993 {
ommpy 0:d383e2dee0f7 994 return Span<const T, Extent>(elements, Extent);
ommpy 0:d383e2dee0f7 995 }
ommpy 0:d383e2dee0f7 996
ommpy 0:d383e2dee0f7 997 /**
ommpy 0:d383e2dee0f7 998 * Generate a Span to a const content from a C/C++ pointer and the size of the
ommpy 0:d383e2dee0f7 999 * array.
ommpy 0:d383e2dee0f7 1000 *
ommpy 0:d383e2dee0f7 1001 * @tparam T Type of elements held in array_ptr.
ommpy 0:d383e2dee0f7 1002 *
ommpy 0:d383e2dee0f7 1003 * @param array_ptr The pointer to the array to viewed.
ommpy 0:d383e2dee0f7 1004 * @param array_size The number of T elements in the array.
ommpy 0:d383e2dee0f7 1005 *
ommpy 0:d383e2dee0f7 1006 * @return The Span to array_ptr with a size of array_size.
ommpy 0:d383e2dee0f7 1007 *
ommpy 0:d383e2dee0f7 1008 * @note This helper avoids the typing of template parameter when Span is
ommpy 0:d383e2dee0f7 1009 * created 'inline'.
ommpy 0:d383e2dee0f7 1010 *
ommpy 0:d383e2dee0f7 1011 * @relates Span
ommpy 0:d383e2dee0f7 1012 */
ommpy 0:d383e2dee0f7 1013 template<typename T>
ommpy 0:d383e2dee0f7 1014 Span<const T> make_const_Span(T *array_ptr, size_t array_size)
ommpy 0:d383e2dee0f7 1015 {
ommpy 0:d383e2dee0f7 1016 return Span<const T>(array_ptr, array_size);
ommpy 0:d383e2dee0f7 1017 }
ommpy 0:d383e2dee0f7 1018
ommpy 0:d383e2dee0f7 1019 /**@}*/
ommpy 0:d383e2dee0f7 1020
ommpy 0:d383e2dee0f7 1021 /**@}*/
ommpy 0:d383e2dee0f7 1022
ommpy 0:d383e2dee0f7 1023 } // namespace mbed
ommpy 0:d383e2dee0f7 1024
ommpy 0:d383e2dee0f7 1025 #endif /* MBED_PLATFORM_SPAN_H_ */