• 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 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 
writeTo(LChar * destination)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 
writeTo(UChar * destination)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 
144 private:
145     const char* m_buffer;
146     unsigned m_length;
147 };
148 
149 template<>
150 class StringTypeAdapter<LChar*> {
151 public:
152     StringTypeAdapter<LChar*>(LChar* buffer)
m_buffer(buffer)153     : m_buffer(buffer)
154     , m_length(strlen(reinterpret_cast<char*>(buffer)))
155     {
156     }
157 
length()158     unsigned length() { return m_length; }
159 
is8Bit()160     bool is8Bit() { return true; }
161 
writeTo(LChar * destination)162     void writeTo(LChar* destination)
163     {
164         memcpy(destination, m_buffer, m_length * sizeof(LChar));
165     }
166 
writeTo(UChar * destination)167     void writeTo(UChar* destination)
168     {
169         StringImpl::copyChars(destination, m_buffer, m_length);
170     }
171 
172 private:
173     const LChar* m_buffer;
174     unsigned m_length;
175 };
176 
177 template<>
178 class StringTypeAdapter<const UChar*> {
179 public:
180     StringTypeAdapter<const UChar*>(const UChar* buffer)
m_buffer(buffer)181         : m_buffer(buffer)
182     {
183         size_t len = 0;
184         while (m_buffer[len] != UChar(0))
185             ++len;
186 
187         RELEASE_ASSERT(len <= std::numeric_limits<unsigned>::max());
188 
189         m_length = len;
190     }
191 
length()192     unsigned length() { return m_length; }
193 
is8Bit()194     bool is8Bit() { return false; }
195 
writeTo(LChar *)196     NO_RETURN_DUE_TO_CRASH void writeTo(LChar*)
197     {
198         RELEASE_ASSERT(false);
199     }
200 
writeTo(UChar * destination)201     void writeTo(UChar* destination)
202     {
203         memcpy(destination, m_buffer, m_length * sizeof(UChar));
204     }
205 
206 private:
207     const UChar* m_buffer;
208     unsigned m_length;
209 };
210 
211 template<>
212 class StringTypeAdapter<const char*> {
213 public:
214     StringTypeAdapter<const char*>(const char* buffer)
m_buffer(buffer)215         : m_buffer(buffer)
216         , m_length(strlen(buffer))
217     {
218     }
219 
length()220     unsigned length() { return m_length; }
221 
is8Bit()222     bool is8Bit() { return true; }
223 
writeTo(LChar * destination)224     void writeTo(LChar* destination)
225     {
226         memcpy(destination, m_buffer, static_cast<size_t>(m_length) * sizeof(LChar));
227     }
228 
writeTo(UChar * destination)229     void writeTo(UChar* destination)
230     {
231         for (unsigned i = 0; i < m_length; ++i) {
232             unsigned char c = m_buffer[i];
233             destination[i] = c;
234         }
235     }
236 
237 private:
238     const char* m_buffer;
239     unsigned m_length;
240 };
241 
242 template<>
243 class StringTypeAdapter<const LChar*> {
244 public:
245     StringTypeAdapter<const LChar*>(const LChar* buffer)
m_buffer(buffer)246         : m_buffer(buffer)
247         , m_length(strlen(reinterpret_cast<const char*>(buffer)))
248     {
249     }
250 
length()251     unsigned length() { return m_length; }
252 
is8Bit()253     bool is8Bit() { return true; }
254 
writeTo(LChar * destination)255     void writeTo(LChar* destination)
256     {
257         memcpy(destination, m_buffer, static_cast<size_t>(m_length) * sizeof(LChar));
258     }
259 
writeTo(UChar * destination)260     void writeTo(UChar* destination)
261     {
262         StringImpl::copyChars(destination, m_buffer, m_length);
263     }
264 
265 private:
266     const LChar* m_buffer;
267     unsigned m_length;
268 };
269 
270 template<>
271 class StringTypeAdapter<Vector<char> > {
272 public:
273     StringTypeAdapter<Vector<char> >(const Vector<char>& buffer)
m_buffer(buffer)274         : m_buffer(buffer)
275     {
276     }
277 
length()278     size_t length() { return m_buffer.size(); }
279 
is8Bit()280     bool is8Bit() { return true; }
281 
writeTo(LChar * destination)282     void writeTo(LChar* destination)
283     {
284         for (size_t i = 0; i < m_buffer.size(); ++i)
285             destination[i] = static_cast<unsigned char>(m_buffer[i]);
286     }
287 
writeTo(UChar * destination)288     void writeTo(UChar* destination)
289     {
290         for (size_t i = 0; i < m_buffer.size(); ++i)
291             destination[i] = static_cast<unsigned char>(m_buffer[i]);
292     }
293 
294 private:
295     const Vector<char>& m_buffer;
296 };
297 
298 template<>
299 class StringTypeAdapter<Vector<LChar> > {
300 public:
301     StringTypeAdapter<Vector<LChar> >(const Vector<LChar>& buffer)
m_buffer(buffer)302         : m_buffer(buffer)
303     {
304     }
305 
length()306     size_t length() { return m_buffer.size(); }
307 
is8Bit()308     bool is8Bit() { return true; }
309 
writeTo(LChar * destination)310     void writeTo(LChar* destination)
311     {
312         for (size_t i = 0; i < m_buffer.size(); ++i)
313             destination[i] = m_buffer[i];
314     }
315 
writeTo(UChar * destination)316     void writeTo(UChar* destination)
317     {
318         for (size_t i = 0; i < m_buffer.size(); ++i)
319             destination[i] = m_buffer[i];
320     }
321 
322 private:
323     const Vector<LChar>& m_buffer;
324 };
325 
326 template<>
327 class StringTypeAdapter<String> {
328 public:
329     StringTypeAdapter<String>(const String& string)
m_buffer(string)330         : m_buffer(string)
331     {
332     }
333 
length()334     unsigned length() { return m_buffer.length(); }
335 
is8Bit()336     bool is8Bit() { return m_buffer.isNull() || m_buffer.is8Bit(); }
337 
writeTo(LChar * destination)338     void writeTo(LChar* destination)
339     {
340         unsigned length = m_buffer.length();
341 
342         ASSERT(is8Bit());
343         const LChar* data = m_buffer.characters8();
344         for (unsigned i = 0; i < length; ++i)
345             destination[i] = data[i];
346 
347         WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING();
348     }
349 
writeTo(UChar * destination)350     void writeTo(UChar* destination)
351     {
352         unsigned length = m_buffer.length();
353 
354         if (is8Bit()) {
355             const LChar* data = m_buffer.characters8();
356             for (unsigned i = 0; i < length; ++i)
357                 destination[i] = data[i];
358         } else {
359             const UChar* data = m_buffer.characters16();
360             for (unsigned i = 0; i < length; ++i)
361                 destination[i] = data[i];
362         }
363 
364         WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING();
365     }
366 
367 private:
368     const String& m_buffer;
369 };
370 
371 template<>
372 class StringTypeAdapter<AtomicString> {
373 public:
374     StringTypeAdapter<AtomicString>(const AtomicString& string)
375         : m_adapter(string.string())
376     {
377     }
378 
length()379     unsigned length() { return m_adapter.length(); }
380 
is8Bit()381     bool is8Bit() { return m_adapter.is8Bit(); }
382 
writeTo(LChar * destination)383     void writeTo(LChar* destination) { m_adapter.writeTo(destination); }
writeTo(UChar * destination)384     void writeTo(UChar* destination) { m_adapter.writeTo(destination); }
385 
386 private:
387     StringTypeAdapter<String> m_adapter;
388 };
389 
sumWithOverflow(unsigned & total,unsigned addend,bool & overflow)390 inline void sumWithOverflow(unsigned& total, unsigned addend, bool& overflow)
391 {
392     unsigned oldTotal = total;
393     total = oldTotal + addend;
394     if (total < oldTotal)
395         overflow = true;
396 }
397 
398 template<typename StringType1, typename StringType2>
makeString(StringType1 string1,StringType2 string2)399 PassRefPtr<StringImpl> makeString(StringType1 string1, StringType2 string2)
400 {
401     StringTypeAdapter<StringType1> adapter1(string1);
402     StringTypeAdapter<StringType2> adapter2(string2);
403 
404     bool overflow = false;
405     unsigned length = adapter1.length();
406     sumWithOverflow(length, adapter2.length(), overflow);
407     if (overflow)
408         return 0;
409 
410     if (adapter1.is8Bit() && adapter2.is8Bit()) {
411         LChar* buffer;
412         RefPtr<StringImpl> resultImpl = StringImpl::createUninitialized(length, buffer);
413         if (!resultImpl)
414             return 0;
415 
416         LChar* result = buffer;
417         adapter1.writeTo(result);
418         result += adapter1.length();
419         adapter2.writeTo(result);
420 
421         return resultImpl.release();
422     }
423 
424     UChar* buffer;
425     RefPtr<StringImpl> resultImpl = StringImpl::createUninitialized(length, buffer);
426     if (!resultImpl)
427         return 0;
428 
429     UChar* result = buffer;
430     adapter1.writeTo(result);
431     result += adapter1.length();
432     adapter2.writeTo(result);
433 
434     return resultImpl.release();
435 }
436 
437 } // namespace WTF
438 
439 #include "wtf/text/StringOperators.h"
440 #endif
441