1/*
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
3 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 */
21
22#pragma once
23
24namespace WTF {
25
26template<typename StringType1, typename StringType2> class StringAppend {
27public:
28 StringAppend(StringType1 string1, StringType2 string2)
29 : m_string1 { string1 }
30 , m_string2 { string2 }
31 {
32 }
33
34 operator String() const
35 {
36 String result = tryMakeString(m_string1, m_string2);
37 if (!result)
38 CRASH();
39 return result;
40 }
41
42 operator AtomString() const
43 {
44 return operator String();
45 }
46
47 bool is8Bit()
48 {
49 StringTypeAdapter<StringType1> adapter1(m_string1);
50 StringTypeAdapter<StringType2> adapter2(m_string2);
51 return adapter1.is8Bit() && adapter2.is8Bit();
52 }
53
54 void writeTo(LChar* destination)
55 {
56 ASSERT(is8Bit());
57 StringTypeAdapter<StringType1> adapter1(m_string1);
58 StringTypeAdapter<StringType2> adapter2(m_string2);
59 adapter1.writeTo(destination);
60 adapter2.writeTo(destination + adapter1.length());
61 }
62
63 void writeTo(UChar* destination)
64 {
65 StringTypeAdapter<StringType1> adapter1(m_string1);
66 StringTypeAdapter<StringType2> adapter2(m_string2);
67 adapter1.writeTo(destination);
68 adapter2.writeTo(destination + adapter1.length());
69 }
70
71 unsigned length()
72 {
73 StringTypeAdapter<StringType1> adapter1(m_string1);
74 StringTypeAdapter<StringType2> adapter2(m_string2);
75 return adapter1.length() + adapter2.length();
76 }
77
78private:
79 StringType1 m_string1;
80 StringType2 m_string2;
81};
82
83template<typename StringType1, typename StringType2>
84class StringTypeAdapter<StringAppend<StringType1, StringType2>> {
85public:
86 StringTypeAdapter<StringAppend<StringType1, StringType2>>(StringAppend<StringType1, StringType2>& buffer)
87 : m_buffer { buffer }
88 {
89 }
90
91 unsigned length() const { return m_buffer.length(); }
92 bool is8Bit() const { return m_buffer.is8Bit(); }
93 template<typename CharacterType> void writeTo(CharacterType* destination) const { m_buffer.writeTo(destination); }
94
95private:
96 StringAppend<StringType1, StringType2>& m_buffer;
97};
98
99inline StringAppend<const char*, String> operator+(const char* string1, const String& string2)
100{
101 return StringAppend<const char*, String>(string1, string2);
102}
103
104inline StringAppend<const char*, AtomString> operator+(const char* string1, const AtomString& string2)
105{
106 return StringAppend<const char*, AtomString>(string1, string2);
107}
108
109template<typename T, typename = std::enable_if_t<std::is_same<std::decay_t<T>, StringView>::value>>
110inline StringAppend<const char*, StringView> operator+(const char* string1, T string2)
111{
112 return StringAppend<const char*, StringView>(string1, string2);
113}
114
115template<typename U, typename V>
116inline StringAppend<const char*, StringAppend<U, V>> operator+(const char* string1, const StringAppend<U, V>& string2)
117{
118 return StringAppend<const char*, StringAppend<U, V>>(string1, string2);
119}
120
121inline StringAppend<const UChar*, String> operator+(const UChar* string1, const String& string2)
122{
123 return StringAppend<const UChar*, String>(string1, string2);
124}
125
126inline StringAppend<const UChar*, AtomString> operator+(const UChar* string1, const AtomString& string2)
127{
128 return StringAppend<const UChar*, AtomString>(string1, string2);
129}
130
131template<typename T, typename = std::enable_if_t<std::is_same<std::decay_t<T>, StringView>::value>>
132inline StringAppend<const UChar*, StringView> operator+(const UChar* string1, T string2)
133{
134 return StringAppend<const UChar*, StringView>(string1, string2);
135}
136
137template<typename U, typename V>
138inline StringAppend<const UChar*, StringAppend<U, V>> operator+(const UChar* string1, const StringAppend<U, V>& string2)
139{
140 return StringAppend<const UChar*, StringAppend<U, V>>(string1, string2);
141}
142
143inline StringAppend<ASCIILiteral, String> operator+(const ASCIILiteral& string1, const String& string2)
144{
145 return StringAppend<ASCIILiteral, String>(string1, string2);
146}
147
148inline StringAppend<ASCIILiteral, AtomString> operator+(const ASCIILiteral& string1, const AtomString& string2)
149{
150 return StringAppend<ASCIILiteral, AtomString>(string1, string2);
151}
152
153template<typename T, typename = std::enable_if_t<std::is_same<std::decay_t<T>, StringView>::value>>
154inline StringAppend<ASCIILiteral, StringView> operator+(const ASCIILiteral& string1, T string2)
155{
156 return StringAppend<ASCIILiteral, StringView>(string1, string2);
157}
158
159template<typename U, typename V>
160inline StringAppend<ASCIILiteral, StringAppend<U, V>> operator+(const ASCIILiteral& string1, const StringAppend<U, V>& string2)
161{
162 return StringAppend<ASCIILiteral, StringAppend<U, V>>(string1, string2);
163}
164
165template<typename T>
166StringAppend<String, T> operator+(const String& string1, T string2)
167{
168 return StringAppend<String, T>(string1, string2);
169}
170
171template<typename T, typename U, typename = std::enable_if_t<std::is_same<std::decay_t<T>, StringView>::value>>
172StringAppend<StringView, U> operator+(T string1, U string2)
173{
174 return StringAppend<StringView, U>(string1, string2);
175}
176
177template<typename U, typename V, typename W>
178StringAppend<StringAppend<U, V>, W> operator+(const StringAppend<U, V>& string1, W string2)
179{
180 return StringAppend<StringAppend<U, V>, W>(string1, string2);
181}
182
183} // namespace WTF
184