1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#ifndef ANDROID_PDX_RPC_STRING_WRAPPER_H_
2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#define ANDROID_PDX_RPC_STRING_WRAPPER_H_
3e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <cstddef>
5e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <cstring>
6e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <string>
7e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <type_traits>
8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
9e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android {
10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace pdx {
11e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace rpc {
12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Wrapper class for C string buffers, providing an interface suitable for
14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// SerializeObject and DeserializeObject. This class serializes to the same
15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// format as std::basic_string, and may be substituted for std::basic_string
16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// during serialization and deserialization. This substitution makes handling of
17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// C strings more efficient by avoiding unnecessary copies when remote method
18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// signatures specify std::basic_string arguments or return values.
19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkotemplate <typename CharT = std::string::value_type,
20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          typename Traits = std::char_traits<CharT>>
21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass StringWrapper {
22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Define types in the style of STL strings to support STL operators.
24e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  typedef Traits traits_type;
25e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  typedef typename Traits::char_type value_type;
26e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  typedef std::size_t size_type;
27e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  typedef value_type& reference;
28e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  typedef const value_type& const_reference;
29e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  typedef value_type* pointer;
30e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  typedef const value_type* const_pointer;
31e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
32e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  StringWrapper() : buffer_(nullptr), capacity_(0), end_(0) {}
33e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
34e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  StringWrapper(pointer buffer, size_type capacity, size_type size)
35e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      : buffer_(&buffer[0]),
36e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        capacity_(capacity),
37e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        end_(capacity < size ? capacity : size) {}
38e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
39e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  StringWrapper(pointer buffer, size_type size)
40e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      : StringWrapper(buffer, size, size) {}
41e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
42e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  explicit StringWrapper(pointer buffer)
43e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      : StringWrapper(buffer, std::strlen(buffer)) {}
44e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
45e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  StringWrapper(const StringWrapper& other) { *this = other; }
46e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  StringWrapper(StringWrapper&& other) { *this = std::move(other); }
48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
49e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  StringWrapper& operator=(const StringWrapper& other) {
50e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (&other == this) {
51e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return *this;
52e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else {
53e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      buffer_ = other.buffer_;
54e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      capacity_ = other.capacity_;
55e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      end_ = other.end_;
56e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
57e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
58e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return *this;
59e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
60e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
61e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  StringWrapper& operator=(StringWrapper&& other) {
62e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (&other == this) {
63e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return *this;
64e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else {
65e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      buffer_ = other.buffer_;
66e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      capacity_ = other.capacity_;
67e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      end_ = other.end_;
68e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      other.buffer_ = nullptr;
69e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      other.capacity_ = 0;
70e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      other.end_ = 0;
71e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
72e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
73e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return *this;
74e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
75e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
76e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  pointer data() { return buffer_; }
77e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const_pointer data() const { return buffer_; }
78e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
79e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  pointer begin() { return &buffer_[0]; }
80e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  pointer end() { return &buffer_[end_]; }
81e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const_pointer begin() const { return &buffer_[0]; }
82e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const_pointer end() const { return &buffer_[end_]; }
83e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
84e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_type size() const { return end_; }
85e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_type length() const { return end_; }
86e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_type max_size() const { return capacity_; }
87e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_type capacity() const { return capacity_; }
88e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
89e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void resize(size_type size) {
90e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (size <= capacity_)
91e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      end_ = size;
92e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    else
93e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      end_ = capacity_;
94e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
95e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
96e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  reference operator[](size_type pos) { return buffer_[pos]; }
97e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const_reference operator[](size_type pos) const { return buffer_[pos]; }
98e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
99e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko private:
100e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  pointer buffer_;
101e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_type capacity_;
102e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_type end_;
103e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
104e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
105e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Utility functions that infer the underlying type of the string, simplifying
106e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// the wrapper interface.
107e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
108e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// TODO(eieio): Wrapping std::basic_string is here for completeness, but is it
109e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// useful?
110e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkotemplate <typename T, typename... Any>
111e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStringWrapper<const T> WrapString(const std::basic_string<T, Any...>& s) {
112e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return StringWrapper<const T>(s.c_str(), s.length());
113e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
114e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
115e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkotemplate <typename T, typename SizeType = std::size_t>
116e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStringWrapper<T> WrapString(T* s, SizeType size) {
117e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return StringWrapper<T>(s, size);
118e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
119e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
120e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkotemplate <typename T>
121e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStringWrapper<T> WrapString(T* s) {
122e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return StringWrapper<T>(s);
123e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
124e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
125e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace rpc
126e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace pdx
127e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace android
128e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
129e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#endif  // ANDROID_PDX_RPC_STRING_WRAPPER_H_
130