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