]> git.saurik.com Git - apple/javascriptcore.git/blob - wtf/text/StringConcatenate.h
JavaScriptCore-903.5.tar.gz
[apple/javascriptcore.git] / wtf / text / StringConcatenate.h
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 #ifndef WTFString_h
30 #include "AtomicString.h"
31 #endif
32
33 namespace WTF {
34
35 template<typename StringType>
36 class StringTypeAdapter {
37 };
38
39 template<>
40 class StringTypeAdapter<char> {
41 public:
42 StringTypeAdapter<char>(char buffer)
43 : m_buffer(buffer)
44 {
45 }
46
47 unsigned length() { return 1; }
48 void writeTo(UChar* destination) { *destination = m_buffer; }
49
50 private:
51 unsigned char m_buffer;
52 };
53
54 template<>
55 class StringTypeAdapter<UChar> {
56 public:
57 StringTypeAdapter<UChar>(UChar buffer)
58 : m_buffer(buffer)
59 {
60 }
61
62 unsigned length() { return 1; }
63 void writeTo(UChar* destination) { *destination = m_buffer; }
64
65 private:
66 UChar m_buffer;
67 };
68
69 template<>
70 class StringTypeAdapter<char*> {
71 public:
72 StringTypeAdapter<char*>(char* buffer)
73 : m_buffer(buffer)
74 , m_length(strlen(buffer))
75 {
76 }
77
78 unsigned length() { return m_length; }
79
80 void writeTo(UChar* destination)
81 {
82 for (unsigned i = 0; i < m_length; ++i) {
83 unsigned char c = m_buffer[i];
84 destination[i] = c;
85 }
86 }
87
88 private:
89 const char* m_buffer;
90 unsigned m_length;
91 };
92
93 template<>
94 class StringTypeAdapter<const UChar*> {
95 public:
96 StringTypeAdapter<const UChar*>(const UChar* buffer)
97 : m_buffer(buffer)
98 {
99 size_t len = 0;
100 while (m_buffer[len] != UChar(0))
101 len++;
102
103 if (len > std::numeric_limits<unsigned>::max())
104 CRASH();
105
106 m_length = len;
107 }
108
109 unsigned length() { return m_length; }
110
111 void writeTo(UChar* destination)
112 {
113 memcpy(destination, m_buffer, static_cast<size_t>(m_length) * sizeof(UChar));
114 }
115
116 private:
117 const UChar* m_buffer;
118 unsigned m_length;
119 };
120
121 template<>
122 class StringTypeAdapter<const char*> {
123 public:
124 StringTypeAdapter<const char*>(const char* buffer)
125 : m_buffer(buffer)
126 , m_length(strlen(buffer))
127 {
128 }
129
130 unsigned length() { return m_length; }
131
132 void writeTo(UChar* destination)
133 {
134 for (unsigned i = 0; i < m_length; ++i) {
135 unsigned char c = m_buffer[i];
136 destination[i] = c;
137 }
138 }
139
140 private:
141 const char* m_buffer;
142 unsigned m_length;
143 };
144
145 template<>
146 class StringTypeAdapter<Vector<char> > {
147 public:
148 StringTypeAdapter<Vector<char> >(const Vector<char>& buffer)
149 : m_buffer(buffer)
150 {
151 }
152
153 size_t length() { return m_buffer.size(); }
154
155 void writeTo(UChar* destination)
156 {
157 for (size_t i = 0; i < m_buffer.size(); ++i) {
158 unsigned char c = m_buffer[i];
159 destination[i] = c;
160 }
161 }
162
163 private:
164 const Vector<char>& m_buffer;
165 };
166
167 template<>
168 class StringTypeAdapter<String> {
169 public:
170 StringTypeAdapter<String>(const String& string)
171 : m_buffer(string)
172 {
173 }
174
175 unsigned length() { return m_buffer.length(); }
176
177 void writeTo(UChar* destination)
178 {
179 const UChar* data = m_buffer.characters();
180 unsigned length = m_buffer.length();
181 for (unsigned i = 0; i < length; ++i)
182 destination[i] = data[i];
183 }
184
185 private:
186 const String& m_buffer;
187 };
188
189 template<>
190 class StringTypeAdapter<AtomicString> {
191 public:
192 StringTypeAdapter<AtomicString>(const AtomicString& string)
193 : m_adapter(string.string())
194 {
195 }
196
197 unsigned length() { return m_adapter.length(); }
198 void writeTo(UChar* destination) { m_adapter.writeTo(destination); }
199
200 private:
201 StringTypeAdapter<String> m_adapter;
202 };
203
204 inline void sumWithOverflow(unsigned& total, unsigned addend, bool& overflow)
205 {
206 unsigned oldTotal = total;
207 total = oldTotal + addend;
208 if (total < oldTotal)
209 overflow = true;
210 }
211
212 template<typename StringType1, typename StringType2>
213 PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2)
214 {
215 StringTypeAdapter<StringType1> adapter1(string1);
216 StringTypeAdapter<StringType2> adapter2(string2);
217
218 UChar* buffer;
219 bool overflow = false;
220 unsigned length = adapter1.length();
221 sumWithOverflow(length, adapter2.length(), overflow);
222 if (overflow)
223 return 0;
224 RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
225 if (!resultImpl)
226 return 0;
227
228 UChar* result = buffer;
229 adapter1.writeTo(result);
230 result += adapter1.length();
231 adapter2.writeTo(result);
232
233 return resultImpl.release();
234 }
235
236 template<typename StringType1, typename StringType2, typename StringType3>
237 PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3)
238 {
239 StringTypeAdapter<StringType1> adapter1(string1);
240 StringTypeAdapter<StringType2> adapter2(string2);
241 StringTypeAdapter<StringType3> adapter3(string3);
242
243 UChar* buffer = 0;
244 bool overflow = false;
245 unsigned length = adapter1.length();
246 sumWithOverflow(length, adapter2.length(), overflow);
247 sumWithOverflow(length, adapter3.length(), overflow);
248 if (overflow)
249 return 0;
250 RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
251 if (!resultImpl)
252 return 0;
253
254 UChar* result = buffer;
255 adapter1.writeTo(result);
256 result += adapter1.length();
257 adapter2.writeTo(result);
258 result += adapter2.length();
259 adapter3.writeTo(result);
260
261 return resultImpl.release();
262 }
263
264 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4>
265 PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4)
266 {
267 StringTypeAdapter<StringType1> adapter1(string1);
268 StringTypeAdapter<StringType2> adapter2(string2);
269 StringTypeAdapter<StringType3> adapter3(string3);
270 StringTypeAdapter<StringType4> adapter4(string4);
271
272 UChar* buffer;
273 bool overflow = false;
274 unsigned length = adapter1.length();
275 sumWithOverflow(length, adapter2.length(), overflow);
276 sumWithOverflow(length, adapter3.length(), overflow);
277 sumWithOverflow(length, adapter4.length(), overflow);
278 if (overflow)
279 return 0;
280 RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
281 if (!resultImpl)
282 return 0;
283
284 UChar* result = buffer;
285 adapter1.writeTo(result);
286 result += adapter1.length();
287 adapter2.writeTo(result);
288 result += adapter2.length();
289 adapter3.writeTo(result);
290 result += adapter3.length();
291 adapter4.writeTo(result);
292
293 return resultImpl.release();
294 }
295
296 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5>
297 PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5)
298 {
299 StringTypeAdapter<StringType1> adapter1(string1);
300 StringTypeAdapter<StringType2> adapter2(string2);
301 StringTypeAdapter<StringType3> adapter3(string3);
302 StringTypeAdapter<StringType4> adapter4(string4);
303 StringTypeAdapter<StringType5> adapter5(string5);
304
305 UChar* buffer;
306 bool overflow = false;
307 unsigned length = adapter1.length();
308 sumWithOverflow(length, adapter2.length(), overflow);
309 sumWithOverflow(length, adapter3.length(), overflow);
310 sumWithOverflow(length, adapter4.length(), overflow);
311 sumWithOverflow(length, adapter5.length(), overflow);
312 if (overflow)
313 return 0;
314 RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
315 if (!resultImpl)
316 return 0;
317
318 UChar* result = buffer;
319 adapter1.writeTo(result);
320 result += adapter1.length();
321 adapter2.writeTo(result);
322 result += adapter2.length();
323 adapter3.writeTo(result);
324 result += adapter3.length();
325 adapter4.writeTo(result);
326 result += adapter4.length();
327 adapter5.writeTo(result);
328
329 return resultImpl.release();
330 }
331
332 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6>
333 PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6)
334 {
335 StringTypeAdapter<StringType1> adapter1(string1);
336 StringTypeAdapter<StringType2> adapter2(string2);
337 StringTypeAdapter<StringType3> adapter3(string3);
338 StringTypeAdapter<StringType4> adapter4(string4);
339 StringTypeAdapter<StringType5> adapter5(string5);
340 StringTypeAdapter<StringType6> adapter6(string6);
341
342 UChar* buffer;
343 bool overflow = false;
344 unsigned length = adapter1.length();
345 sumWithOverflow(length, adapter2.length(), overflow);
346 sumWithOverflow(length, adapter3.length(), overflow);
347 sumWithOverflow(length, adapter4.length(), overflow);
348 sumWithOverflow(length, adapter5.length(), overflow);
349 sumWithOverflow(length, adapter6.length(), overflow);
350 if (overflow)
351 return 0;
352 RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
353 if (!resultImpl)
354 return 0;
355
356 UChar* result = buffer;
357 adapter1.writeTo(result);
358 result += adapter1.length();
359 adapter2.writeTo(result);
360 result += adapter2.length();
361 adapter3.writeTo(result);
362 result += adapter3.length();
363 adapter4.writeTo(result);
364 result += adapter4.length();
365 adapter5.writeTo(result);
366 result += adapter5.length();
367 adapter6.writeTo(result);
368
369 return resultImpl.release();
370 }
371
372 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7>
373 PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7)
374 {
375 StringTypeAdapter<StringType1> adapter1(string1);
376 StringTypeAdapter<StringType2> adapter2(string2);
377 StringTypeAdapter<StringType3> adapter3(string3);
378 StringTypeAdapter<StringType4> adapter4(string4);
379 StringTypeAdapter<StringType5> adapter5(string5);
380 StringTypeAdapter<StringType6> adapter6(string6);
381 StringTypeAdapter<StringType7> adapter7(string7);
382
383 UChar* buffer;
384 bool overflow = false;
385 unsigned length = adapter1.length();
386 sumWithOverflow(length, adapter2.length(), overflow);
387 sumWithOverflow(length, adapter3.length(), overflow);
388 sumWithOverflow(length, adapter4.length(), overflow);
389 sumWithOverflow(length, adapter5.length(), overflow);
390 sumWithOverflow(length, adapter6.length(), overflow);
391 sumWithOverflow(length, adapter7.length(), overflow);
392 if (overflow)
393 return 0;
394 RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
395 if (!resultImpl)
396 return 0;
397
398 UChar* result = buffer;
399 adapter1.writeTo(result);
400 result += adapter1.length();
401 adapter2.writeTo(result);
402 result += adapter2.length();
403 adapter3.writeTo(result);
404 result += adapter3.length();
405 adapter4.writeTo(result);
406 result += adapter4.length();
407 adapter5.writeTo(result);
408 result += adapter5.length();
409 adapter6.writeTo(result);
410 result += adapter6.length();
411 adapter7.writeTo(result);
412
413 return resultImpl.release();
414 }
415
416 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8>
417 PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8)
418 {
419 StringTypeAdapter<StringType1> adapter1(string1);
420 StringTypeAdapter<StringType2> adapter2(string2);
421 StringTypeAdapter<StringType3> adapter3(string3);
422 StringTypeAdapter<StringType4> adapter4(string4);
423 StringTypeAdapter<StringType5> adapter5(string5);
424 StringTypeAdapter<StringType6> adapter6(string6);
425 StringTypeAdapter<StringType7> adapter7(string7);
426 StringTypeAdapter<StringType8> adapter8(string8);
427
428 UChar* buffer;
429 bool overflow = false;
430 unsigned length = adapter1.length();
431 sumWithOverflow(length, adapter2.length(), overflow);
432 sumWithOverflow(length, adapter3.length(), overflow);
433 sumWithOverflow(length, adapter4.length(), overflow);
434 sumWithOverflow(length, adapter5.length(), overflow);
435 sumWithOverflow(length, adapter6.length(), overflow);
436 sumWithOverflow(length, adapter7.length(), overflow);
437 sumWithOverflow(length, adapter8.length(), overflow);
438 if (overflow)
439 return 0;
440 RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
441 if (!resultImpl)
442 return 0;
443
444 UChar* result = buffer;
445 adapter1.writeTo(result);
446 result += adapter1.length();
447 adapter2.writeTo(result);
448 result += adapter2.length();
449 adapter3.writeTo(result);
450 result += adapter3.length();
451 adapter4.writeTo(result);
452 result += adapter4.length();
453 adapter5.writeTo(result);
454 result += adapter5.length();
455 adapter6.writeTo(result);
456 result += adapter6.length();
457 adapter7.writeTo(result);
458 result += adapter7.length();
459 adapter8.writeTo(result);
460
461 return resultImpl.release();
462 }
463
464 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8, typename StringType9>
465 PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8, StringType9 string9)
466 {
467 StringTypeAdapter<StringType1> adapter1(string1);
468 StringTypeAdapter<StringType2> adapter2(string2);
469 StringTypeAdapter<StringType3> adapter3(string3);
470 StringTypeAdapter<StringType4> adapter4(string4);
471 StringTypeAdapter<StringType5> adapter5(string5);
472 StringTypeAdapter<StringType6> adapter6(string6);
473 StringTypeAdapter<StringType7> adapter7(string7);
474 StringTypeAdapter<StringType8> adapter8(string8);
475 StringTypeAdapter<StringType9> adapter9(string9);
476
477 UChar* buffer;
478 bool overflow = false;
479 unsigned length = adapter1.length();
480 sumWithOverflow(length, adapter2.length(), overflow);
481 sumWithOverflow(length, adapter3.length(), overflow);
482 sumWithOverflow(length, adapter4.length(), overflow);
483 sumWithOverflow(length, adapter5.length(), overflow);
484 sumWithOverflow(length, adapter6.length(), overflow);
485 sumWithOverflow(length, adapter7.length(), overflow);
486 sumWithOverflow(length, adapter8.length(), overflow);
487 sumWithOverflow(length, adapter9.length(), overflow);
488 if (overflow)
489 return 0;
490 RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
491 if (!resultImpl)
492 return 0;
493
494 UChar* result = buffer;
495 adapter1.writeTo(result);
496 result += adapter1.length();
497 adapter2.writeTo(result);
498 result += adapter2.length();
499 adapter3.writeTo(result);
500 result += adapter3.length();
501 adapter4.writeTo(result);
502 result += adapter4.length();
503 adapter5.writeTo(result);
504 result += adapter5.length();
505 adapter6.writeTo(result);
506 result += adapter6.length();
507 adapter7.writeTo(result);
508 result += adapter7.length();
509 adapter8.writeTo(result);
510 result += adapter8.length();
511 adapter9.writeTo(result);
512
513 return resultImpl.release();
514 }
515
516
517 // Convenience only.
518 template<typename StringType1>
519 String makeString(StringType1 string1)
520 {
521 return String(string1);
522 }
523
524 template<typename StringType1, typename StringType2>
525 String makeString(StringType1 string1, StringType2 string2)
526 {
527 RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2);
528 if (!resultImpl)
529 CRASH();
530 return resultImpl.release();
531 }
532
533 template<typename StringType1, typename StringType2, typename StringType3>
534 String makeString(StringType1 string1, StringType2 string2, StringType3 string3)
535 {
536 RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3);
537 if (!resultImpl)
538 CRASH();
539 return resultImpl.release();
540 }
541
542 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4>
543 String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4)
544 {
545 RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4);
546 if (!resultImpl)
547 CRASH();
548 return resultImpl.release();
549 }
550
551 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5>
552 String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5)
553 {
554 RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5);
555 if (!resultImpl)
556 CRASH();
557 return resultImpl.release();
558 }
559
560 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6>
561 String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6)
562 {
563 RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6);
564 if (!resultImpl)
565 CRASH();
566 return resultImpl.release();
567 }
568
569 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7>
570 String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7)
571 {
572 RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7);
573 if (!resultImpl)
574 CRASH();
575 return resultImpl.release();
576 }
577
578 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8>
579 String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8)
580 {
581 RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8);
582 if (!resultImpl)
583 CRASH();
584 return resultImpl.release();
585 }
586
587 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8, typename StringType9>
588 String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8, StringType9 string9)
589 {
590 RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8, string9);
591 if (!resultImpl)
592 CRASH();
593 return resultImpl.release();
594 }
595
596 } // namespace WTF
597
598 using WTF::makeString;
599
600 #include "StringOperators.h"
601 #endif