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 AtomicString_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
41namespace WTF {
42
43template<typename StringType>
44class StringTypeAdapter {
45};
46
47template<>
48class StringTypeAdapter<char> {
49public:
50    StringTypeAdapter<char>(char buffer)
51        : m_buffer(buffer)
52    {
53    }
54
55    unsigned length() { return 1; }
56
57    bool is8Bit() { return true; }
58
59    void writeTo(LChar* destination)
60    {
61        *destination = m_buffer;
62    }
63
64    void writeTo(UChar* destination) { *destination = m_buffer; }
65
66private:
67    unsigned char m_buffer;
68};
69
70template<>
71class StringTypeAdapter<LChar> {
72public:
73    StringTypeAdapter<LChar>(LChar buffer)
74        : m_buffer(buffer)
75    {
76    }
77
78    unsigned length() { return 1; }
79
80    bool is8Bit() { return true; }
81
82    void writeTo(LChar* destination)
83    {
84        *destination = m_buffer;
85    }
86
87    void writeTo(UChar* destination) { *destination = m_buffer; }
88
89private:
90    LChar m_buffer;
91};
92
93template<>
94class StringTypeAdapter<UChar> {
95public:
96    StringTypeAdapter<UChar>(UChar buffer)
97        : m_buffer(buffer)
98    {
99    }
100
101    unsigned length() { return 1; }
102
103    bool is8Bit() { return m_buffer <= 0xff; }
104
105    void writeTo(LChar* destination)
106    {
107        ASSERT(is8Bit());
108        *destination = static_cast<LChar>(m_buffer);
109    }
110
111    void writeTo(UChar* destination) { *destination = m_buffer; }
112
113private:
114    UChar m_buffer;
115};
116
117template<>
118class StringTypeAdapter<char*> {
119public:
120    StringTypeAdapter<char*>(char* buffer)
121        : m_buffer(buffer)
122        , m_length(strlen(buffer))
123    {
124    }
125
126    unsigned length() { return m_length; }
127
128    bool is8Bit() { return true; }
129
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
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
144private:
145    const char* m_buffer;
146    unsigned m_length;
147};
148
149template<>
150class StringTypeAdapter<LChar*> {
151public:
152    StringTypeAdapter<LChar*>(LChar* buffer)
153    : m_buffer(buffer)
154    , m_length(strlen(reinterpret_cast<char*>(buffer)))
155    {
156    }
157
158    unsigned length() { return m_length; }
159
160    bool is8Bit() { return true; }
161
162    void writeTo(LChar* destination)
163    {
164        memcpy(destination, m_buffer, m_length * sizeof(LChar));
165    }
166
167    void writeTo(UChar* destination)
168    {
169        StringImpl::copyChars(destination, m_buffer, m_length);
170    }
171
172private:
173    const LChar* m_buffer;
174    unsigned m_length;
175};
176
177template<>
178class StringTypeAdapter<const UChar*> {
179public:
180    StringTypeAdapter<const UChar*>(const UChar* buffer)
181        : m_buffer(buffer)
182    {
183        size_t len = 0;
184        while (m_buffer[len] != UChar(0))
185            ++len;
186
187        if (len > std::numeric_limits<unsigned>::max())
188            CRASH();
189
190        m_length = len;
191    }
192
193    unsigned length() { return m_length; }
194
195    bool is8Bit() { return false; }
196
197    NO_RETURN_DUE_TO_CRASH void writeTo(LChar*)
198    {
199        CRASH();
200    }
201
202    void writeTo(UChar* destination)
203    {
204        memcpy(destination, m_buffer, m_length * sizeof(UChar));
205    }
206
207private:
208    const UChar* m_buffer;
209    unsigned m_length;
210};
211
212template<>
213class StringTypeAdapter<const char*> {
214public:
215    StringTypeAdapter<const char*>(const char* buffer)
216        : m_buffer(buffer)
217        , m_length(strlen(buffer))
218    {
219    }
220
221    unsigned length() { return m_length; }
222
223    bool is8Bit() { return true; }
224
225    void writeTo(LChar* destination)
226    {
227        memcpy(destination, m_buffer, static_cast<size_t>(m_length) * sizeof(LChar));
228    }
229
230    void writeTo(UChar* destination)
231    {
232        for (unsigned i = 0; i < m_length; ++i) {
233            unsigned char c = m_buffer[i];
234            destination[i] = c;
235        }
236    }
237
238private:
239    const char* m_buffer;
240    unsigned m_length;
241};
242
243template<>
244class StringTypeAdapter<const LChar*> {
245public:
246    StringTypeAdapter<const LChar*>(const LChar* buffer)
247        : m_buffer(buffer)
248        , m_length(strlen(reinterpret_cast<const char*>(buffer)))
249    {
250    }
251
252    unsigned length() { return m_length; }
253
254    bool is8Bit() { return true; }
255
256    void writeTo(LChar* destination)
257    {
258        memcpy(destination, m_buffer, static_cast<size_t>(m_length) * sizeof(LChar));
259    }
260
261    void writeTo(UChar* destination)
262    {
263        StringImpl::copyChars(destination, m_buffer, m_length);
264    }
265
266private:
267    const LChar* m_buffer;
268    unsigned m_length;
269};
270
271template<>
272class StringTypeAdapter<ASCIILiteral> {
273public:
274    StringTypeAdapter<ASCIILiteral>(ASCIILiteral buffer)
275        : m_buffer(reinterpret_cast<const LChar*>(static_cast<const char*>(buffer)))
276        , m_length(strlen(buffer))
277    {
278    }
279
280    size_t length() { return m_length; }
281
282    bool is8Bit() { return true; }
283
284    void writeTo(LChar* destination)
285    {
286        memcpy(destination, m_buffer, static_cast<size_t>(m_length));
287    }
288
289    void writeTo(UChar* destination)
290    {
291        StringImpl::copyChars(destination, m_buffer, m_length);
292    }
293
294private:
295    const LChar* m_buffer;
296    unsigned m_length;
297};
298
299template<>
300class StringTypeAdapter<Vector<char>> {
301public:
302    StringTypeAdapter<Vector<char>>(const Vector<char>& buffer)
303        : m_buffer(buffer)
304    {
305    }
306
307    size_t length() { return m_buffer.size(); }
308
309    bool is8Bit() { return true; }
310
311    void writeTo(LChar* destination)
312    {
313        for (size_t i = 0; i < m_buffer.size(); ++i)
314            destination[i] = static_cast<unsigned char>(m_buffer[i]);
315    }
316
317    void writeTo(UChar* destination)
318    {
319        for (size_t i = 0; i < m_buffer.size(); ++i)
320            destination[i] = static_cast<unsigned char>(m_buffer[i]);
321    }
322
323private:
324    const Vector<char>& m_buffer;
325};
326
327template<>
328class StringTypeAdapter<Vector<LChar>> {
329public:
330    StringTypeAdapter<Vector<LChar>>(const Vector<LChar>& buffer)
331        : m_buffer(buffer)
332    {
333    }
334
335    size_t length() { return m_buffer.size(); }
336
337    bool is8Bit() { return true; }
338
339    void writeTo(LChar* destination)
340    {
341        for (size_t i = 0; i < m_buffer.size(); ++i)
342            destination[i] = m_buffer[i];
343    }
344
345    void writeTo(UChar* destination)
346    {
347        for (size_t i = 0; i < m_buffer.size(); ++i)
348            destination[i] = m_buffer[i];
349    }
350
351private:
352    const Vector<LChar>& m_buffer;
353};
354
355template<>
356class StringTypeAdapter<String> {
357public:
358    StringTypeAdapter<String>(const String& string)
359        : m_buffer(string)
360    {
361    }
362
363    unsigned length() { return m_buffer.length(); }
364
365    bool is8Bit() { return m_buffer.isNull() || m_buffer.is8Bit(); }
366
367    void writeTo(LChar* destination)
368    {
369        unsigned length = m_buffer.length();
370
371        ASSERT(is8Bit());
372        const LChar* data = m_buffer.characters8();
373        for (unsigned i = 0; i < length; ++i)
374            destination[i] = data[i];
375
376        WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING();
377    }
378
379    void writeTo(UChar* destination)
380    {
381        unsigned length = m_buffer.length();
382
383        if (is8Bit()) {
384            const LChar* data = m_buffer.characters8();
385            for (unsigned i = 0; i < length; ++i)
386                destination[i] = data[i];
387        } else {
388            const UChar* data = m_buffer.characters16();
389            for (unsigned i = 0; i < length; ++i)
390                destination[i] = data[i];
391        }
392
393        WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING();
394    }
395
396private:
397    const String& m_buffer;
398};
399
400template<>
401class StringTypeAdapter<AtomicString> {
402public:
403    StringTypeAdapter<AtomicString>(const AtomicString& string)
404        : m_adapter(string.string())
405    {
406    }
407
408    unsigned length() { return m_adapter.length(); }
409
410    bool is8Bit() { return m_adapter.is8Bit(); }
411
412    void writeTo(LChar* destination) { m_adapter.writeTo(destination); }
413    void writeTo(UChar* destination) { m_adapter.writeTo(destination); }
414
415private:
416    StringTypeAdapter<String> m_adapter;
417};
418
419inline void sumWithOverflow(unsigned& total, unsigned addend, bool& overflow)
420{
421    unsigned oldTotal = total;
422    total = oldTotal + addend;
423    if (total < oldTotal)
424        overflow = true;
425}
426
427template<typename StringType1, typename StringType2>
428PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2)
429{
430    StringTypeAdapter<StringType1> adapter1(string1);
431    StringTypeAdapter<StringType2> adapter2(string2);
432
433    bool overflow = false;
434    unsigned length = adapter1.length();
435    sumWithOverflow(length, adapter2.length(), overflow);
436    if (overflow)
437        return 0;
438
439    if (adapter1.is8Bit() && adapter2.is8Bit()) {
440        LChar* buffer;
441        RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
442        if (!resultImpl)
443            return 0;
444
445        LChar* result = buffer;
446        adapter1.writeTo(result);
447        result += adapter1.length();
448        adapter2.writeTo(result);
449
450        return resultImpl.release();
451    }
452
453    UChar* buffer;
454    RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
455    if (!resultImpl)
456        return 0;
457
458    UChar* result = buffer;
459    adapter1.writeTo(result);
460    result += adapter1.length();
461    adapter2.writeTo(result);
462
463    return resultImpl.release();
464}
465
466template<typename StringType1, typename StringType2, typename StringType3>
467PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3)
468{
469    StringTypeAdapter<StringType1> adapter1(string1);
470    StringTypeAdapter<StringType2> adapter2(string2);
471    StringTypeAdapter<StringType3> adapter3(string3);
472
473    bool overflow = false;
474    unsigned length = adapter1.length();
475    sumWithOverflow(length, adapter2.length(), overflow);
476    sumWithOverflow(length, adapter3.length(), overflow);
477    if (overflow)
478        return 0;
479
480    if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit()) {
481        LChar* buffer;
482        RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
483        if (!resultImpl)
484            return 0;
485
486        LChar* result = buffer;
487        adapter1.writeTo(result);
488        result += adapter1.length();
489        adapter2.writeTo(result);
490        result += adapter2.length();
491        adapter3.writeTo(result);
492
493        return resultImpl.release();
494    }
495
496    UChar* buffer = 0;
497    RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
498    if (!resultImpl)
499        return 0;
500
501    UChar* result = buffer;
502    adapter1.writeTo(result);
503    result += adapter1.length();
504    adapter2.writeTo(result);
505    result += adapter2.length();
506    adapter3.writeTo(result);
507
508    return resultImpl.release();
509}
510
511template<typename StringType1, typename StringType2, typename StringType3, typename StringType4>
512PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4)
513{
514    StringTypeAdapter<StringType1> adapter1(string1);
515    StringTypeAdapter<StringType2> adapter2(string2);
516    StringTypeAdapter<StringType3> adapter3(string3);
517    StringTypeAdapter<StringType4> adapter4(string4);
518
519    bool overflow = false;
520    unsigned length = adapter1.length();
521    sumWithOverflow(length, adapter2.length(), overflow);
522    sumWithOverflow(length, adapter3.length(), overflow);
523    sumWithOverflow(length, adapter4.length(), overflow);
524    if (overflow)
525        return 0;
526
527    if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit()) {
528        LChar* buffer;
529        RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
530        if (!resultImpl)
531            return 0;
532
533        LChar* result = buffer;
534        adapter1.writeTo(result);
535        result += adapter1.length();
536        adapter2.writeTo(result);
537        result += adapter2.length();
538        adapter3.writeTo(result);
539        result += adapter3.length();
540        adapter4.writeTo(result);
541
542        return resultImpl.release();
543    }
544
545    UChar* buffer;
546    RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
547    if (!resultImpl)
548        return 0;
549
550    UChar* result = buffer;
551    adapter1.writeTo(result);
552    result += adapter1.length();
553    adapter2.writeTo(result);
554    result += adapter2.length();
555    adapter3.writeTo(result);
556    result += adapter3.length();
557    adapter4.writeTo(result);
558
559    return resultImpl.release();
560}
561
562template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5>
563PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5)
564{
565    StringTypeAdapter<StringType1> adapter1(string1);
566    StringTypeAdapter<StringType2> adapter2(string2);
567    StringTypeAdapter<StringType3> adapter3(string3);
568    StringTypeAdapter<StringType4> adapter4(string4);
569    StringTypeAdapter<StringType5> adapter5(string5);
570
571    bool overflow = false;
572    unsigned length = adapter1.length();
573    sumWithOverflow(length, adapter2.length(), overflow);
574    sumWithOverflow(length, adapter3.length(), overflow);
575    sumWithOverflow(length, adapter4.length(), overflow);
576    sumWithOverflow(length, adapter5.length(), overflow);
577    if (overflow)
578        return 0;
579
580    if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit() && adapter5.is8Bit()) {
581        LChar* buffer;
582        RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
583        if (!resultImpl)
584            return 0;
585
586        LChar* result = buffer;
587        adapter1.writeTo(result);
588        result += adapter1.length();
589        adapter2.writeTo(result);
590        result += adapter2.length();
591        adapter3.writeTo(result);
592        result += adapter3.length();
593        adapter4.writeTo(result);
594        result += adapter4.length();
595        adapter5.writeTo(result);
596
597        return resultImpl.release();
598    }
599
600    UChar* buffer;
601    RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
602    if (!resultImpl)
603        return 0;
604
605    UChar* result = buffer;
606    adapter1.writeTo(result);
607    result += adapter1.length();
608    adapter2.writeTo(result);
609    result += adapter2.length();
610    adapter3.writeTo(result);
611    result += adapter3.length();
612    adapter4.writeTo(result);
613    result += adapter4.length();
614    adapter5.writeTo(result);
615
616    return resultImpl.release();
617}
618
619template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6>
620PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6)
621{
622    StringTypeAdapter<StringType1> adapter1(string1);
623    StringTypeAdapter<StringType2> adapter2(string2);
624    StringTypeAdapter<StringType3> adapter3(string3);
625    StringTypeAdapter<StringType4> adapter4(string4);
626    StringTypeAdapter<StringType5> adapter5(string5);
627    StringTypeAdapter<StringType6> adapter6(string6);
628
629    bool overflow = false;
630    unsigned length = adapter1.length();
631    sumWithOverflow(length, adapter2.length(), overflow);
632    sumWithOverflow(length, adapter3.length(), overflow);
633    sumWithOverflow(length, adapter4.length(), overflow);
634    sumWithOverflow(length, adapter5.length(), overflow);
635    sumWithOverflow(length, adapter6.length(), overflow);
636    if (overflow)
637        return 0;
638
639    if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit() && adapter5.is8Bit() && adapter6.is8Bit()) {
640        LChar* buffer;
641        RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
642        if (!resultImpl)
643            return 0;
644
645        LChar* result = buffer;
646        adapter1.writeTo(result);
647        result += adapter1.length();
648        adapter2.writeTo(result);
649        result += adapter2.length();
650        adapter3.writeTo(result);
651        result += adapter3.length();
652        adapter4.writeTo(result);
653        result += adapter4.length();
654        adapter5.writeTo(result);
655        result += adapter5.length();
656        adapter6.writeTo(result);
657
658        return resultImpl.release();
659    }
660
661    UChar* buffer;
662    RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
663    if (!resultImpl)
664        return 0;
665
666    UChar* result = buffer;
667    adapter1.writeTo(result);
668    result += adapter1.length();
669    adapter2.writeTo(result);
670    result += adapter2.length();
671    adapter3.writeTo(result);
672    result += adapter3.length();
673    adapter4.writeTo(result);
674    result += adapter4.length();
675    adapter5.writeTo(result);
676    result += adapter5.length();
677    adapter6.writeTo(result);
678
679    return resultImpl.release();
680}
681
682template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7>
683PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7)
684{
685    StringTypeAdapter<StringType1> adapter1(string1);
686    StringTypeAdapter<StringType2> adapter2(string2);
687    StringTypeAdapter<StringType3> adapter3(string3);
688    StringTypeAdapter<StringType4> adapter4(string4);
689    StringTypeAdapter<StringType5> adapter5(string5);
690    StringTypeAdapter<StringType6> adapter6(string6);
691    StringTypeAdapter<StringType7> adapter7(string7);
692
693    bool overflow = false;
694    unsigned length = adapter1.length();
695    sumWithOverflow(length, adapter2.length(), overflow);
696    sumWithOverflow(length, adapter3.length(), overflow);
697    sumWithOverflow(length, adapter4.length(), overflow);
698    sumWithOverflow(length, adapter5.length(), overflow);
699    sumWithOverflow(length, adapter6.length(), overflow);
700    sumWithOverflow(length, adapter7.length(), overflow);
701    if (overflow)
702        return 0;
703
704    if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit() && adapter5.is8Bit() && adapter6.is8Bit() && adapter7.is8Bit()) {
705        LChar* buffer;
706        RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
707        if (!resultImpl)
708            return 0;
709
710        LChar* result = buffer;
711        adapter1.writeTo(result);
712        result += adapter1.length();
713        adapter2.writeTo(result);
714        result += adapter2.length();
715        adapter3.writeTo(result);
716        result += adapter3.length();
717        adapter4.writeTo(result);
718        result += adapter4.length();
719        adapter5.writeTo(result);
720        result += adapter5.length();
721        adapter6.writeTo(result);
722        result += adapter6.length();
723        adapter7.writeTo(result);
724
725        return resultImpl.release();
726    }
727
728    UChar* buffer;
729    RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
730    if (!resultImpl)
731        return 0;
732
733    UChar* result = buffer;
734    adapter1.writeTo(result);
735    result += adapter1.length();
736    adapter2.writeTo(result);
737    result += adapter2.length();
738    adapter3.writeTo(result);
739    result += adapter3.length();
740    adapter4.writeTo(result);
741    result += adapter4.length();
742    adapter5.writeTo(result);
743    result += adapter5.length();
744    adapter6.writeTo(result);
745    result += adapter6.length();
746    adapter7.writeTo(result);
747
748    return resultImpl.release();
749}
750
751template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8>
752PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8)
753{
754    StringTypeAdapter<StringType1> adapter1(string1);
755    StringTypeAdapter<StringType2> adapter2(string2);
756    StringTypeAdapter<StringType3> adapter3(string3);
757    StringTypeAdapter<StringType4> adapter4(string4);
758    StringTypeAdapter<StringType5> adapter5(string5);
759    StringTypeAdapter<StringType6> adapter6(string6);
760    StringTypeAdapter<StringType7> adapter7(string7);
761    StringTypeAdapter<StringType8> adapter8(string8);
762
763    bool overflow = false;
764    unsigned length = adapter1.length();
765    sumWithOverflow(length, adapter2.length(), overflow);
766    sumWithOverflow(length, adapter3.length(), overflow);
767    sumWithOverflow(length, adapter4.length(), overflow);
768    sumWithOverflow(length, adapter5.length(), overflow);
769    sumWithOverflow(length, adapter6.length(), overflow);
770    sumWithOverflow(length, adapter7.length(), overflow);
771    sumWithOverflow(length, adapter8.length(), overflow);
772    if (overflow)
773        return 0;
774
775    if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit() && adapter5.is8Bit() && adapter6.is8Bit() && adapter7.is8Bit() && adapter8.is8Bit()) {
776        LChar* buffer;
777        RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
778        if (!resultImpl)
779            return 0;
780
781        LChar* result = buffer;
782        adapter1.writeTo(result);
783        result += adapter1.length();
784        adapter2.writeTo(result);
785        result += adapter2.length();
786        adapter3.writeTo(result);
787        result += adapter3.length();
788        adapter4.writeTo(result);
789        result += adapter4.length();
790        adapter5.writeTo(result);
791        result += adapter5.length();
792        adapter6.writeTo(result);
793        result += adapter6.length();
794        adapter7.writeTo(result);
795        result += adapter7.length();
796        adapter8.writeTo(result);
797
798        return resultImpl.release();
799    }
800
801    UChar* buffer;
802    RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
803    if (!resultImpl)
804        return 0;
805
806    UChar* result = buffer;
807    adapter1.writeTo(result);
808    result += adapter1.length();
809    adapter2.writeTo(result);
810    result += adapter2.length();
811    adapter3.writeTo(result);
812    result += adapter3.length();
813    adapter4.writeTo(result);
814    result += adapter4.length();
815    adapter5.writeTo(result);
816    result += adapter5.length();
817    adapter6.writeTo(result);
818    result += adapter6.length();
819    adapter7.writeTo(result);
820    result += adapter7.length();
821    adapter8.writeTo(result);
822
823    return resultImpl.release();
824}
825
826template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8, typename StringType9>
827PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8, StringType9 string9)
828{
829    StringTypeAdapter<StringType1> adapter1(string1);
830    StringTypeAdapter<StringType2> adapter2(string2);
831    StringTypeAdapter<StringType3> adapter3(string3);
832    StringTypeAdapter<StringType4> adapter4(string4);
833    StringTypeAdapter<StringType5> adapter5(string5);
834    StringTypeAdapter<StringType6> adapter6(string6);
835    StringTypeAdapter<StringType7> adapter7(string7);
836    StringTypeAdapter<StringType8> adapter8(string8);
837    StringTypeAdapter<StringType9> adapter9(string9);
838
839    bool overflow = false;
840    unsigned length = adapter1.length();
841    sumWithOverflow(length, adapter2.length(), overflow);
842    sumWithOverflow(length, adapter3.length(), overflow);
843    sumWithOverflow(length, adapter4.length(), overflow);
844    sumWithOverflow(length, adapter5.length(), overflow);
845    sumWithOverflow(length, adapter6.length(), overflow);
846    sumWithOverflow(length, adapter7.length(), overflow);
847    sumWithOverflow(length, adapter8.length(), overflow);
848    sumWithOverflow(length, adapter9.length(), overflow);
849    if (overflow)
850        return 0;
851
852    if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit() && adapter5.is8Bit() && adapter6.is8Bit() && adapter7.is8Bit() && adapter8.is8Bit() && adapter9.is8Bit()) {
853        LChar* buffer;
854        RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
855        if (!resultImpl)
856            return 0;
857
858        LChar* result = buffer;
859        adapter1.writeTo(result);
860        result += adapter1.length();
861        adapter2.writeTo(result);
862        result += adapter2.length();
863        adapter3.writeTo(result);
864        result += adapter3.length();
865        adapter4.writeTo(result);
866        result += adapter4.length();
867        adapter5.writeTo(result);
868        result += adapter5.length();
869        adapter6.writeTo(result);
870        result += adapter6.length();
871        adapter7.writeTo(result);
872        result += adapter7.length();
873        adapter8.writeTo(result);
874        result += adapter8.length();
875        adapter9.writeTo(result);
876
877        return resultImpl.release();
878    }
879
880    UChar* buffer;
881    RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
882    if (!resultImpl)
883        return 0;
884
885    UChar* result = buffer;
886    adapter1.writeTo(result);
887    result += adapter1.length();
888    adapter2.writeTo(result);
889    result += adapter2.length();
890    adapter3.writeTo(result);
891    result += adapter3.length();
892    adapter4.writeTo(result);
893    result += adapter4.length();
894    adapter5.writeTo(result);
895    result += adapter5.length();
896    adapter6.writeTo(result);
897    result += adapter6.length();
898    adapter7.writeTo(result);
899    result += adapter7.length();
900    adapter8.writeTo(result);
901    result += adapter8.length();
902    adapter9.writeTo(result);
903
904    return resultImpl.release();
905}
906
907
908// Convenience only.
909template<typename StringType1>
910String makeString(StringType1 string1)
911{
912    return String(string1);
913}
914
915template<typename StringType1, typename StringType2>
916String makeString(StringType1 string1, StringType2 string2)
917{
918    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2);
919    if (!resultImpl)
920        CRASH();
921    return resultImpl.release();
922}
923
924template<typename StringType1, typename StringType2, typename StringType3>
925String makeString(StringType1 string1, StringType2 string2, StringType3 string3)
926{
927    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3);
928    if (!resultImpl)
929        CRASH();
930    return resultImpl.release();
931}
932
933template<typename StringType1, typename StringType2, typename StringType3, typename StringType4>
934String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4)
935{
936    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4);
937    if (!resultImpl)
938        CRASH();
939    return resultImpl.release();
940}
941
942template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5>
943String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5)
944{
945    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5);
946    if (!resultImpl)
947        CRASH();
948    return resultImpl.release();
949}
950
951template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6>
952String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6)
953{
954    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6);
955    if (!resultImpl)
956        CRASH();
957    return resultImpl.release();
958}
959
960template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7>
961String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7)
962{
963    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7);
964    if (!resultImpl)
965        CRASH();
966    return resultImpl.release();
967}
968
969template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8>
970String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8)
971{
972    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8);
973    if (!resultImpl)
974        CRASH();
975    return resultImpl.release();
976}
977
978template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8, typename StringType9>
979String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8, StringType9 string9)
980{
981    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8, string9);
982    if (!resultImpl)
983        CRASH();
984    return resultImpl.release();
985}
986
987} // namespace WTF
988
989using WTF::makeString;
990
991#include <wtf/text/StringOperators.h>
992#endif
993