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