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 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? 110 template <typename T, typename... Any> 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> 116 StringWrapper<T> WrapString(T* s, SizeType size) { 117 return StringWrapper<T>(s, size); 118 } 119 120 template <typename T> 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