Make string MaxLength for all WTF and JS strings consistently equal to INT_MAX.
[WebKit-https.git] / Source / WTF / wtf / text / StringConcatenate.h
1 /*
2  * Copyright (C) 2010-2018 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 #include <wtf/CheckedArithmetic.h>
31
32 #ifndef AtomicString_h
33 #include <wtf/text/AtomicString.h>
34 #endif
35
36 #ifndef StringView_h
37 #include <wtf/text/StringView.h>
38 #endif
39
40 // This macro is helpful for testing how many intermediate Strings are created while evaluating an
41 // expression containing operator+.
42 #ifndef WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING
43 #define WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING() ((void)0)
44 #endif
45
46 namespace WTF {
47
48 template<typename StringType, typename>
49 class StringTypeAdapter;
50
51 template<>
52 class StringTypeAdapter<char, void> {
53 public:
54     StringTypeAdapter(char character)
55         : m_character(character)
56     {
57     }
58
59     unsigned length() { return 1; }
60     bool is8Bit() { return true; }
61
62     void writeTo(LChar* destination) const
63     {
64         *destination = m_character;
65     }
66
67     void writeTo(UChar* destination) const
68     {
69         *destination = m_character;
70     }
71
72     String toString() const { return String(&m_character, 1); }
73
74 private:
75     char m_character;
76 };
77
78 template<>
79 class StringTypeAdapter<UChar, void> {
80 public:
81     StringTypeAdapter(UChar character)
82         : m_character(character)
83     {
84     }
85
86     unsigned length() const { return 1; }
87     bool is8Bit() const { return m_character <= 0xff; }
88
89     void writeTo(LChar* destination) const
90     {
91         ASSERT(is8Bit());
92         *destination = static_cast<LChar>(m_character);
93     }
94
95     void writeTo(UChar* destination) const
96     {
97         *destination = m_character;
98     }
99
100     String toString() const { return String(&m_character, 1); }
101
102 private:
103     UChar m_character;
104 };
105
106 template<>
107 class StringTypeAdapter<const LChar*, void> {
108 public:
109     StringTypeAdapter(const LChar* characters)
110         : m_characters(characters)
111         , m_length(strlen(reinterpret_cast<const char*>(characters)))
112     {
113     }
114
115     unsigned length() const { return m_length; }
116     bool is8Bit() const { return true; }
117
118     void writeTo(LChar* destination) const
119     {
120         StringView(m_characters, m_length).getCharactersWithUpconvert(destination);
121     }
122
123     void writeTo(UChar* destination) const
124     {
125         StringView(m_characters, m_length).getCharactersWithUpconvert(destination);
126     }
127
128     String toString() const { return String(m_characters, m_length); }
129
130 private:
131     const LChar* m_characters;
132     unsigned m_length;
133 };
134
135 template<>
136 class StringTypeAdapter<const UChar*, void> {
137 public:
138     StringTypeAdapter(const UChar* characters)
139         : m_characters(characters)
140     {
141         unsigned length = 0;
142         while (m_characters[length])
143             ++length;
144
145         RELEASE_ASSERT(length <= String::MaxLength);
146         m_length = length;
147     }
148
149     unsigned length() const { return m_length; }
150     bool is8Bit() const { return false; }
151
152     NO_RETURN_DUE_TO_CRASH void writeTo(LChar*) const
153     {
154         CRASH(); // FIXME make this a compile-time failure https://bugs.webkit.org/show_bug.cgi?id=165791
155     }
156
157     void writeTo(UChar* destination) const
158     {
159         memcpy(destination, m_characters, m_length * sizeof(UChar));
160     }
161
162     String toString() const { return String(m_characters, m_length); }
163
164 private:
165     const UChar* m_characters;
166     unsigned m_length;
167 };
168
169 template<>
170 class StringTypeAdapter<const char*, void> : public StringTypeAdapter<const LChar*, void> {
171 public:
172     StringTypeAdapter(const char* characters)
173         : StringTypeAdapter<const LChar*, void>(reinterpret_cast<const LChar*>(characters))
174     {
175     }
176 };
177
178 template<>
179 class StringTypeAdapter<char*, void> : public StringTypeAdapter<const char*, void> {
180 public:
181     StringTypeAdapter(const char* characters)
182         : StringTypeAdapter<const char*, void>(characters)
183     {
184     }
185 };
186
187 template<>
188 class StringTypeAdapter<ASCIILiteral, void> : public StringTypeAdapter<const char*, void> {
189 public:
190     StringTypeAdapter(ASCIILiteral characters)
191         : StringTypeAdapter<const char*, void>(characters)
192     {
193     }
194 };
195
196 template<>
197 class StringTypeAdapter<Vector<char>, void> {
198 public:
199     StringTypeAdapter(const Vector<char>& vector)
200         : m_vector(vector)
201     {
202     }
203
204     size_t length() const { return m_vector.size(); }
205     bool is8Bit() const { return true; }
206
207     void writeTo(LChar* destination) const
208     {
209         StringView(reinterpret_cast<const LChar*>(m_vector.data()), m_vector.size()).getCharactersWithUpconvert(destination);
210     }
211
212     void writeTo(UChar* destination) const
213     {
214         StringView(reinterpret_cast<const LChar*>(m_vector.data()), m_vector.size()).getCharactersWithUpconvert(destination);
215     }
216
217     String toString() const { return String(m_vector.data(), m_vector.size()); }
218
219 private:
220     const Vector<char>& m_vector;
221 };
222
223 template<>
224 class StringTypeAdapter<String, void> {
225 public:
226     StringTypeAdapter(const String& string)
227         : m_string(string)
228     {
229     }
230
231     unsigned length() const { return m_string.length(); }
232     bool is8Bit() const { return m_string.isNull() || m_string.is8Bit(); }
233
234     void writeTo(LChar* destination) const
235     {
236         StringView(m_string).getCharactersWithUpconvert(destination);
237         WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING();
238     }
239
240     void writeTo(UChar* destination) const
241     {
242         StringView(m_string).getCharactersWithUpconvert(destination);
243         WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING();
244     }
245
246     String toString() const { return m_string; }
247
248 private:
249     const String& m_string;
250 };
251
252 template<>
253 class StringTypeAdapter<AtomicString, void> : public StringTypeAdapter<String, void> {
254 public:
255     StringTypeAdapter(const AtomicString& string)
256         : StringTypeAdapter<String, void>(string.string())
257     {
258     }
259 };
260
261 template<typename Adapter>
262 inline bool are8Bit(Adapter adapter)
263 {
264     return adapter.is8Bit();
265 }
266
267 template<typename Adapter, typename... Adapters>
268 inline bool are8Bit(Adapter adapter, Adapters ...adapters)
269 {
270     return adapter.is8Bit() && are8Bit(adapters...);
271 }
272
273 template<typename ResultType, typename Adapter>
274 inline void makeStringAccumulator(ResultType* result, Adapter adapter)
275 {
276     adapter.writeTo(result);
277 }
278
279 template<typename ResultType, typename Adapter, typename... Adapters>
280 inline void makeStringAccumulator(ResultType* result, Adapter adapter, Adapters ...adapters)
281 {
282     adapter.writeTo(result);
283     makeStringAccumulator(result + adapter.length(), adapters...);
284 }
285
286 template<typename StringTypeAdapter, typename... StringTypeAdapters>
287 String tryMakeStringFromAdapters(StringTypeAdapter adapter, StringTypeAdapters ...adapters)
288 {
289     static_assert(String::MaxLength == std::numeric_limits<int32_t>::max(), "");
290     auto sum = checkedSum<int32_t>(adapter.length(), adapters.length()...);
291     if (sum.hasOverflowed())
292         return String();
293
294     unsigned length = sum.unsafeGet();
295     ASSERT(length <= String::MaxLength);
296     if (are8Bit(adapter, adapters...)) {
297         LChar* buffer;
298         RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
299         if (!resultImpl)
300             return String();
301
302         makeStringAccumulator(buffer, adapter, adapters...);
303
304         return WTFMove(resultImpl);
305     }
306
307     UChar* buffer;
308     RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
309     if (!resultImpl)
310         return String();
311
312     makeStringAccumulator(buffer, adapter, adapters...);
313
314     return WTFMove(resultImpl);
315 }
316
317 template<typename... StringTypes>
318 String tryMakeString(StringTypes ...strings)
319 {
320     return tryMakeStringFromAdapters(StringTypeAdapter<StringTypes>(strings)...);
321 }
322
323 // Convenience only.
324 template<typename StringType>
325 String makeString(StringType string)
326 {
327     return String(string);
328 }
329
330 template<typename... StringTypes>
331 String makeString(StringTypes... strings)
332 {
333     String result = tryMakeString(strings...);
334     if (!result)
335         CRASH();
336     return result;
337 }
338
339 } // namespace WTF
340
341 using WTF::makeString;
342 using WTF::tryMakeString;
343
344 #include <wtf/text/StringOperators.h>
345 #endif