Aleksandrs Gumenuks / MaximInterface_Extended

Dependents:   mbed_DS28EC20_GPIO

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers span.hpp Source File

span.hpp

00001 /*******************************************************************************
00002 * Copyright (C) 2018 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 MaximInterface_span
00034 #define MaximInterface_span
00035 
00036 #include <stddef.h>
00037 #include <algorithm>
00038 #include <iterator>
00039 #include <vector>
00040 #include "array.hpp"
00041 #include "type_traits.hpp"
00042 
00043 namespace MaximInterface {
00044 
00045 static const ptrdiff_t dynamic_extent = -1;
00046 
00047 struct with_container_t {
00048   explicit with_container_t(int) {}
00049 };
00050 
00051 static const with_container_t with_container(0);
00052 
00053 namespace detail {
00054 
00055 template <template <typename, ptrdiff_t = MaximInterface::dynamic_extent>
00056           class span,
00057           typename T, ptrdiff_t Extent>
00058 class span_base {
00059 public:
00060   typedef T element_type;
00061   typedef typename remove_cv<element_type>::type value_type;
00062   typedef ptrdiff_t index_type;
00063   typedef ptrdiff_t difference_type;
00064   typedef element_type * pointer;
00065   typedef element_type & reference;
00066   typedef element_type * iterator;
00067   typedef const element_type * const_iterator;
00068   typedef std::reverse_iterator<iterator> reverse_iterator;
00069   typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00070 
00071   static const index_type extent = Extent;
00072 
00073 protected:
00074   span_base(pointer data) : data_(data) {}
00075   ~span_base() {}
00076 
00077 public:
00078   /// @name Iterators
00079   /// @{
00080   
00081   iterator begin() const {
00082     return const_cast<iterator>(static_cast<const span_base &>(*this).cbegin());
00083   }
00084   
00085   const_iterator cbegin() const { return data(); }
00086   
00087   iterator end() const {
00088     return const_cast<iterator>(static_cast<const span_base &>(*this).cend());
00089   }
00090   
00091   const_iterator cend() const { return cbegin() + size(); }
00092   
00093   reverse_iterator rbegin() const { return reverse_iterator(end()); }
00094   
00095   const_reverse_iterator crbegin() const {
00096     return const_reverse_iterator(cend());
00097   }
00098   
00099   reverse_iterator rend() const { return reverse_iterator(begin()); }
00100   
00101   const_reverse_iterator crend() const {
00102     return const_reverse_iterator(cbegin());
00103   }
00104   
00105   /// @}
00106 
00107   /// @name Element access
00108   /// @{
00109   
00110   reference operator[](index_type idx) const { return data()[idx]; }
00111   
00112   reference operator()(index_type idx) const { return operator[](idx); }
00113   
00114   pointer data() const { return data_; }
00115   
00116   /// @}
00117 
00118   /// @name Subviews
00119   /// @{
00120   
00121   template <index_type Count> span<element_type, Count> first() const {
00122     return subspan<0, Count>();
00123   }
00124   
00125   span<element_type> first(index_type Count) const { return subspan(0, Count); }
00126   
00127   span<element_type> last(index_type Count) const {
00128     return subspan(size() - Count, Count);
00129   }
00130   
00131   template <index_type Offset, index_type Count>
00132   span<element_type, Count> subspan() const {
00133     return span<element_type, Count>(data() + Offset, Count);
00134   }
00135   
00136   span<element_type> subspan(index_type Offset,
00137                              index_type Count = dynamic_extent) const {
00138     return span<element_type>(
00139         data() + Offset, Count == dynamic_extent ? size() - Offset : Count);
00140   }
00141   
00142   /// @}
00143 
00144 private:
00145   index_type size() const {
00146     return static_cast<const span<T, Extent> &>(*this).size();
00147   }
00148 
00149   pointer data_;
00150 };
00151 
00152 } // namespace detail
00153 
00154 /// Generic memory span class similar to gsl::span or the proposed std::span.
00155 template <typename T, ptrdiff_t Extent = dynamic_extent>
00156 class span : public detail::span_base<MaximInterface::span, T, Extent> {
00157   typedef detail::span_base<MaximInterface::span, T, Extent> span_base;
00158 
00159 public:
00160   using span_base::extent;
00161   using typename span_base::element_type;
00162   using typename span_base::index_type;
00163   using typename span_base::pointer;
00164   using typename span_base::value_type;
00165 
00166   span(pointer data, index_type) : span_base(data) {}
00167   
00168   span(pointer begin, pointer) : span_base(begin) {}
00169   
00170   span(element_type (&arr)[extent]) : span_base(arr) {}
00171   
00172   span(array<value_type, extent> & arr) : span_base(arr.data()) {}
00173   
00174   span(const array<value_type, extent> & arr) : span_base(arr.data()) {}
00175   
00176   template <typename U> span(const span<U, extent> & s) : span_base(s.data()) {}
00177   
00178   template <typename Allocator>
00179   explicit span(std::vector<value_type, Allocator> & vec)
00180       : span_base(&vec.front()) {}
00181       
00182   template <typename Allocator>
00183   explicit span(const std::vector<value_type, Allocator> & vec)
00184       : span_base(&vec.front()) {}
00185       
00186   template <typename Container>
00187   span(with_container_t, Container & cont) : span_base(cont.data()) {}
00188   
00189   template <typename Container>
00190   span(with_container_t, const Container & cont) : span_base(cont.data()) {}
00191 
00192   /// @name Observers
00193   /// @{
00194   
00195   static index_type size() { return extent; }
00196   
00197   static index_type size_bytes() { return size() * sizeof(element_type); }
00198   
00199   static bool empty() { return size() == 0; }
00200   
00201   /// @}
00202 
00203   /// @name Subviews
00204   /// @{
00205   
00206   template <index_type Count> span<element_type, Count> last() const {
00207     return this->template subspan<extent - Count, Count>();
00208   }
00209   
00210   /// @}
00211 };
00212 
00213 template <typename T>
00214 class span<T, dynamic_extent>
00215     : public detail::span_base<MaximInterface::span, T, dynamic_extent> {
00216   typedef detail::span_base<MaximInterface::span, T, dynamic_extent> span_base;
00217 
00218 public:
00219   using typename span_base::element_type;
00220   using typename span_base::index_type;
00221   using typename span_base::pointer;
00222   using typename span_base::value_type;
00223 
00224   span() : span_base(NULL), size_(0) {}
00225   
00226   span(pointer data, index_type size) : span_base(data), size_(size) {}
00227   
00228   span(pointer begin, pointer end) : span_base(begin), size_(end - begin) {}
00229   
00230   template <size_t N> span(element_type (&arr)[N]) : span_base(arr), size_(N) {}
00231   
00232   template <size_t N>
00233   span(array<value_type, N> & arr) : span_base(arr.data()), size_(N) {}
00234   
00235   template <size_t N>
00236   span(const array<value_type, N> & arr) : span_base(arr.data()), size_(N) {}
00237   
00238   template <typename U, ptrdiff_t N>
00239   span(const span<U, N> & s) : span_base(s.data()), size_(s.size()) {}
00240   
00241   template <typename Allocator>
00242   span(std::vector<value_type, Allocator> & vec)
00243       : span_base(vec.empty() ? NULL : &vec.front()), size_(vec.size()) {}
00244       
00245   template <typename Allocator>
00246   span(const std::vector<value_type, Allocator> & vec)
00247       : span_base(vec.empty() ? NULL : &vec.front()), size_(vec.size()) {}
00248       
00249   template <typename Container>
00250   span(with_container_t, Container & cont)
00251       : span_base(cont.data()), size_(cont.size()) {}
00252       
00253   template <typename Container>
00254   span(with_container_t, const Container & cont)
00255       : span_base(cont.data()), size_(cont.size()) {}
00256 
00257   /// @name Observers
00258   /// @{
00259   
00260   index_type size() const { return size_; }
00261   
00262   index_type size_bytes() const { return size() * sizeof(element_type); }
00263   
00264   bool empty() const { return size() == 0; }
00265   
00266   /// @}
00267 
00268   /// @name Subviews
00269   /// @{
00270   
00271   template <index_type Count> span<element_type, Count> last() const {
00272     return span<element_type, Count>(this->data() + (size() - Count), Count);
00273   }
00274   
00275   /// @}
00276 
00277 private:
00278   index_type size_;
00279 };
00280 
00281 template <typename T, ptrdiff_t Extent, typename U>
00282 bool operator==(span<T, Extent> lhs, span<U, Extent> rhs) {
00283   return lhs.size() == rhs.size() &&
00284          std::equal(lhs.begin(), lhs.end(), rhs.begin());
00285 }
00286 
00287 template <typename T, ptrdiff_t Extent, typename U>
00288 bool operator!=(span<T, Extent> lhs, span<U, Extent> rhs) {
00289   return !operator==(lhs, rhs);
00290 }
00291 
00292 template <typename T, ptrdiff_t Extent, typename U>
00293 bool operator<(span<T, Extent> lhs, span<U, Extent> rhs) {
00294   return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(),
00295                                       rhs.end());
00296 }
00297 
00298 template <typename T, ptrdiff_t Extent, typename U>
00299 bool operator>(span<T, Extent> lhs, span<U, Extent> rhs) {
00300   return operator<(rhs, lhs);
00301 }
00302 
00303 template <typename T, ptrdiff_t Extent, typename U>
00304 bool operator<=(span<T, Extent> lhs, span<U, Extent> rhs) {
00305   return !operator>(lhs, rhs);
00306 }
00307 
00308 template <typename T, ptrdiff_t Extent, typename U>
00309 bool operator>=(span<T, Extent> lhs, span<U, Extent> rhs) {
00310   return !operator<(lhs, rhs);
00311 }
00312 
00313 template <typename T>
00314 span<T> make_span(T * data, typename span<T>::index_type size) {
00315   return span<T>(data, size);
00316 }
00317 
00318 template <typename T> span<T> make_span(T * begin, T * end) {
00319   return span<T>(begin, end);
00320 }
00321 
00322 template <typename T, size_t N> span<T, N> make_span(T (&arr)[N]) {
00323   return span<T, N>(arr);
00324 }
00325 
00326 template <typename T, size_t N> span<T, N> make_span(array<T, N> & arr) {
00327   return arr;
00328 }
00329 
00330 template <typename T, size_t N>
00331 span<const T, N> make_span(const array<T, N> & arr) {
00332   return arr;
00333 }
00334 
00335 template <typename T, typename Allocator>
00336 span<T> make_span(std::vector<T, Allocator> & vec) {
00337   return vec;
00338 }
00339 
00340 template <typename T, typename Allocator>
00341 span<const T> make_span(const std::vector<T, Allocator> & vec) {
00342   return vec;
00343 }
00344 
00345 template <typename Container>
00346 span<typename Container::value_type> make_span(with_container_t,
00347                                                Container & cont) {
00348   return span<typename Container::value_type>(with_container, cont);
00349 }
00350 
00351 template <typename Container>
00352 span<const typename Container::value_type> make_span(with_container_t,
00353                                                      const Container & cont) {
00354   return span<const typename Container::value_type>(with_container, cont);
00355 }
00356 
00357 /// Deep copy between static spans of the same size.
00358 template <typename T, ptrdiff_t Extent, typename U>
00359 typename enable_if<Extent != dynamic_extent>::type copy(span<T, Extent> src,
00360                                                         span<U, Extent> dst) {
00361   std::copy(src.begin(), src.end(), dst.begin());
00362 }
00363 
00364 } // namespace MaximInterface
00365 
00366 #endif