• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 WTF_EXPORT 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 
130     void writeTo(LChar* destination);
131 
132     void writeTo(UChar* destination);
133 
134 private:
135     const char* m_buffer;
136     unsigned m_length;
137 };
138 
139 template<>
140 class WTF_EXPORT StringTypeAdapter<LChar*> {
141 public:
142     StringTypeAdapter<LChar*>(LChar* buffer);
143 
length()144     unsigned length() { return m_length; }
145 
is8Bit()146     bool is8Bit() { return true; }
147 
148     void writeTo(LChar* destination);
149 
150     void writeTo(UChar* destination);
151 
152 private:
153     const LChar* m_buffer;
154     unsigned m_length;
155 };
156 
157 template<>
158 class WTF_EXPORT StringTypeAdapter<const UChar*> {
159 public:
160     StringTypeAdapter(const UChar* buffer);
161 
length()162     unsigned length() { return m_length; }
163 
is8Bit()164     bool is8Bit() { return false; }
165 
writeTo(LChar *)166     NO_RETURN_DUE_TO_CRASH void writeTo(LChar*)
167     {
168         RELEASE_ASSERT(false);
169     }
170 
171     void writeTo(UChar* destination);
172 
173 private:
174     const UChar* m_buffer;
175     unsigned m_length;
176 };
177 
178 template<>
179 class WTF_EXPORT StringTypeAdapter<const char*> {
180 public:
181     StringTypeAdapter<const char*>(const char* buffer);
182 
length()183     unsigned length() { return m_length; }
184 
is8Bit()185     bool is8Bit() { return true; }
186 
187     void writeTo(LChar* destination);
188 
189     void writeTo(UChar* destination);
190 
191 private:
192     const char* m_buffer;
193     unsigned m_length;
194 };
195 
196 template<>
197 class WTF_EXPORT StringTypeAdapter<const LChar*> {
198 public:
199     StringTypeAdapter<const LChar*>(const LChar* buffer);
200 
length()201     unsigned length() { return m_length; }
202 
is8Bit()203     bool is8Bit() { return true; }
204 
205     void writeTo(LChar* destination);
206 
207     void writeTo(UChar* destination);
208 
209 private:
210     const LChar* m_buffer;
211     unsigned m_length;
212 };
213 
214 template<>
215 class WTF_EXPORT StringTypeAdapter<Vector<char> > {
216 public:
217     StringTypeAdapter<Vector<char> >(const Vector<char>& buffer)
m_buffer(buffer)218         : m_buffer(buffer)
219     {
220     }
221 
length()222     size_t length() { return m_buffer.size(); }
223 
is8Bit()224     bool is8Bit() { return true; }
225 
226     void writeTo(LChar* destination);
227 
228     void writeTo(UChar* destination);
229 
230 private:
231     const Vector<char>& m_buffer;
232 };
233 
234 template<>
235 class StringTypeAdapter<Vector<LChar> > {
236 public:
237     StringTypeAdapter<Vector<LChar> >(const Vector<LChar>& buffer)
m_buffer(buffer)238         : m_buffer(buffer)
239     {
240     }
241 
length()242     size_t length() { return m_buffer.size(); }
243 
is8Bit()244     bool is8Bit() { return true; }
245 
246     void writeTo(LChar* destination);
247 
248     void writeTo(UChar* destination);
249 
250 private:
251     const Vector<LChar>& m_buffer;
252 };
253 
254 template<>
255 class WTF_EXPORT StringTypeAdapter<String> {
256 public:
257     StringTypeAdapter<String>(const String& string)
m_buffer(string)258         : m_buffer(string)
259     {
260     }
261 
length()262     unsigned length() { return m_buffer.length(); }
263 
is8Bit()264     bool is8Bit() { return m_buffer.isNull() || m_buffer.is8Bit(); }
265 
266     void writeTo(LChar* destination);
267 
268     void writeTo(UChar* destination);
269 
270 private:
271     const String& m_buffer;
272 };
273 
274 template<>
275 class StringTypeAdapter<AtomicString> {
276 public:
277     StringTypeAdapter<AtomicString>(const AtomicString& string)
278         : m_adapter(string.string())
279     {
280     }
281 
length()282     unsigned length() { return m_adapter.length(); }
283 
is8Bit()284     bool is8Bit() { return m_adapter.is8Bit(); }
285 
writeTo(LChar * destination)286     void writeTo(LChar* destination) { m_adapter.writeTo(destination); }
writeTo(UChar * destination)287     void writeTo(UChar* destination) { m_adapter.writeTo(destination); }
288 
289 private:
290     StringTypeAdapter<String> m_adapter;
291 };
292 
sumWithOverflow(unsigned & total,unsigned addend,bool & overflow)293 inline void sumWithOverflow(unsigned& total, unsigned addend, bool& overflow)
294 {
295     unsigned oldTotal = total;
296     total = oldTotal + addend;
297     if (total < oldTotal)
298         overflow = true;
299 }
300 
301 template<typename StringType1, typename StringType2>
makeString(StringType1 string1,StringType2 string2)302 PassRefPtr<StringImpl> makeString(StringType1 string1, StringType2 string2)
303 {
304     StringTypeAdapter<StringType1> adapter1(string1);
305     StringTypeAdapter<StringType2> adapter2(string2);
306 
307     bool overflow = false;
308     unsigned length = adapter1.length();
309     sumWithOverflow(length, adapter2.length(), overflow);
310     if (overflow)
311         return nullptr;
312 
313     if (adapter1.is8Bit() && adapter2.is8Bit()) {
314         LChar* buffer;
315         RefPtr<StringImpl> resultImpl = StringImpl::createUninitialized(length, buffer);
316         if (!resultImpl)
317             return nullptr;
318 
319         LChar* result = buffer;
320         adapter1.writeTo(result);
321         result += adapter1.length();
322         adapter2.writeTo(result);
323 
324         return resultImpl.release();
325     }
326 
327     UChar* buffer;
328     RefPtr<StringImpl> resultImpl = StringImpl::createUninitialized(length, buffer);
329     if (!resultImpl)
330         return nullptr;
331 
332     UChar* result = buffer;
333     adapter1.writeTo(result);
334     result += adapter1.length();
335     adapter2.writeTo(result);
336 
337     return resultImpl.release();
338 }
339 
340 } // namespace WTF
341 
342 #include "wtf/text/StringOperators.h"
343 #endif
344