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 
9 namespace android {
10 namespace pdx {
11 namespace 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.
19 template <typename CharT = std::string::value_type,
20           typename Traits = std::char_traits<CharT>>
21 class 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 
StringWrapper()32   StringWrapper() : buffer_(nullptr), capacity_(0), end_(0) {}
33 
StringWrapper(pointer buffer,size_type capacity,size_type size)34   StringWrapper(pointer buffer, size_type capacity, size_type size)
35       : buffer_(&buffer[0]),
36         capacity_(capacity),
37         end_(capacity < size ? capacity : size) {}
38 
StringWrapper(pointer buffer,size_type size)39   StringWrapper(pointer buffer, size_type size)
40       : StringWrapper(buffer, size, size) {}
41 
StringWrapper(pointer buffer)42   explicit StringWrapper(pointer buffer)
43       : StringWrapper(buffer, std::strlen(buffer)) {}
44 
StringWrapper(const StringWrapper & other)45   StringWrapper(const StringWrapper& other) { *this = other; }
46 
StringWrapper(StringWrapper && other)47   StringWrapper(StringWrapper&& other) noexcept { *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) noexcept {
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 
data()76   pointer data() { return buffer_; }
data()77   const_pointer data() const { return buffer_; }
78 
begin()79   pointer begin() { return &buffer_[0]; }
end()80   pointer end() { return &buffer_[end_]; }
begin()81   const_pointer begin() const { return &buffer_[0]; }
end()82   const_pointer end() const { return &buffer_[end_]; }
83 
size()84   size_type size() const { return end_; }
length()85   size_type length() const { return end_; }
max_size()86   size_type max_size() const { return capacity_; }
capacity()87   size_type capacity() const { return capacity_; }
88 
resize(size_type size)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?
110 template <typename T, typename... Any>
WrapString(const std::basic_string<T,Any...> & s)111 StringWrapper<const T> WrapString(const std::basic_string<T, Any...>& s) {
112   return StringWrapper<const T>(s.c_str(), s.length());
113 }
114 
115 template <typename T, typename SizeType = std::size_t>
WrapString(T * s,SizeType size)116 StringWrapper<T> WrapString(T* s, SizeType size) {
117   return StringWrapper<T>(s, size);
118 }
119 
120 template <typename T>
WrapString(T * s)121 StringWrapper<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