1 #ifndef ANDROID_PDX_RPC_ARRAY_WRAPPER_H_
2 #define ANDROID_PDX_RPC_ARRAY_WRAPPER_H_
3 
4 #include <cstddef>
5 #include <memory>
6 #include <type_traits>
7 #include <vector>
8 
9 namespace android {
10 namespace pdx {
11 namespace rpc {
12 
13 // Wrapper class for C array buffers, providing an interface suitable for
14 // SerializeObject and DeserializeObject. This class serializes to the same
15 // format as std::vector, and may be substituted for std::vector during
16 // serialization and deserialization. This substitution makes handling of C
17 // arrays more efficient by avoiding unnecessary copies when remote method
18 // signatures specify std::vector arguments or return values.
19 template <typename T>
20 class ArrayWrapper {
21  public:
22   // Define types in the style of STL containers to support STL operators.
23   typedef T value_type;
24   typedef std::size_t size_type;
25   typedef T& reference;
26   typedef const T& const_reference;
27   typedef T* pointer;
28   typedef const T* const_pointer;
29 
ArrayWrapper()30   ArrayWrapper() : buffer_(nullptr), capacity_(0), end_(0) {}
31 
ArrayWrapper(pointer buffer,size_type capacity,size_type size)32   ArrayWrapper(pointer buffer, size_type capacity, size_type size)
33       : buffer_(&buffer[0]),
34         capacity_(capacity),
35         end_(capacity < size ? capacity : size) {}
36 
ArrayWrapper(pointer buffer,size_type size)37   ArrayWrapper(pointer buffer, size_type size)
38       : ArrayWrapper(buffer, size, size) {}
39 
ArrayWrapper(const ArrayWrapper & other)40   ArrayWrapper(const ArrayWrapper& other) { *this = other; }
41 
ArrayWrapper(ArrayWrapper && other)42   ArrayWrapper(ArrayWrapper&& other) noexcept { *this = std::move(other); }
43 
44   ArrayWrapper& operator=(const ArrayWrapper& other) {
45     if (&other == this) {
46       return *this;
47     } else {
48       buffer_ = other.buffer_;
49       capacity_ = other.capacity_;
50       end_ = other.end_;
51     }
52 
53     return *this;
54   }
55 
56   ArrayWrapper& operator=(ArrayWrapper&& other) noexcept {
57     if (&other == this) {
58       return *this;
59     } else {
60       buffer_ = other.buffer_;
61       capacity_ = other.capacity_;
62       end_ = other.end_;
63       other.buffer_ = nullptr;
64       other.capacity_ = 0;
65       other.end_ = 0;
66     }
67 
68     return *this;
69   }
70 
data()71   pointer data() { return buffer_; }
data()72   const_pointer data() const { return buffer_; }
73 
begin()74   pointer begin() { return &buffer_[0]; }
end()75   pointer end() { return &buffer_[end_]; }
begin()76   const_pointer begin() const { return &buffer_[0]; }
end()77   const_pointer end() const { return &buffer_[end_]; }
78 
size()79   size_type size() const { return end_; }
max_size()80   size_type max_size() const { return capacity_; }
capacity()81   size_type capacity() const { return capacity_; }
82 
83   // Moves the end marker to |size|, clamping the end marker to the max capacity
84   // of the underlying array. This method does not change the size of the
85   // underlying array.
resize(size_type size)86   void resize(size_type size) {
87     if (size <= capacity_)
88       end_ = size;
89     else
90       end_ = capacity_;
91   }
92 
93   reference operator[](size_type pos) { return buffer_[pos]; }
94   const_reference operator[](size_type pos) const { return buffer_[pos]; }
95 
96  private:
97   pointer buffer_;
98   size_type capacity_;
99   size_type end_;
100 };
101 
102 template <typename T, typename SizeType = std::size_t>
WrapArray(T * buffer,SizeType size)103 ArrayWrapper<T> WrapArray(T* buffer, SizeType size) {
104   return ArrayWrapper<T>(buffer, size);
105 }
106 
107 }  // namespace rpc
108 }  // namespace pdx
109 }  // namespace android
110 
111 #endif  // ANDROID_PDX_RPC_ARRAY_WRAPPER_H_
112