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
9namespace android {
10namespace pdx {
11namespace 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.
19template <typename T>
20class 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
30  ArrayWrapper() : buffer_(nullptr), capacity_(0), end_(0) {}
31
32  ArrayWrapper(pointer buffer, size_type capacity, size_type size)
33      : buffer_(&buffer[0]),
34        capacity_(capacity),
35        end_(capacity < size ? capacity : size) {}
36
37  ArrayWrapper(pointer buffer, size_type size)
38      : ArrayWrapper(buffer, size, size) {}
39
40  ArrayWrapper(const ArrayWrapper& other) { *this = other; }
41
42  ArrayWrapper(ArrayWrapper&& other) { *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) {
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
71  pointer data() { return buffer_; }
72  const_pointer data() const { return buffer_; }
73
74  pointer begin() { return &buffer_[0]; }
75  pointer end() { return &buffer_[end_]; }
76  const_pointer begin() const { return &buffer_[0]; }
77  const_pointer end() const { return &buffer_[end_]; }
78
79  size_type size() const { return end_; }
80  size_type max_size() const { return 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.
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
102template <typename T, typename SizeType = std::size_t>
103ArrayWrapper<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