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;