Convert (by copying) hidl_array from and to std::array.
* For example, hidl_array<T, 2, 3> can be converted to
std::array<std::array<T, 3>, 2>.
* Uses operator= for copying.
* Also uses operator= when initializing an hidl_array
(instead of memcpy'ing). This fixes potential memory
issues for hidl_array<hidl_string>, for example.
Bug: 32883329
Test: libhidl_test
Change-Id: Idf7d080433aaed2c585fd4875f3411e5544a9e72
diff --git a/base/include/hidl/HidlSupport.h b/base/include/hidl/HidlSupport.h
index f9f7f32..7d649ef 100644
--- a/base/include/hidl/HidlSupport.h
+++ b/base/include/hidl/HidlSupport.h
@@ -18,6 +18,7 @@
#define ANDROID_HIDL_SUPPORT_H
#include <algorithm>
+#include <array>
#include <dirent.h>
#include <dlfcn.h>
#include <iterator>
@@ -453,7 +454,20 @@
};
template<typename T, size_t SIZE1, size_t... SIZES>
+ struct std_array {
+ using type = std::array<typename std_array<T, SIZES...>::type, SIZE1>;
+ };
+
+ template<typename T, size_t SIZE1>
+ struct std_array<T, SIZE1> {
+ using type = std::array<T, SIZE1>;
+ };
+
+ template<typename T, size_t SIZE1, size_t... SIZES>
struct accessor {
+
+ using std_array_type = typename std_array<T, SIZE1, SIZES...>::type;
+
explicit accessor(T *base)
: mBase(base) {
}
@@ -463,12 +477,22 @@
&mBase[index * product<SIZES...>::value]);
}
+ accessor &operator=(const std_array_type &other) {
+ for (size_t i = 0; i < SIZE1; ++i) {
+ (*this)[i] = other[i];
+ }
+ return *this;
+ }
+
private:
T *mBase;
};
template<typename T, size_t SIZE1>
struct accessor<T, SIZE1> {
+
+ using std_array_type = typename std_array<T, SIZE1>::type;
+
explicit accessor(T *base)
: mBase(base) {
}
@@ -477,12 +501,22 @@
return mBase[index];
}
+ accessor &operator=(const std_array_type &other) {
+ for (size_t i = 0; i < SIZE1; ++i) {
+ (*this)[i] = other[i];
+ }
+ return *this;
+ }
+
private:
T *mBase;
};
template<typename T, size_t SIZE1, size_t... SIZES>
struct const_accessor {
+
+ using std_array_type = typename std_array<T, SIZE1, SIZES...>::type;
+
explicit const_accessor(const T *base)
: mBase(base) {
}
@@ -492,12 +526,23 @@
&mBase[index * product<SIZES...>::value]);
}
+ operator std_array_type() {
+ std_array_type array;
+ for (size_t i = 0; i < SIZE1; ++i) {
+ array[i] = (*this)[i];
+ }
+ return array;
+ }
+
private:
const T *mBase;
};
template<typename T, size_t SIZE1>
struct const_accessor<T, SIZE1> {
+
+ using std_array_type = typename std_array<T, SIZE1>::type;
+
explicit const_accessor(const T *base)
: mBase(base) {
}
@@ -506,6 +551,14 @@
return mBase[index];
}
+ operator std_array_type() {
+ std_array_type array;
+ for (size_t i = 0; i < SIZE1; ++i) {
+ array[i] = (*this)[i];
+ }
+ return array;
+ }
+
private:
const T *mBase;
};
@@ -514,10 +567,27 @@
////////////////////////////////////////////////////////////////////////////////
+// A multidimensional array of T's. Assumes that T::operator=(const T &) is defined.
template<typename T, size_t SIZE1, size_t... SIZES>
struct hidl_array {
+
+ using std_array_type = typename details::std_array<T, SIZE1, SIZES...>::type;
+
hidl_array() = default;
+ // Copies the data from source, using T::operator=(const T &).
+ hidl_array(const T *source) {
+ for (size_t i = 0; i < elementCount(); ++i) {
+ mBuffer[i] = source[i];
+ }
+ }
+
+ // Copies the data from the given std::array, using T::operator=(const T &).
+ hidl_array(const std_array_type &array) {
+ details::accessor<T, SIZE1, SIZES...> modifier(mBuffer);
+ modifier = array;
+ }
+
T *data() { return mBuffer; }
const T *data() const { return mBuffer; }
@@ -537,17 +607,36 @@
return std::make_tuple(SIZE1, SIZES...);
}
+ static constexpr size_t elementCount() {
+ return details::product<SIZE1, SIZES...>::value;
+ }
+
+ operator std_array_type() const {
+ return details::const_accessor<T, SIZE1, SIZES...>(mBuffer);
+ }
+
private:
- T mBuffer[details::product<SIZE1, SIZES...>::value];
+ T mBuffer[elementCount()];
};
+// An array of T's. Assumes that T::operator=(const T &) is defined.
template<typename T, size_t SIZE1>
struct hidl_array<T, SIZE1> {
+
+ using std_array_type = typename details::std_array<T, SIZE1>::type;
+
hidl_array() = default;
+
+ // Copies the data from source, using T::operator=(const T &).
hidl_array(const T *source) {
- memcpy(mBuffer, source, SIZE1 * sizeof(T));
+ for (size_t i = 0; i < elementCount(); ++i) {
+ mBuffer[i] = source[i];
+ }
}
+ // Copies the data from the given std::array, using T::operator=(const T &).
+ hidl_array(const std_array_type &array) : hidl_array(array.data()) {}
+
T *data() { return mBuffer; }
const T *data() const { return mBuffer; }
@@ -560,6 +649,16 @@
}
static constexpr size_t size() { return SIZE1; }
+ static constexpr size_t elementCount() { return SIZE1; }
+
+ // Copies the data to an std::array, using T::operator=(T).
+ operator std_array_type() const {
+ std_array_type array;
+ for (size_t i = 0; i < SIZE1; ++i) {
+ array[i] = mBuffer[i];
+ }
+ return array;
+ }
private:
T mBuffer[SIZE1];