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

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.