1 /*
2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
24 */
25
26 #ifndef StringConcatenate_h
27 #define StringConcatenate_h
28
29 #include <string.h>
30
31 #ifndef WTFString_h
32 #include "wtf/text/AtomicString.h"
33 #endif
34
35 // This macro is helpful for testing how many intermediate Strings are created while evaluating an
36 // expression containing operator+.
37 #ifndef WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING
38 #define WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING() ((void)0)
39 #endif
40
41 namespace WTF {
42
43 template<typename StringType>
44 class StringTypeAdapter {
45 };
46
47 template<>
48 class StringTypeAdapter<char> {
49 public:
50 StringTypeAdapter<char>(char buffer)
m_buffer(buffer)51 : m_buffer(buffer)
52 {
53 }
54
length()55 unsigned length() { return 1; }
56
is8Bit()57 bool is8Bit() { return true; }
58
writeTo(LChar * destination)59 void writeTo(LChar* destination)
60 {
61 *destination = m_buffer;
62 }
63
writeTo(UChar * destination)64 void writeTo(UChar* destination) { *destination = m_buffer; }
65
66 private:
67 unsigned char m_buffer;
68 };
69
70 template<>
71 class StringTypeAdapter<LChar> {
72 public:
73 StringTypeAdapter<LChar>(LChar buffer)
m_buffer(buffer)74 : m_buffer(buffer)
75 {
76 }
77
length()78 unsigned length() { return 1; }
79
is8Bit()80 bool is8Bit() { return true; }
81
writeTo(LChar * destination)82 void writeTo(LChar* destination)
83 {
84 *destination = m_buffer;
85 }
86
writeTo(UChar * destination)87 void writeTo(UChar* destination) { *destination = m_buffer; }
88
89 private:
90 LChar m_buffer;
91 };
92
93 template<>
94 class StringTypeAdapter<UChar> {
95 public:
96 StringTypeAdapter<UChar>(UChar buffer)
m_buffer(buffer)97 : m_buffer(buffer)
98 {
99 }
100
length()101 unsigned length() { return 1; }
102
is8Bit()103 bool is8Bit() { return m_buffer <= 0xff; }
104
writeTo(LChar * destination)105 void writeTo(LChar* destination)
106 {
107 ASSERT(is8Bit());
108 *destination = static_cast<LChar>(m_buffer);
109 }
110
writeTo(UChar * destination)111 void writeTo(UChar* destination) { *destination = m_buffer; }
112
113 private:
114 UChar m_buffer;
115 };
116
117 template<>
118 class StringTypeAdapter<char*> {
119 public:
120 StringTypeAdapter<char*>(char* buffer)
m_buffer(buffer)121 : m_buffer(buffer)
122 , m_length(strlen(buffer))
123 {
124 }
125
length()126 unsigned length() { return m_length; }
127
is8Bit()128 bool is8Bit() { return true; }
129
writeTo(LChar * destination)130 void writeTo(LChar* destination)
131 {
132 for (unsigned i = 0; i < m_length; ++i)
133 destination[i] = static_cast<LChar>(m_buffer[i]);
134 }
135
writeTo(UChar * destination)136 void writeTo(UChar* destination)
137 {
138 for (unsigned i = 0; i < m_length; ++i) {
139 unsigned char c = m_buffer[i];
140 destination[i] = c;
141 }
142 }
143
144 private:
145 const char* m_buffer;
146 unsigned m_length;
147 };
148
149 template<>
150 class StringTypeAdapter<LChar*> {
151 public:
152 StringTypeAdapter<LChar*>(LChar* buffer)
m_buffer(buffer)153 : m_buffer(buffer)
154 , m_length(strlen(reinterpret_cast<char*>(buffer)))
155 {
156 }
157
length()158 unsigned length() { return m_length; }
159
is8Bit()160 bool is8Bit() { return true; }
161
writeTo(LChar * destination)162 void writeTo(LChar* destination)
163 {
164 memcpy(destination, m_buffer, m_length * sizeof(LChar));
165 }
166
writeTo(UChar * destination)167 void writeTo(UChar* destination)
168 {
169 StringImpl::copyChars(destination, m_buffer, m_length);
170 }
171
172 private:
173 const LChar* m_buffer;
174 unsigned m_length;
175 };
176
177 template<>
178 class StringTypeAdapter<const UChar*> {
179 public:
180 StringTypeAdapter<const UChar*>(const UChar* buffer)
m_buffer(buffer)181 : m_buffer(buffer)
182 {
183 size_t len = 0;
184 while (m_buffer[len] != UChar(0))
185 ++len;
186
187 RELEASE_ASSERT(len <= std::numeric_limits<unsigned>::max());
188
189 m_length = len;
190 }
191
length()192 unsigned length() { return m_length; }
193
is8Bit()194 bool is8Bit() { return false; }
195
writeTo(LChar *)196 NO_RETURN_DUE_TO_CRASH void writeTo(LChar*)
197 {
198 RELEASE_ASSERT(false);
199 }
200
writeTo(UChar * destination)201 void writeTo(UChar* destination)
202 {
203 memcpy(destination, m_buffer, m_length * sizeof(UChar));
204 }
205
206 private:
207 const UChar* m_buffer;
208 unsigned m_length;
209 };
210
211 template<>
212 class StringTypeAdapter<const char*> {
213 public:
214 StringTypeAdapter<const char*>(const char* buffer)
m_buffer(buffer)215 : m_buffer(buffer)
216 , m_length(strlen(buffer))
217 {
218 }
219
length()220 unsigned length() { return m_length; }
221
is8Bit()222 bool is8Bit() { return true; }
223
writeTo(LChar * destination)224 void writeTo(LChar* destination)
225 {
226 memcpy(destination, m_buffer, static_cast<size_t>(m_length) * sizeof(LChar));
227 }
228
writeTo(UChar * destination)229 void writeTo(UChar* destination)
230 {
231 for (unsigned i = 0; i < m_length; ++i) {
232 unsigned char c = m_buffer[i];
233 destination[i] = c;
234 }
235 }
236
237 private:
238 const char* m_buffer;
239 unsigned m_length;
240 };
241
242 template<>
243 class StringTypeAdapter<const LChar*> {
244 public:
245 StringTypeAdapter<const LChar*>(const LChar* buffer)
m_buffer(buffer)246 : m_buffer(buffer)
247 , m_length(strlen(reinterpret_cast<const char*>(buffer)))
248 {
249 }
250
length()251 unsigned length() { return m_length; }
252
is8Bit()253 bool is8Bit() { return true; }
254
writeTo(LChar * destination)255 void writeTo(LChar* destination)
256 {
257 memcpy(destination, m_buffer, static_cast<size_t>(m_length) * sizeof(LChar));
258 }
259
writeTo(UChar * destination)260 void writeTo(UChar* destination)
261 {
262 StringImpl::copyChars(destination, m_buffer, m_length);
263 }
264
265 private:
266 const LChar* m_buffer;
267 unsigned m_length;
268 };
269
270 template<>
271 class StringTypeAdapter<Vector<char> > {
272 public:
273 StringTypeAdapter<Vector<char> >(const Vector<char>& buffer)
m_buffer(buffer)274 : m_buffer(buffer)
275 {
276 }
277
length()278 size_t length() { return m_buffer.size(); }
279
is8Bit()280 bool is8Bit() { return true; }
281
writeTo(LChar * destination)282 void writeTo(LChar* destination)
283 {
284 for (size_t i = 0; i < m_buffer.size(); ++i)
285 destination[i] = static_cast<unsigned char>(m_buffer[i]);
286 }
287
writeTo(UChar * destination)288 void writeTo(UChar* destination)
289 {
290 for (size_t i = 0; i < m_buffer.size(); ++i)
291 destination[i] = static_cast<unsigned char>(m_buffer[i]);
292 }
293
294 private:
295 const Vector<char>& m_buffer;
296 };
297
298 template<>
299 class StringTypeAdapter<Vector<LChar> > {
300 public:
301 StringTypeAdapter<Vector<LChar> >(const Vector<LChar>& buffer)
m_buffer(buffer)302 : m_buffer(buffer)
303 {
304 }
305
length()306 size_t length() { return m_buffer.size(); }
307
is8Bit()308 bool is8Bit() { return true; }
309
writeTo(LChar * destination)310 void writeTo(LChar* destination)
311 {
312 for (size_t i = 0; i < m_buffer.size(); ++i)
313 destination[i] = m_buffer[i];
314 }
315
writeTo(UChar * destination)316 void writeTo(UChar* destination)
317 {
318 for (size_t i = 0; i < m_buffer.size(); ++i)
319 destination[i] = m_buffer[i];
320 }
321
322 private:
323 const Vector<LChar>& m_buffer;
324 };
325
326 template<>
327 class StringTypeAdapter<String> {
328 public:
329 StringTypeAdapter<String>(const String& string)
m_buffer(string)330 : m_buffer(string)
331 {
332 }
333
length()334 unsigned length() { return m_buffer.length(); }
335
is8Bit()336 bool is8Bit() { return m_buffer.isNull() || m_buffer.is8Bit(); }
337
writeTo(LChar * destination)338 void writeTo(LChar* destination)
339 {
340 unsigned length = m_buffer.length();
341
342 ASSERT(is8Bit());
343 const LChar* data = m_buffer.characters8();
344 for (unsigned i = 0; i < length; ++i)
345 destination[i] = data[i];
346
347 WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING();
348 }
349
writeTo(UChar * destination)350 void writeTo(UChar* destination)
351 {
352 unsigned length = m_buffer.length();
353
354 if (is8Bit()) {
355 const LChar* data = m_buffer.characters8();
356 for (unsigned i = 0; i < length; ++i)
357 destination[i] = data[i];
358 } else {
359 const UChar* data = m_buffer.characters16();
360 for (unsigned i = 0; i < length; ++i)
361 destination[i] = data[i];
362 }
363
364 WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING();
365 }
366
367 private:
368 const String& m_buffer;
369 };
370
371 template<>
372 class StringTypeAdapter<AtomicString> {
373 public:
374 StringTypeAdapter<AtomicString>(const AtomicString& string)
375 : m_adapter(string.string())
376 {
377 }
378
length()379 unsigned length() { return m_adapter.length(); }
380
is8Bit()381 bool is8Bit() { return m_adapter.is8Bit(); }
382
writeTo(LChar * destination)383 void writeTo(LChar* destination) { m_adapter.writeTo(destination); }
writeTo(UChar * destination)384 void writeTo(UChar* destination) { m_adapter.writeTo(destination); }
385
386 private:
387 StringTypeAdapter<String> m_adapter;
388 };
389
sumWithOverflow(unsigned & total,unsigned addend,bool & overflow)390 inline void sumWithOverflow(unsigned& total, unsigned addend, bool& overflow)
391 {
392 unsigned oldTotal = total;
393 total = oldTotal + addend;
394 if (total < oldTotal)
395 overflow = true;
396 }
397
398 template<typename StringType1, typename StringType2>
makeString(StringType1 string1,StringType2 string2)399 PassRefPtr<StringImpl> makeString(StringType1 string1, StringType2 string2)
400 {
401 StringTypeAdapter<StringType1> adapter1(string1);
402 StringTypeAdapter<StringType2> adapter2(string2);
403
404 bool overflow = false;
405 unsigned length = adapter1.length();
406 sumWithOverflow(length, adapter2.length(), overflow);
407 if (overflow)
408 return 0;
409
410 if (adapter1.is8Bit() && adapter2.is8Bit()) {
411 LChar* buffer;
412 RefPtr<StringImpl> resultImpl = StringImpl::createUninitialized(length, buffer);
413 if (!resultImpl)
414 return 0;
415
416 LChar* result = buffer;
417 adapter1.writeTo(result);
418 result += adapter1.length();
419 adapter2.writeTo(result);
420
421 return resultImpl.release();
422 }
423
424 UChar* buffer;
425 RefPtr<StringImpl> resultImpl = StringImpl::createUninitialized(length, buffer);
426 if (!resultImpl)
427 return 0;
428
429 UChar* result = buffer;
430 adapter1.writeTo(result);
431 result += adapter1.length();
432 adapter2.writeTo(result);
433
434 return resultImpl.release();
435 }
436
437 } // namespace WTF
438
439 #include "wtf/text/StringOperators.h"
440 #endif
441