Device interface library for multiple platforms including Mbed.

Dependents:   DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers span.hpp Source File

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