Device interface library for multiple platforms including Mbed.

Dependents:   DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#

Maxim Interface is a library framework focused on providing flexible and expressive hardware interfaces. Both communication interfaces such as I2C and 1-Wire and device interfaces such as DS18B20 are supported. Modern C++ concepts are used extensively while keeping compatibility with C++98/C++03 and requiring no external dependencies. The embedded-friendly design does not depend on exceptions or RTTI.

The full version of the project is hosted on GitLab: https://gitlab.com/iabenz/MaximInterface

Revision:
8:5ea891c7d1a1
Parent:
7:9cd16581b578
Child:
10:947d3f44e0a0
--- a/MaximInterfaceCore/span.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/span.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,11 +30,10 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_span
-#define MaximInterfaceCore_span
+#ifndef MaximInterfaceCore_span_hpp
+#define MaximInterfaceCore_span_hpp
 
 #include <stddef.h>
-#include <stdint.h>
 #include <iterator>
 #include <vector>
 #include "array.hpp"
@@ -43,7 +42,7 @@
 namespace MaximInterfaceCore {
 
 /// Differentiates spans of static and dynamic extent.
-static const size_t dynamic_extent = SIZE_MAX;
+static const size_t dynamic_extent = static_cast<size_t>(-1); // SIZE_MAX
 
 /// @brief
 /// Generic memory span class similar to gsl::span and the proposed std::span.
@@ -155,11 +154,60 @@
   pointer data_;
 };
 
-template <typename T> struct is_array : false_type {};
+template <template <typename, size_t> class span, typename T, size_t Extent>
+const typename span_base<span, T, Extent>::index_type
+    span_base<span, T, Extent>::extent;
+
+template <typename T> class has_data {
+  typedef char true_type[1];
+  typedef char false_type[2];
+
+  template <typename U, U> struct check;
+
+  template <typename U>
+  static true_type & test(check<typename U::pointer (U::*)(), &U::data> *);
+
+  template <typename> static false_type & test(...);
+
+public:
+  static const bool value = (sizeof(test<T>(NULL)) == sizeof(true_type));
+};
+
+template <typename T> class has_data<const T> {
+  typedef char true_type[1];
+  typedef char false_type[2];
+
+  template <typename U, U> struct check;
 
-template <typename T> struct is_array<T[]> : true_type {};
+  template <typename U>
+  static true_type &
+  test(check<typename U::const_pointer (U::*)() const, &U::data> *);
+
+  template <typename> static false_type & test(...);
+
+public:
+  static const bool value = (sizeof(test<T>(NULL)) == sizeof(true_type));
+};
+
+template <typename T> class has_size {
+  typedef char true_type[1];
+  typedef char false_type[2];
 
-template <typename T, size_t N> struct is_array<T[N]> : true_type {};
+  template <typename U, U> struct check;
+
+  template <typename U>
+  static true_type &
+  test(check<typename U::size_type (U::*)() const, &U::size> *);
+
+  // Additionally support a static member function.
+  template <typename U>
+  static true_type & test(check<typename U::size_type (*)(), &U::size> *);
+
+  template <typename> static false_type & test(...);
+
+public:
+  static const bool value = (sizeof(test<T>(NULL)) == sizeof(true_type));
+};
 
 template <typename T> struct is_array_class_helper : false_type {};
 
@@ -185,16 +233,11 @@
 template <typename T>
 struct is_vector : is_vector_helper<typename remove_cv<T>::type> {};
 
-// Used by the static extent span to disable the container constructors.
+// Used to disable the span container constructors.
 template <typename T>
-struct enable_if_static_extent_convertible
-    : enable_if<!(is_array<T>::value || is_array_class<T>::value ||
-                  is_span<T>::value || is_vector<T>::value)> {};
-
-// Used by the dynamic extent span to disable the container constructors.
-template <typename T>
-struct enable_if_dynamic_extent_convertible
-    : enable_if<!(is_array<T>::value || is_span<T>::value ||
+struct enable_if_span_convertible
+    : enable_if<has_data<T>::value && has_size<T>::value &&
+                !(is_array_class<T>::value || is_span<T>::value ||
                   is_vector<T>::value)> {};
 
 } // namespace detail
@@ -232,13 +275,12 @@
 
   template <typename Container>
   span(Container & cont,
-       typename detail::enable_if_static_extent_convertible<Container>::type * =
-           NULL)
+       typename detail::enable_if_span_convertible<Container>::type * = NULL)
       : span_base(cont.data()) {}
 
   template <typename Container>
   span(const Container & cont,
-       typename detail::enable_if_static_extent_convertible<Container>::type * =
+       typename detail::enable_if_span_convertible<const Container>::type * =
            NULL)
       : span_base(cont.data()) {}
 
@@ -284,6 +326,12 @@
 
   template <size_t N> span(element_type (&arr)[N]) : span_base(arr), size_(N) {}
 
+  template <size_t N>
+  span(array<value_type, N> & arr) : span_base(arr.data()), size_(N) {}
+
+  template <size_t N>
+  span(const array<value_type, N> & arr) : span_base(arr.data()), size_(N) {}
+
   template <typename U, size_t N>
   span(const span<U, N> & s) : span_base(s.data()), size_(s.size()) {}
 
@@ -296,17 +344,14 @@
       : span_base(vec.empty() ? NULL : &vec.front()), size_(vec.size()) {}
 
   template <typename Container>
-  span(
-      Container & cont,
-      typename detail::enable_if_dynamic_extent_convertible<Container>::type * =
-          NULL)
+  span(Container & cont,
+       typename detail::enable_if_span_convertible<Container>::type * = NULL)
       : span_base(cont.data()), size_(cont.size()) {}
 
   template <typename Container>
-  span(
-      const Container & cont,
-      typename detail::enable_if_dynamic_extent_convertible<Container>::type * =
-          NULL)
+  span(const Container & cont,
+       typename detail::enable_if_span_convertible<const Container>::type * =
+           NULL)
       : span_base(cont.data()), size_(cont.size()) {}
 
   /// @name Observers