Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: third_party/WebKit/Source/wtf/text/StringConcatenate.h

Issue 2315853002: Massively simplify WTF's StringConcatenate (Closed)
Patch Set: missing inlines. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 Apple Inc. All rights reserved. 2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * 12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */ 24 */
25 25
26 #ifndef StringConcatenate_h 26 #ifndef StringConcatenate_h
27 #define StringConcatenate_h 27 #define StringConcatenate_h
28 28
29 #include "wtf/Allocator.h" 29 #include "wtf/Allocator.h"
30 #include "wtf/text/StringBuffer.h"
30 #include <string.h> 31 #include <string.h>
31 32
32 #ifndef WTFString_h 33 #ifndef WTFString_h
33 #include "wtf/text/AtomicString.h" 34 #include "wtf/text/AtomicString.h"
34 #endif 35 #endif
35 36
36 // This macro is helpful for testing how many intermediate Strings are created w hile evaluating an
37 // expression containing operator+.
38 #ifndef WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING
39 #define WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING() ((void)0)
40 #endif
41
42 namespace WTF { 37 namespace WTF {
43 38
44 template<typename StringType> 39 template<typename StringType>
45 class StringTypeAdapter { 40 class StringTypeAdapter {
46 DISALLOW_NEW(); 41 STACK_ALLOCATED();
47 }; 42 };
48 43
49 template<> 44 template<>
50 class StringTypeAdapter<char> { 45 class StringTypeAdapter<LChar> {
51 DISALLOW_NEW(); 46 STACK_ALLOCATED();
52 public: 47 public:
53 StringTypeAdapter<char>(char buffer) 48 explicit StringTypeAdapter<LChar>(LChar buffer)
49 : m_buffer(buffer) {}
50
51 unsigned length() const { return 1; }
52 bool is8Bit() const { return true; }
53
54 void writeTo(LChar* destination) const { *destination = m_buffer; }
55 void writeTo(UChar* destination) const { *destination = m_buffer; }
56
57 private:
58 const LChar m_buffer;
59 };
60
61 template<>
62 class StringTypeAdapter<char> : public StringTypeAdapter<LChar> {
63 STACK_ALLOCATED();
64 public:
65 explicit StringTypeAdapter<char>(char buffer)
66 : StringTypeAdapter<LChar>(buffer) {}
67 };
68
69 template<>
70 class StringTypeAdapter<UChar> {
71 STACK_ALLOCATED();
72 public:
73 explicit StringTypeAdapter<UChar>(UChar buffer)
74 : m_buffer(buffer) {}
75
76 unsigned length() const { return 1; }
77 bool is8Bit() const { return m_buffer <= 0xff; }
78
79 void writeTo(LChar* destination) const
80 {
81 DCHECK(is8Bit());
82 *destination = static_cast<LChar>(m_buffer);
83 }
84
85 void writeTo(UChar* destination) const { *destination = m_buffer; }
86
87 private:
88 const UChar m_buffer;
89 };
90
91 template<>
92 class WTF_EXPORT StringTypeAdapter<const UChar*> {
93 STACK_ALLOCATED();
94 public:
95 explicit StringTypeAdapter(const UChar* buffer);
96
97 unsigned length() const { return m_length; }
98
99 bool is8Bit() const { return false; }
100
101 void writeTo(LChar*) const { RELEASE_NOTREACHED(); }
102 void writeTo(UChar* destination) const;
103
104 private:
105 const UChar* m_buffer;
106 const unsigned m_length;
107 };
108
109 template<>
110 class WTF_EXPORT StringTypeAdapter<const LChar*> {
111 STACK_ALLOCATED();
112 public:
113 explicit StringTypeAdapter(const LChar* buffer)
54 : m_buffer(buffer) 114 : m_buffer(buffer)
55 { 115 , m_length(strlen(reinterpret_cast<const char*>(buffer))) {}
56 } 116
57 117 explicit StringTypeAdapter(const char* buffer)
58 unsigned length() { return 1; } 118 : StringTypeAdapter(reinterpret_cast<const LChar*>(buffer)) {}
59 119
60 bool is8Bit() { return true; } 120 unsigned length() const { return m_length; }
61 121 bool is8Bit() const { return true; }
62 void writeTo(LChar* destination) 122
63 { 123 void writeTo(LChar* destination) const;
64 *destination = m_buffer; 124 void writeTo(UChar* destination) const;
65 }
66
67 void writeTo(UChar* destination) { *destination = m_buffer; }
68
69 private:
70 unsigned char m_buffer;
71 };
72
73 template<>
74 class StringTypeAdapter<LChar> {
75 DISALLOW_NEW();
76 public:
77 StringTypeAdapter<LChar>(LChar buffer)
78 : m_buffer(buffer)
79 {
80 }
81
82 unsigned length() { return 1; }
83
84 bool is8Bit() { return true; }
85
86 void writeTo(LChar* destination)
87 {
88 *destination = m_buffer;
89 }
90
91 void writeTo(UChar* destination) { *destination = m_buffer; }
92
93 private:
94 LChar m_buffer;
95 };
96
97 template<>
98 class StringTypeAdapter<UChar> {
99 DISALLOW_NEW();
100 public:
101 StringTypeAdapter<UChar>(UChar buffer)
102 : m_buffer(buffer)
103 {
104 }
105
106 unsigned length() { return 1; }
107
108 bool is8Bit() { return m_buffer <= 0xff; }
109
110 void writeTo(LChar* destination)
111 {
112 ASSERT(is8Bit());
113 *destination = static_cast<LChar>(m_buffer);
114 }
115
116 void writeTo(UChar* destination) { *destination = m_buffer; }
117
118 private:
119 UChar m_buffer;
120 };
121
122 template<>
123 class WTF_EXPORT StringTypeAdapter<char*> {
124 DISALLOW_NEW();
125 public:
126 StringTypeAdapter<char*>(char* buffer)
127 : m_buffer(buffer)
128 , m_length(strlen(buffer))
129 {
130 }
131
132 unsigned length() { return m_length; }
133
134 bool is8Bit() { return true; }
135
136 void writeTo(LChar* destination);
137
138 void writeTo(UChar* destination);
139
140 private:
141 const char* m_buffer;
142 unsigned m_length;
143 };
144
145 template<>
146 class WTF_EXPORT StringTypeAdapter<LChar*> {
147 DISALLOW_NEW();
148 public:
149 StringTypeAdapter<LChar*>(LChar* buffer);
150
151 unsigned length() { return m_length; }
152
153 bool is8Bit() { return true; }
154
155 void writeTo(LChar* destination);
156
157 void writeTo(UChar* destination);
158 125
159 private: 126 private:
160 const LChar* m_buffer; 127 const LChar* m_buffer;
161 unsigned m_length; 128 const unsigned m_length;
162 };
163
164 template<>
165 class WTF_EXPORT StringTypeAdapter<const UChar*> {
166 DISALLOW_NEW();
167 public:
168 StringTypeAdapter(const UChar* buffer);
169
170 unsigned length() { return m_length; }
171
172 bool is8Bit() { return false; }
173
174 void writeTo(LChar*)
175 {
176 RELEASE_ASSERT(false);
177 }
178
179 void writeTo(UChar* destination);
180
181 private:
182 const UChar* m_buffer;
183 unsigned m_length;
184 };
185
186 template<>
187 class WTF_EXPORT StringTypeAdapter<const char*> {
188 DISALLOW_NEW();
189 public:
190 StringTypeAdapter<const char*>(const char* buffer);
191
192 unsigned length() { return m_length; }
193
194 bool is8Bit() { return true; }
195
196 void writeTo(LChar* destination);
197
198 void writeTo(UChar* destination);
199
200 private:
201 const char* m_buffer;
202 unsigned m_length;
203 };
204
205 template<>
206 class WTF_EXPORT StringTypeAdapter<const LChar*> {
207 DISALLOW_NEW();
208 public:
209 StringTypeAdapter<const LChar*>(const LChar* buffer);
210
211 unsigned length() { return m_length; }
212
213 bool is8Bit() { return true; }
214
215 void writeTo(LChar* destination);
216
217 void writeTo(UChar* destination);
218
219 private:
220 const LChar* m_buffer;
221 unsigned m_length;
222 };
223
224 template<>
225 class WTF_EXPORT StringTypeAdapter<Vector<char>> {
226 DISALLOW_NEW();
227 public:
228 StringTypeAdapter<Vector<char>>(const Vector<char>& buffer)
229 : m_buffer(buffer)
230 {
231 }
232
233 size_t length() { return m_buffer.size(); }
234
235 bool is8Bit() { return true; }
236
237 void writeTo(LChar* destination);
238
239 void writeTo(UChar* destination);
240
241 private:
242 const Vector<char>& m_buffer;
243 };
244
245 template<>
246 class StringTypeAdapter<Vector<LChar>> {
247 DISALLOW_NEW();
248 public:
249 StringTypeAdapter<Vector<LChar>>(const Vector<LChar>& buffer)
250 : m_buffer(buffer)
251 {
252 }
253
254 size_t length() { return m_buffer.size(); }
255
256 bool is8Bit() { return true; }
257
258 void writeTo(LChar* destination);
259
260 void writeTo(UChar* destination);
261
262 private:
263 const Vector<LChar>& m_buffer;
264 }; 129 };
265 130
266 template<> 131 template<>
267 class WTF_EXPORT StringTypeAdapter<String> { 132 class WTF_EXPORT StringTypeAdapter<String> {
268 DISALLOW_NEW(); 133 STACK_ALLOCATED();
269 public: 134 public:
270 StringTypeAdapter<String>(const String& string) 135 explicit StringTypeAdapter(const String& string)
271 : m_buffer(string) 136 : m_buffer(string) {}
272 { 137
273 } 138 unsigned length() const { return m_buffer.length(); }
274 139 bool is8Bit() const { return m_buffer.isNull() || m_buffer.is8Bit(); }
275 unsigned length() { return m_buffer.length(); } 140
276 141 void writeTo(LChar* destination) const;
277 bool is8Bit() { return m_buffer.isNull() || m_buffer.is8Bit(); } 142 void writeTo(UChar* destination) const;
278 143
279 void writeTo(LChar* destination); 144 private:
280 145 const String m_buffer;
Yuta Kitamura 2016/09/07 10:25:39 I don't think store-as-value is an improvement, un
esprehn 2016/09/07 16:21:26 Note that the StringAppend class has always stored
Jeffrey Yasskin 2016/09/07 18:53:01 LLVM has a type called "Twine" that stores referen
Yuta Kitamura 2016/09/08 05:09:31 Ah sorry, I wasn't aware the tests were disabled a
281 void writeTo(UChar* destination); 146 };
282 147
283 private: 148 template<>
284 const String& m_buffer; 149 class StringTypeAdapter<AtomicString> : public StringTypeAdapter<String> {
285 }; 150 STACK_ALLOCATED();
286 151 public:
287 template<> 152 explicit StringTypeAdapter(const AtomicString& string)
288 class StringTypeAdapter<AtomicString> { 153 : StringTypeAdapter<String>(string) {}
289 DISALLOW_NEW(); 154 };
290 public: 155
291 StringTypeAdapter<AtomicString>(const AtomicString& string) 156 namespace internal {
292 : m_adapter(string.getString()) 157 WTF_EXPORT unsigned checkedAddLength(unsigned length1, unsigned length2);
293 { 158 };
294 }
295
296 unsigned length() { return m_adapter.length(); }
297
298 bool is8Bit() { return m_adapter.is8Bit(); }
299
300 void writeTo(LChar* destination) { m_adapter.writeTo(destination); }
301 void writeTo(UChar* destination) { m_adapter.writeTo(destination); }
302
303 private:
304 StringTypeAdapter<String> m_adapter;
305 };
306
307 inline void sumWithOverflow(unsigned& total, unsigned addend, bool& overflow)
308 {
309 unsigned oldTotal = total;
310 total = oldTotal + addend;
311 if (total < oldTotal)
312 overflow = true;
313 }
314 159
315 template<typename StringType1, typename StringType2> 160 template<typename StringType1, typename StringType2>
316 PassRefPtr<StringImpl> makeString(StringType1 string1, StringType2 string2) 161 class StringAppend final {
317 { 162 STACK_ALLOCATED();
318 StringTypeAdapter<StringType1> adapter1(string1); 163 public:
319 StringTypeAdapter<StringType2> adapter2(string2); 164 StringAppend(StringType1 string1, StringType2 string2)
320 165 : m_adapter1(string1)
321 bool overflow = false; 166 , m_adapter2(string2) {}
322 unsigned length = adapter1.length(); 167
323 sumWithOverflow(length, adapter2.length(), overflow); 168 operator String() const { return toString(); }
324 if (overflow) 169 operator AtomicString() const { return AtomicString(toString()); }
325 return nullptr; 170
326 171 unsigned length() const { return internal::checkedAddLength(m_adapter1.lengt h(), m_adapter2.length()); }
327 if (adapter1.is8Bit() && adapter2.is8Bit()) { 172 bool is8Bit() const { return m_adapter1.is8Bit() && m_adapter2.is8Bit(); }
328 LChar* buffer; 173
329 RefPtr<StringImpl> resultImpl = StringImpl::createUninitialized(length, buffer); 174 void writeTo(LChar* destination) const
330 if (!resultImpl) 175 {
331 return nullptr; 176 DCHECK(is8Bit());
332 177 m_adapter1.writeTo(destination);
333 LChar* result = buffer; 178 m_adapter2.writeTo(destination + m_adapter1.length());
334 adapter1.writeTo(result); 179 }
335 result += adapter1.length(); 180
336 adapter2.writeTo(result); 181 void writeTo(UChar* destination) const
337 182 {
338 return resultImpl.release(); 183 m_adapter1.writeTo(destination);
339 } 184 m_adapter2.writeTo(destination + m_adapter1.length());
340 185 }
341 UChar* buffer; 186
342 RefPtr<StringImpl> resultImpl = StringImpl::createUninitialized(length, buff er); 187 private:
343 if (!resultImpl) 188 PassRefPtr<StringImpl> toString() const
344 return nullptr; 189 {
345 190 if (is8Bit()) {
346 UChar* result = buffer; 191 StringBuffer<LChar> buffer(length());
347 adapter1.writeTo(result); 192 writeTo(buffer.characters());
348 result += adapter1.length(); 193 return buffer.release();
349 adapter2.writeTo(result); 194 }
350 195 StringBuffer<UChar> buffer(length());
351 return resultImpl.release(); 196 writeTo(buffer.characters());
197 return buffer.release();
198 }
199
200 StringTypeAdapter<StringType1> m_adapter1;
201 StringTypeAdapter<StringType2> m_adapter2;
202 };
203
204 template<typename StringType1, typename StringType2>
205 class StringTypeAdapter<StringAppend<StringType1, StringType2>> {
206 STACK_ALLOCATED();
207 public:
208 explicit StringTypeAdapter(const StringAppend<StringType1, StringType2>& buf fer)
209 : m_buffer(buffer) {}
210
211 unsigned length() const { return m_buffer.length(); }
212 bool is8Bit() const { return m_buffer.is8Bit(); }
213
214 void writeTo(LChar* destination) const { m_buffer.writeTo(destination); }
215 void writeTo(UChar* destination) const { m_buffer.writeTo(destination); }
216
217 private:
218 const StringAppend<StringType1, StringType2> m_buffer;
219 };
220
221 inline StringAppend<const LChar*, String> operator+(const char* string1, const S tring& string2)
222 {
223 return StringAppend<const LChar*, String>(reinterpret_cast<const LChar*>(str ing1), string2);
224 }
225
226 inline StringAppend<const LChar*, AtomicString> operator+(const char* string1, c onst AtomicString& string2)
227 {
228 return StringAppend<const LChar*, AtomicString>(reinterpret_cast<const LChar *>(string1), string2);
229 }
230
231 template<typename U, typename V>
232 inline StringAppend<const LChar*, StringAppend<U, V>> operator+(const char* stri ng1, const StringAppend<U, V>& string2)
233 {
234 return StringAppend<const LChar*, StringAppend<U, V>>(reinterpret_cast<const LChar*>(string1), string2);
235 }
236
237 inline StringAppend<const UChar*, String> operator+(const UChar* string1, const String& string2)
238 {
239 return StringAppend<const UChar*, String>(string1, string2);
240 }
241
242 inline StringAppend<const UChar*, AtomicString> operator+(const UChar* string1, const AtomicString& string2)
243 {
244 return StringAppend<const UChar*, AtomicString>(string1, string2);
245 }
246
247 template<typename U, typename V>
248 inline StringAppend<const UChar*, StringAppend<U, V>> operator+(const UChar* str ing1, const StringAppend<U, V>& string2)
249 {
250 return StringAppend<const UChar*, StringAppend<U, V>>(string1, string2);
251 }
252
253 inline StringAppend<String, const LChar*> operator+(const String& string1, const char* string2)
254 {
255 return StringAppend<String, const LChar*>(string1, reinterpret_cast<const LC har*>(string2));
256 }
257
258 template<typename T>
259 inline StringAppend<String, T> operator+(const String& string1, T string2)
260 {
261 return StringAppend<String, T>(string1, string2);
262 }
263
264 template<typename U, typename V>
265 inline StringAppend<StringAppend<U, V>, const LChar*> operator+(const StringAppe nd<U, V>& string1, const char* string2)
266 {
267 return StringAppend<StringAppend<U, V>, const LChar*>(string1, reinterpret_c ast<const LChar*>(string2));
268 }
269
270 template<typename U, typename V, typename W>
271 inline StringAppend<StringAppend<U, V>, W> operator+(const StringAppend<U, V>& s tring1, W string2)
272 {
273 return StringAppend<StringAppend<U, V>, W>(string1, string2);
352 } 274 }
353 275
354 } // namespace WTF 276 } // namespace WTF
355
356 #include "wtf/text/StringOperators.h"
357 #endif 277 #endif
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/wtf/BUILD.gn ('k') | third_party/WebKit/Source/wtf/text/StringConcatenate.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698