Device interface library for multiple platforms including Mbed.
Dependents: DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#
span.hpp
00001 /******************************************************************************* 00002 * Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved. 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a 00005 * copy of this software and associated documentation files (the "Software"), 00006 * to deal in the Software without restriction, including without limitation 00007 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00008 * and/or sell copies of the Software, and to permit persons to whom the 00009 * Software is furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included 00012 * in all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00015 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 00017 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES 00018 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 00019 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 00020 * OTHER DEALINGS IN THE SOFTWARE. 00021 * 00022 * Except as contained in this notice, the name of Maxim Integrated 00023 * Products, Inc. shall not be used except as stated in the Maxim Integrated 00024 * Products, Inc. Branding Policy. 00025 * 00026 * The mere transfer of this software does not imply any licenses 00027 * of trade secrets, proprietary technology, copyrights, patents, 00028 * trademarks, maskwork rights, or any other form of intellectual 00029 * property whatsoever. Maxim Integrated Products, Inc. retains all 00030 * ownership rights. 00031 *******************************************************************************/ 00032 00033 #ifndef MaximInterfaceCore_span_hpp 00034 #define MaximInterfaceCore_span_hpp 00035 00036 #include <stddef.h> 00037 #include <iterator> 00038 #include <vector> 00039 #include "array.hpp" 00040 #include "type_traits.hpp" 00041 00042 namespace MaximInterfaceCore { 00043 00044 /// Differentiates spans of static and dynamic extent. 00045 static const size_t dynamic_extent = static_cast<size_t>(-1); // SIZE_MAX 00046 00047 /// @brief 00048 /// Generic memory span class similar to gsl::span and the proposed std::span. 00049 /// @note 00050 /// Separate implementations are used for spans of static and dynamic extent. 00051 template <typename T, size_t Extent = dynamic_extent> class span; 00052 00053 namespace detail { 00054 00055 // Implementation of common span functionality using CRTP. 00056 template <template <typename, size_t = MaximInterfaceCore::dynamic_extent> 00057 class span, 00058 typename T, size_t Extent> 00059 class span_base { 00060 public: 00061 typedef T element_type; 00062 typedef typename remove_cv<element_type>::type value_type; 00063 typedef size_t index_type; 00064 typedef ptrdiff_t difference_type; 00065 typedef element_type * pointer; 00066 typedef const element_type * const_pointer; 00067 typedef element_type & reference; 00068 typedef const element_type & const_reference; 00069 typedef element_type * iterator; 00070 typedef const element_type * const_iterator; 00071 typedef std::reverse_iterator<iterator> reverse_iterator; 00072 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00073 00074 static const index_type extent = Extent; 00075 00076 protected: 00077 span_base(pointer data) : data_(data) {} 00078 ~span_base() {} 00079 00080 public: 00081 /// @name Iterators 00082 /// @{ 00083 00084 iterator begin() const { return data(); } 00085 00086 const_iterator cbegin() const { return begin(); } 00087 00088 iterator end() const { return begin() + size(); } 00089 00090 const_iterator cend() const { return end(); } 00091 00092 reverse_iterator rbegin() const { return reverse_iterator(end()); } 00093 00094 const_reverse_iterator crbegin() const { 00095 return const_reverse_iterator(cend()); 00096 } 00097 00098 reverse_iterator rend() const { return reverse_iterator(begin()); } 00099 00100 const_reverse_iterator crend() const { 00101 return const_reverse_iterator(cbegin()); 00102 } 00103 00104 /// @} 00105 00106 /// @name Element access 00107 /// @{ 00108 00109 reference front() const { return operator[](0); } 00110 00111 reference back() const { return operator[](size() - 1); } 00112 00113 reference operator[](index_type idx) const { return data()[idx]; } 00114 00115 pointer data() const { return data_; } 00116 00117 /// @} 00118 00119 /// @name Subviews 00120 /// @{ 00121 00122 template <index_type Count> span<element_type, Count> first() const { 00123 return subspan<0, Count>(); 00124 } 00125 00126 span<element_type> first(index_type Count) const { return subspan(0, Count); } 00127 00128 span<element_type> last(index_type Count) const { 00129 return subspan(size() - Count, Count); 00130 } 00131 00132 template <index_type Offset, index_type Count> 00133 span<element_type, Count> subspan() const { 00134 return span<element_type, Count>(data() + Offset, Count); 00135 } 00136 00137 span<element_type> subspan(index_type Offset, 00138 index_type Count = dynamic_extent) const { 00139 return span<element_type>( 00140 data() + Offset, Count == dynamic_extent ? size() - Offset : Count); 00141 } 00142 00143 /// @} 00144 00145 private: 00146 index_type size() const { 00147 return static_cast<const span<T, Extent> &>(*this).size(); 00148 } 00149 00150 pointer data_; 00151 }; 00152 00153 template <template <typename, size_t> class span, typename T, size_t Extent> 00154 const typename span_base<span, T, Extent>::index_type 00155 span_base<span, T, Extent>::extent; 00156 00157 template <typename T> class has_data { 00158 typedef char true_type[1]; 00159 typedef char false_type[2]; 00160 00161 template <typename U, U> struct check; 00162 00163 template <typename U> 00164 static true_type & test(check<typename U::pointer (U::*)(), &U::data> *); 00165 00166 template <typename> static false_type & test(...); 00167 00168 public: 00169 static const bool value = (sizeof(test<T>(NULL)) == sizeof(true_type)); 00170 }; 00171 00172 template <typename T> class has_data<const T> { 00173 typedef char true_type[1]; 00174 typedef char false_type[2]; 00175 00176 template <typename U, U> struct check; 00177 00178 template <typename U> 00179 static true_type & 00180 test(check<typename U::const_pointer (U::*)() const, &U::data> *); 00181 00182 template <typename> static false_type & test(...); 00183 00184 public: 00185 static const bool value = (sizeof(test<T>(NULL)) == sizeof(true_type)); 00186 }; 00187 00188 template <typename T> class has_size { 00189 typedef char true_type[1]; 00190 typedef char false_type[2]; 00191 00192 template <typename U, U> struct check; 00193 00194 template <typename U> 00195 static true_type & 00196 test(check<typename U::size_type (U::*)() const, &U::size> *); 00197 00198 // Additionally support a static member function. 00199 template <typename U> 00200 static true_type & test(check<typename U::size_type (*)(), &U::size> *); 00201 00202 template <typename> static false_type & test(...); 00203 00204 public: 00205 static const bool value = (sizeof(test<T>(NULL)) == sizeof(true_type)); 00206 }; 00207 00208 template <typename T> struct is_array_class_helper : false_type {}; 00209 00210 template <typename T, size_t N> 00211 struct is_array_class_helper<array<T, N> > : true_type {}; 00212 00213 template <typename T> 00214 struct is_array_class : is_array_class_helper<typename remove_cv<T>::type> {}; 00215 00216 template <typename T> struct is_span_helper : false_type {}; 00217 00218 template <typename T, size_t Extent> 00219 struct is_span_helper<span<T, Extent> > : true_type {}; 00220 00221 template <typename T> 00222 struct is_span : is_span_helper<typename remove_cv<T>::type> {}; 00223 00224 template <typename T> struct is_vector_helper : false_type {}; 00225 00226 template <typename T, typename Allocator> 00227 struct is_vector_helper<std::vector<T, Allocator> > : true_type {}; 00228 00229 template <typename T> 00230 struct is_vector : is_vector_helper<typename remove_cv<T>::type> {}; 00231 00232 // Used to disable the span container constructors. 00233 template <typename T> 00234 struct enable_if_span_convertible 00235 : enable_if<has_data<T>::value && has_size<T>::value && 00236 !(is_array_class<T>::value || is_span<T>::value || 00237 is_vector<T>::value)> {}; 00238 00239 } // namespace detail 00240 00241 // Implementation of the static extent span. 00242 template <typename T, size_t Extent> 00243 class span : public detail::span_base<MaximInterfaceCore::span, T, Extent> { 00244 typedef detail::span_base<MaximInterfaceCore::span, T, Extent> span_base; 00245 00246 public: 00247 using span_base::extent; 00248 using typename span_base::element_type; 00249 using typename span_base::index_type; 00250 using typename span_base::pointer; 00251 using typename span_base::value_type; 00252 00253 span(pointer data, index_type) : span_base(data) {} 00254 00255 span(pointer begin, pointer) : span_base(begin) {} 00256 00257 span(element_type (&arr)[extent]) : span_base(arr) {} 00258 00259 span(array<value_type, extent> & arr) : span_base(arr.data()) {} 00260 00261 span(const array<value_type, extent> & arr) : span_base(arr.data()) {} 00262 00263 template <typename U> span(const span<U, extent> & s) : span_base(s.data()) {} 00264 00265 template <typename Allocator> 00266 span(std::vector<value_type, Allocator> & vec) : span_base(&vec.front()) {} 00267 00268 template <typename Allocator> 00269 span(const std::vector<value_type, Allocator> & vec) 00270 : span_base(&vec.front()) {} 00271 00272 template <typename Container> 00273 span(Container & cont, 00274 typename detail::enable_if_span_convertible<Container>::type * = NULL) 00275 : span_base(cont.data()) {} 00276 00277 template <typename Container> 00278 span(const Container & cont, 00279 typename detail::enable_if_span_convertible<const Container>::type * = 00280 NULL) 00281 : span_base(cont.data()) {} 00282 00283 /// @name Observers 00284 /// @{ 00285 00286 static index_type size() { return extent; } 00287 00288 static index_type size_bytes() { return size() * sizeof(element_type); } 00289 00290 static bool empty() { return size() == 0; } 00291 00292 /// @} 00293 00294 /// @name Subviews 00295 /// @{ 00296 00297 template <index_type Count> span<element_type, Count> last() const { 00298 return this->template subspan<extent - Count, Count>(); 00299 } 00300 00301 using span_base::last; 00302 00303 /// @} 00304 }; 00305 00306 // Implementation of the dynamic extent span. 00307 template <typename T> 00308 class span<T, dynamic_extent> 00309 : public detail::span_base<MaximInterfaceCore::span, T, dynamic_extent> { 00310 typedef detail::span_base<MaximInterfaceCore::span, T, dynamic_extent> 00311 span_base; 00312 00313 public: 00314 using typename span_base::element_type; 00315 using typename span_base::index_type; 00316 using typename span_base::pointer; 00317 using typename span_base::value_type; 00318 00319 span() : span_base(NULL), size_(0) {} 00320 00321 span(pointer data, index_type size) : span_base(data), size_(size) {} 00322 00323 span(pointer begin, pointer end) : span_base(begin), size_(end - begin) {} 00324 00325 template <size_t N> span(element_type (&arr)[N]) : span_base(arr), size_(N) {} 00326 00327 template <size_t N> 00328 span(array<value_type, N> & arr) : span_base(arr.data()), size_(N) {} 00329 00330 template <size_t N> 00331 span(const array<value_type, N> & arr) : span_base(arr.data()), size_(N) {} 00332 00333 template <typename U, size_t N> 00334 span(const span<U, N> & s) : span_base(s.data()), size_(s.size()) {} 00335 00336 template <typename Allocator> 00337 span(std::vector<value_type, Allocator> & vec) 00338 : span_base(vec.empty() ? NULL : &vec.front()), size_(vec.size()) {} 00339 00340 template <typename Allocator> 00341 span(const std::vector<value_type, Allocator> & vec) 00342 : span_base(vec.empty() ? NULL : &vec.front()), size_(vec.size()) {} 00343 00344 template <typename Container> 00345 span(Container & cont, 00346 typename detail::enable_if_span_convertible<Container>::type * = NULL) 00347 : span_base(cont.data()), size_(cont.size()) {} 00348 00349 template <typename Container> 00350 span(const Container & cont, 00351 typename detail::enable_if_span_convertible<const Container>::type * = 00352 NULL) 00353 : span_base(cont.data()), size_(cont.size()) {} 00354 00355 /// @name Observers 00356 /// @{ 00357 00358 index_type size() const { return size_; } 00359 00360 index_type size_bytes() const { return size() * sizeof(element_type); } 00361 00362 bool empty() const { return size() == 0; } 00363 00364 /// @} 00365 00366 /// @name Subviews 00367 /// @{ 00368 00369 template <index_type Count> span<element_type, Count> last() const { 00370 return span<element_type, Count>(this->data() + (size() - Count), Count); 00371 } 00372 00373 using span_base::last; 00374 00375 /// @} 00376 00377 private: 00378 index_type size_; 00379 }; 00380 00381 template <typename T> 00382 span<T> make_span(T * data, typename span<T>::index_type size) { 00383 return span<T>(data, size); 00384 } 00385 00386 template <typename T> span<T> make_span(T * begin, T * end) { 00387 return span<T>(begin, end); 00388 } 00389 00390 template <typename T, size_t N> span<T, N> make_span(T (&arr)[N]) { 00391 return span<T, N>(arr); 00392 } 00393 00394 template <typename T, size_t N> span<T, N> make_span(array<T, N> & arr) { 00395 return arr; 00396 } 00397 00398 template <typename T, size_t N> 00399 span<const T, N> make_span(const array<T, N> & arr) { 00400 return arr; 00401 } 00402 00403 template <typename Container> 00404 span<typename Container::value_type> make_span(Container & cont) { 00405 return cont; 00406 } 00407 00408 template <typename Container> 00409 span<const typename Container::value_type> make_span(const Container & cont) { 00410 return cont; 00411 } 00412 00413 } // namespace MaximInterfaceCore 00414 00415 #endif
Generated on Tue Jul 12 2022 11:13:17 by 1.7.2