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