1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_STRING_H_ 6 #define MOJO_PUBLIC_CPP_BINDINGS_STRING_H_ 7 8 #include <stddef.h> 9 10 #include <string> 11 12 #include "base/logging.h" 13 #include "mojo/public/cpp/bindings/lib/array_internal.h" 14 #include "mojo/public/cpp/bindings/type_converter.h" 15 16 namespace mojo { 17 18 // A UTF-8 encoded character string that can be null. Provides functions that 19 // are similar to std::string, along with access to the underlying std::string 20 // object. 21 class String { 22 public: 23 // Constructs an empty string. String()24 String() : is_null_(false) {} String(const std::string & str)25 String(const std::string& str) : value_(str), is_null_(false) {} String(const char * chars)26 String(const char* chars) : is_null_(!chars) { 27 if (chars) 28 value_ = chars; 29 } String(const char * chars,size_t num_chars)30 String(const char* chars, size_t num_chars) 31 : value_(chars, num_chars), is_null_(false) {} String(const mojo::String & str)32 String(const mojo::String& str) 33 : value_(str.value_), is_null_(str.is_null_) {} 34 35 template <size_t N> String(const char chars[N])36 String(const char chars[N]) 37 : value_(chars, N - 1), is_null_(false) {} 38 String(std::string && other)39 String(std::string&& other) : value_(std::move(other)), is_null_(false) {} String(String && other)40 String(String&& other) : is_null_(true) { Swap(&other); } 41 42 template <typename U> From(const U & other)43 static String From(const U& other) { 44 return TypeConverter<String, U>::Convert(other); 45 } 46 47 template <typename U> To()48 U To() const { 49 return TypeConverter<U, String>::Convert(*this); 50 } 51 52 String& operator=(const mojo::String& str) { 53 value_ = str.value_; 54 is_null_ = str.is_null_; 55 return *this; 56 } 57 String& operator=(const std::string& str) { 58 value_ = str; 59 is_null_ = false; 60 return *this; 61 } 62 String& operator=(const char* chars) { 63 is_null_ = !chars; 64 if (chars) { 65 value_ = chars; 66 } else { 67 value_.clear(); 68 } 69 return *this; 70 } 71 72 String& operator=(std::string&& other) { 73 value_ = std::move(other); 74 is_null_ = false; 75 return *this; 76 } 77 String& operator=(String&& other) { 78 is_null_ = true; 79 value_.clear(); 80 Swap(&other); 81 return *this; 82 } 83 is_null()84 bool is_null() const { return is_null_; } 85 size()86 size_t size() const { return value_.size(); } 87 data()88 const char* data() const { return value_.data(); } 89 at(size_t offset)90 const char& at(size_t offset) const { return value_.at(offset); } 91 const char& operator[](size_t offset) const { return value_[offset]; } 92 get()93 const std::string& get() const { return value_; } 94 operator const std::string&() const { return value_; } 95 96 // Returns a const reference to the |std::string| managed by this class. If 97 // the string is null, this will be an empty std::string. storage()98 const std::string& storage() const { return value_; } 99 100 // Passes the underlying storage and resets this string to null. PassStorage()101 std::string PassStorage() { 102 is_null_ = true; 103 return std::move(value_); 104 } 105 Swap(String * other)106 void Swap(String* other) { 107 std::swap(is_null_, other->is_null_); 108 value_.swap(other->value_); 109 } 110 Swap(std::string * other)111 void Swap(std::string* other) { 112 is_null_ = false; 113 value_.swap(*other); 114 } 115 116 private: 117 typedef std::string String::*Testable; 118 119 public: Testable()120 operator Testable() const { return is_null_ ? 0 : &String::value_; } 121 122 private: 123 std::string value_; 124 bool is_null_; 125 }; 126 127 inline bool operator==(const String& a, const String& b) { 128 return a.is_null() == b.is_null() && a.get() == b.get(); 129 } 130 inline bool operator==(const char* a, const String& b) { 131 return !b.is_null() && a == b.get(); 132 } 133 inline bool operator==(const String& a, const char* b) { 134 return !a.is_null() && a.get() == b; 135 } 136 inline bool operator!=(const String& a, const String& b) { 137 return !(a == b); 138 } 139 inline bool operator!=(const char* a, const String& b) { 140 return !(a == b); 141 } 142 inline bool operator!=(const String& a, const char* b) { 143 return !(a == b); 144 } 145 146 inline std::ostream& operator<<(std::ostream& out, const String& s) { 147 return out << s.get(); 148 } 149 150 inline bool operator<(const String& a, const String& b) { 151 if (a.is_null()) 152 return !b.is_null(); 153 if (b.is_null()) 154 return false; 155 156 return a.get() < b.get(); 157 } 158 159 // TODO(darin): Add similar variants of operator<,<=,>,>= 160 161 template <> 162 struct TypeConverter<String, std::string> { 163 static String Convert(const std::string& input) { return String(input); } 164 }; 165 166 template <> 167 struct TypeConverter<std::string, String> { 168 static std::string Convert(const String& input) { return input; } 169 }; 170 171 template <size_t N> 172 struct TypeConverter<String, char[N]> { 173 static String Convert(const char input[N]) { 174 DCHECK(input); 175 return String(input, N - 1); 176 } 177 }; 178 179 // Appease MSVC. 180 template <size_t N> 181 struct TypeConverter<String, const char[N]> { 182 static String Convert(const char input[N]) { 183 DCHECK(input); 184 return String(input, N - 1); 185 } 186 }; 187 188 template <> 189 struct TypeConverter<String, const char*> { 190 // |input| may be null, in which case a null String will be returned. 191 static String Convert(const char* input) { return String(input); } 192 }; 193 194 } // namespace mojo 195 196 #endif // MOJO_PUBLIC_CPP_BINDINGS_STRING_H_ 197