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