fix and expand hidl_vec::iterator; add const_iterator.
* Fix flipped post++ and ++pre for hidl_vec::iterator
* make it random accessible.
* add const_iterator.
Test: hidl_test
Change-Id: I8649f8598a13e6054c994d30a4daf383d1dae55c
diff --git a/base/include/hidl/HidlSupport.h b/base/include/hidl/HidlSupport.h
index 61a8bea..8bdb5fe 100644
--- a/base/include/hidl/HidlSupport.h
+++ b/base/include/hidl/HidlSupport.h
@@ -28,7 +28,9 @@
#include <hidl/HidlInternal.h>
#include <hidl/Status.h>
#include <map>
+#include <stddef.h>
#include <tuple>
+#include <type_traits>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/StrongPointer.h>
@@ -395,25 +397,52 @@
// offsetof(hidl_string, mBuffer) exposed since mBuffer is private.
static const size_t kOffsetOfBuffer;
+private:
// Define std interator interface for walking the array contents
- // TODO: it might be nice to implement a full featured random access iterator...
- class iterator : public std::iterator<std::bidirectional_iterator_tag, T>
+ template<bool is_const>
+ class iter : public std::iterator<
+ std::random_access_iterator_tag, /* Category */
+ T,
+ ptrdiff_t, /* Distance */
+ typename std::conditional<is_const, const T *, T *>::type /* Pointer */,
+ typename std::conditional<is_const, const T &, T &>::type /* Reference */>
{
+ using traits = std::iterator_traits<iter>;
+ using ptr_type = typename traits::pointer;
+ using ref_type = typename traits::reference;
+ using diff_type = typename traits::difference_type;
public:
- iterator(T* ptr) : mPtr(ptr) { }
- iterator operator++() { iterator i = *this; mPtr++; return i; }
- iterator operator++(int) { mPtr++; return *this; }
- iterator operator--() { iterator i = *this; mPtr--; return i; }
- iterator operator--(int) { mPtr--; return *this; }
- T& operator*() { return *mPtr; }
- T* operator->() { return mPtr; }
- bool operator==(const iterator& rhs) const { return mPtr == rhs.mPtr; }
- bool operator!=(const iterator& rhs) const { return mPtr != rhs.mPtr; }
+ iter(ptr_type ptr) : mPtr(ptr) { }
+ inline iter &operator++() { mPtr++; return *this; }
+ inline iter operator++(int) { iter i = *this; mPtr++; return i; }
+ inline iter &operator--() { mPtr--; return *this; }
+ inline iter operator--(int) { iter i = *this; mPtr--; return i; }
+ inline friend iter operator+(diff_type n, const iter &it) { return it.mPtr + n; }
+ inline iter operator+(diff_type n) const { return mPtr + n; }
+ inline iter operator-(diff_type n) const { return mPtr - n; }
+ inline diff_type operator-(const iter &other) const { return mPtr - other.mPtr; }
+ inline iter &operator+=(diff_type n) { mPtr += n; return *this; }
+ inline iter &operator-=(diff_type n) { mPtr -= n; return *this; }
+ inline ref_type operator*() const { return *mPtr; }
+ inline ptr_type operator->() const { return mPtr; }
+ inline bool operator==(const iter &rhs) const { return mPtr == rhs.mPtr; }
+ inline bool operator!=(const iter &rhs) const { return mPtr != rhs.mPtr; }
+ inline bool operator< (const iter &rhs) const { return mPtr < rhs.mPtr; }
+ inline bool operator> (const iter &rhs) const { return mPtr > rhs.mPtr; }
+ inline bool operator<=(const iter &rhs) const { return mPtr <= rhs.mPtr; }
+ inline bool operator>=(const iter &rhs) const { return mPtr >= rhs.mPtr; }
+ inline ref_type operator[](size_t n) const { return mPtr[n]; }
private:
- T* mPtr;
+ ptr_type mPtr;
};
+public:
+ using iterator = iter<false /* is_const */>;
+ using const_iterator = iter<true /* is_const */>;
+
iterator begin() { return data(); }
iterator end() { return data()+mSize; }
+ const_iterator begin() const { return data(); }
+ const_iterator end() const { return data()+mSize; }
private:
details::hidl_pointer<T> mBuffer;
diff --git a/test_main.cpp b/test_main.cpp
index 3ee8bc9..0a7ad90 100644
--- a/test_main.cpp
+++ b/test_main.cpp
@@ -110,7 +110,7 @@
EXPECT_FALSE(hs1 == stringNE);
}
-TEST_F(LibHidlTest, VecTest) {
+TEST_F(LibHidlTest, VecInitTest) {
using android::hardware::hidl_vec;
using std::vector;
int32_t array[] = {5, 6, 7};
@@ -128,19 +128,65 @@
hidl_vec<int32_t> v3 = {5, 6, 7}; // initializer_list
EXPECT_EQ(v3.size(), 3ul);
EXPECT_ARRAYEQ(v3, array, v3.size());
+}
+
+TEST_F(LibHidlTest, VecIterTest) {
+ int32_t array[] = {5, 6, 7};
+ android::hardware::hidl_vec<int32_t> hv1 = std::vector<int32_t>(array, array + 3);
auto iter = hv1.begin(); // iterator begin()
- EXPECT_EQ(*iter, 5);
- iter++; // post increment
+ EXPECT_EQ(*iter++, 5);
EXPECT_EQ(*iter, 6);
- ++iter; // pre increment
+ EXPECT_EQ(*++iter, 7);
+ EXPECT_EQ(*iter--, 7);
+ EXPECT_EQ(*iter, 6);
+ EXPECT_EQ(*--iter, 5);
+
+ iter += 2;
EXPECT_EQ(*iter, 7);
+ iter -= 2;
+ EXPECT_EQ(*iter, 5);
+
+ iter++;
+ EXPECT_EQ(*(iter + 1), 7);
+ EXPECT_EQ(*(1 + iter), 7);
+ EXPECT_EQ(*(iter - 1), 5);
+ EXPECT_EQ(*iter, 6);
+
+ auto five = iter - 1;
+ auto seven = iter + 1;
+ EXPECT_EQ(seven - five, 2);
+ EXPECT_EQ(five - seven, -2);
+
+ EXPECT_LT(five, seven);
+ EXPECT_LE(five, seven);
+ EXPECT_GT(seven, five);
+ EXPECT_GE(seven, five);
+
+ EXPECT_EQ(seven[0], 7);
+ EXPECT_EQ(five[1], 6);
+}
+
+TEST_F(LibHidlTest, VecIterForTest) {
+ using android::hardware::hidl_vec;
+ int32_t array[] = {5, 6, 7};
+ hidl_vec<int32_t> hv1 = std::vector<int32_t>(array, array + 3);
int32_t sum = 0; // range based for loop interoperability
for (auto &&i: hv1) {
sum += i;
}
EXPECT_EQ(sum, 5+6+7);
+
+ for (auto iter = hv1.begin(); iter < hv1.end(); ++iter) {
+ *iter += 10;
+ }
+ const hidl_vec<int32_t> &v4 = hv1;
+ sum = 0;
+ for (const auto &i : v4) {
+ sum += i;
+ }
+ EXPECT_EQ(sum, 15+16+17);
}
TEST_F(LibHidlTest, ArrayTest) {