|
1 /* |
|
2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) |
|
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. |
|
4 * Copyright (C) 2009 Google Inc. All rights reserved. |
|
5 * |
|
6 * This library is free software; you can redistribute it and/or |
|
7 * modify it under the terms of the GNU Library General Public |
|
8 * License as published by the Free Software Foundation; either |
|
9 * version 2 of the License, or (at your option) any later version. |
|
10 * |
|
11 * This library is distributed in the hope that it will be useful, |
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
14 * Library General Public License for more details. |
|
15 * |
|
16 * You should have received a copy of the GNU Library General Public License |
|
17 * along with this library; see the file COPYING.LIB. If not, write to |
|
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|
19 * Boston, MA 02110-1301, USA. |
|
20 * |
|
21 */ |
|
22 |
|
23 #ifndef UString_h |
|
24 #define UString_h |
|
25 |
|
26 #include "Collector.h" |
|
27 #include "UStringImpl.h" |
|
28 #include <stdint.h> |
|
29 #include <string.h> |
|
30 #include <wtf/Assertions.h> |
|
31 #include <wtf/CrossThreadRefCounted.h> |
|
32 #include <wtf/OwnFastMallocPtr.h> |
|
33 #include <wtf/PassRefPtr.h> |
|
34 #include <wtf/RefPtr.h> |
|
35 #include <wtf/Vector.h> |
|
36 #include <wtf/text/CString.h> |
|
37 #include <wtf/unicode/Unicode.h> |
|
38 |
|
39 namespace JSC { |
|
40 |
|
41 using WTF::PlacementNewAdoptType; |
|
42 using WTF::PlacementNewAdopt; |
|
43 |
|
44 class UString { |
|
45 friend class JIT; |
|
46 |
|
47 public: |
|
48 typedef UStringImpl Rep; |
|
49 |
|
50 public: |
|
51 UString() {} |
|
52 UString(const char*); // Constructor for null-terminated string. |
|
53 UString(const char*, unsigned length); |
|
54 UString(const UChar*, unsigned length); |
|
55 UString(const Vector<UChar>& buffer); |
|
56 |
|
57 UString(const UString& s) |
|
58 : m_rep(s.m_rep) |
|
59 { |
|
60 } |
|
61 |
|
62 // Special constructor for cases where we overwrite an object in place. |
|
63 UString(PlacementNewAdoptType) |
|
64 : m_rep(PlacementNewAdopt) |
|
65 { |
|
66 } |
|
67 |
|
68 template<size_t inlineCapacity> |
|
69 static PassRefPtr<UStringImpl> adopt(Vector<UChar, inlineCapacity>& vector) |
|
70 { |
|
71 return Rep::adopt(vector); |
|
72 } |
|
73 |
|
74 static UString from(int); |
|
75 static UString from(long long); |
|
76 static UString from(unsigned); |
|
77 static UString from(long); |
|
78 static UString from(double); |
|
79 |
|
80 // NOTE: This method should only be used for *debugging* purposes as it |
|
81 // is neither Unicode safe nor free from side effects nor thread-safe. |
|
82 char* ascii() const; |
|
83 |
|
84 /** |
|
85 * Convert the string to UTF-8, assuming it is UTF-16 encoded. |
|
86 * In non-strict mode, this function is tolerant of badly formed UTF-16, it |
|
87 * can create UTF-8 strings that are invalid because they have characters in |
|
88 * the range U+D800-U+DDFF, U+FFFE, or U+FFFF, but the UTF-8 string is |
|
89 * guaranteed to be otherwise valid. |
|
90 * In strict mode, error is returned as null CString. |
|
91 */ |
|
92 CString UTF8String(bool strict = false) const; |
|
93 |
|
94 const UChar* data() const |
|
95 { |
|
96 if (!m_rep) |
|
97 return 0; |
|
98 return m_rep->characters(); |
|
99 } |
|
100 |
|
101 unsigned size() const |
|
102 { |
|
103 if (!m_rep) |
|
104 return 0; |
|
105 return m_rep->length(); |
|
106 } |
|
107 |
|
108 bool isNull() const { return !m_rep; } |
|
109 bool isEmpty() const { return !m_rep || !m_rep->length(); } |
|
110 |
|
111 bool is8Bit() const; |
|
112 |
|
113 UChar operator[](unsigned pos) const; |
|
114 |
|
115 double toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const; |
|
116 double toDouble(bool tolerateTrailingJunk) const; |
|
117 double toDouble() const; |
|
118 |
|
119 uint32_t toUInt32(bool* ok = 0) const; |
|
120 uint32_t toUInt32(bool* ok, bool tolerateEmptyString) const; |
|
121 uint32_t toStrictUInt32(bool* ok = 0) const; |
|
122 |
|
123 unsigned toArrayIndex(bool* ok = 0) const; |
|
124 |
|
125 static const unsigned NotFound = 0xFFFFFFFFu; |
|
126 unsigned find(const UString& f, unsigned pos = 0) const; |
|
127 unsigned find(UChar, unsigned pos = 0) const; |
|
128 unsigned rfind(const UString& f, unsigned pos) const; |
|
129 unsigned rfind(UChar, unsigned pos) const; |
|
130 |
|
131 UString substr(unsigned pos = 0, unsigned len = 0xFFFFFFFF) const; |
|
132 |
|
133 static const UString& null() { return *s_nullUString; } |
|
134 |
|
135 Rep* rep() const { return m_rep.get(); } |
|
136 |
|
137 UString(PassRefPtr<Rep> r) |
|
138 : m_rep(r) |
|
139 { |
|
140 } |
|
141 |
|
142 size_t cost() const |
|
143 { |
|
144 if (!m_rep) |
|
145 return 0; |
|
146 return m_rep->cost(); |
|
147 } |
|
148 |
|
149 ALWAYS_INLINE ~UString() { } |
|
150 private: |
|
151 RefPtr<Rep> m_rep; |
|
152 |
|
153 static UString* s_nullUString; |
|
154 |
|
155 friend void initializeUString(); |
|
156 friend bool operator==(const UString&, const UString&); |
|
157 }; |
|
158 |
|
159 ALWAYS_INLINE bool operator==(const UString& s1, const UString& s2) |
|
160 { |
|
161 UString::Rep* rep1 = s1.rep(); |
|
162 UString::Rep* rep2 = s2.rep(); |
|
163 unsigned size1 = 0; |
|
164 unsigned size2 = 0; |
|
165 |
|
166 if (rep1 == rep2) // If they're the same rep, they're equal. |
|
167 return true; |
|
168 |
|
169 if (rep1) |
|
170 size1 = rep1->length(); |
|
171 |
|
172 if (rep2) |
|
173 size2 = rep2->length(); |
|
174 |
|
175 if (size1 != size2) // If the lengths are not the same, we're done. |
|
176 return false; |
|
177 |
|
178 if (!size1) |
|
179 return true; |
|
180 |
|
181 // At this point we know |
|
182 // (a) that the strings are the same length and |
|
183 // (b) that they are greater than zero length. |
|
184 const UChar* d1 = rep1->characters(); |
|
185 const UChar* d2 = rep2->characters(); |
|
186 |
|
187 if (d1 == d2) // Check to see if the data pointers are the same. |
|
188 return true; |
|
189 |
|
190 // Do quick checks for sizes 1 and 2. |
|
191 switch (size1) { |
|
192 case 1: |
|
193 return d1[0] == d2[0]; |
|
194 case 2: |
|
195 return (d1[0] == d2[0]) & (d1[1] == d2[1]); |
|
196 default: |
|
197 return memcmp(d1, d2, size1 * sizeof(UChar)) == 0; |
|
198 } |
|
199 } |
|
200 |
|
201 |
|
202 inline bool operator!=(const UString& s1, const UString& s2) |
|
203 { |
|
204 return !JSC::operator==(s1, s2); |
|
205 } |
|
206 |
|
207 bool operator<(const UString& s1, const UString& s2); |
|
208 bool operator>(const UString& s1, const UString& s2); |
|
209 |
|
210 bool operator==(const UString& s1, const char* s2); |
|
211 |
|
212 inline bool operator!=(const UString& s1, const char* s2) |
|
213 { |
|
214 return !JSC::operator==(s1, s2); |
|
215 } |
|
216 |
|
217 inline bool operator==(const char *s1, const UString& s2) |
|
218 { |
|
219 return operator==(s2, s1); |
|
220 } |
|
221 |
|
222 inline bool operator!=(const char *s1, const UString& s2) |
|
223 { |
|
224 return !JSC::operator==(s1, s2); |
|
225 } |
|
226 |
|
227 inline int codePointCompare(const UString& s1, const UString& s2) |
|
228 { |
|
229 return codePointCompare(s1.rep(), s2.rep()); |
|
230 } |
|
231 |
|
232 // Rule from ECMA 15.2 about what an array index is. |
|
233 // Must exactly match string form of an unsigned integer, and be less than 2^32 - 1. |
|
234 inline unsigned UString::toArrayIndex(bool* ok) const |
|
235 { |
|
236 unsigned i = toStrictUInt32(ok); |
|
237 if (ok && i >= 0xFFFFFFFFU) |
|
238 *ok = false; |
|
239 return i; |
|
240 } |
|
241 |
|
242 // We'd rather not do shared substring append for small strings, since |
|
243 // this runs too much risk of a tiny initial string holding down a |
|
244 // huge buffer. |
|
245 static const unsigned minShareSize = Heap::minExtraCost / sizeof(UChar); |
|
246 |
|
247 struct IdentifierRepHash : PtrHash<RefPtr<JSC::UString::Rep> > { |
|
248 static unsigned hash(const RefPtr<JSC::UString::Rep>& key) { return key->existingHash(); } |
|
249 static unsigned hash(JSC::UString::Rep* key) { return key->existingHash(); } |
|
250 }; |
|
251 |
|
252 void initializeUString(); |
|
253 |
|
254 template<typename StringType> |
|
255 class StringTypeAdapter { |
|
256 }; |
|
257 |
|
258 template<> |
|
259 class StringTypeAdapter<char*> { |
|
260 public: |
|
261 StringTypeAdapter<char*>(char* buffer) |
|
262 : m_buffer((unsigned char*)buffer) |
|
263 , m_length(strlen(buffer)) |
|
264 { |
|
265 } |
|
266 |
|
267 unsigned length() { return m_length; } |
|
268 |
|
269 void writeTo(UChar* destination) |
|
270 { |
|
271 for (unsigned i = 0; i < m_length; ++i) |
|
272 destination[i] = m_buffer[i]; |
|
273 } |
|
274 |
|
275 private: |
|
276 const unsigned char* m_buffer; |
|
277 unsigned m_length; |
|
278 }; |
|
279 |
|
280 template<> |
|
281 class StringTypeAdapter<const char*> { |
|
282 public: |
|
283 StringTypeAdapter<const char*>(const char* buffer) |
|
284 : m_buffer((unsigned char*)buffer) |
|
285 , m_length(strlen(buffer)) |
|
286 { |
|
287 } |
|
288 |
|
289 unsigned length() { return m_length; } |
|
290 |
|
291 void writeTo(UChar* destination) |
|
292 { |
|
293 for (unsigned i = 0; i < m_length; ++i) |
|
294 destination[i] = m_buffer[i]; |
|
295 } |
|
296 |
|
297 private: |
|
298 const unsigned char* m_buffer; |
|
299 unsigned m_length; |
|
300 }; |
|
301 |
|
302 template<> |
|
303 class StringTypeAdapter<UString> { |
|
304 public: |
|
305 StringTypeAdapter<UString>(UString& string) |
|
306 : m_data(string.data()) |
|
307 , m_length(string.size()) |
|
308 { |
|
309 } |
|
310 |
|
311 unsigned length() { return m_length; } |
|
312 |
|
313 void writeTo(UChar* destination) |
|
314 { |
|
315 for (unsigned i = 0; i < m_length; ++i) |
|
316 destination[i] = m_data[i]; |
|
317 } |
|
318 |
|
319 private: |
|
320 const UChar* m_data; |
|
321 unsigned m_length; |
|
322 }; |
|
323 |
|
324 inline void sumWithOverflow(unsigned& total, unsigned addend, bool& overflow) |
|
325 { |
|
326 unsigned oldTotal = total; |
|
327 total = oldTotal + addend; |
|
328 if (total < oldTotal) |
|
329 overflow = true; |
|
330 } |
|
331 |
|
332 template<typename StringType1, typename StringType2> |
|
333 PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2) |
|
334 { |
|
335 StringTypeAdapter<StringType1> adapter1(string1); |
|
336 StringTypeAdapter<StringType2> adapter2(string2); |
|
337 |
|
338 UChar* buffer; |
|
339 bool overflow = false; |
|
340 unsigned length = adapter1.length(); |
|
341 sumWithOverflow(length, adapter2.length(), overflow); |
|
342 if (overflow) |
|
343 return 0; |
|
344 PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); |
|
345 if (!resultImpl) |
|
346 return 0; |
|
347 |
|
348 UChar* result = buffer; |
|
349 adapter1.writeTo(result); |
|
350 result += adapter1.length(); |
|
351 adapter2.writeTo(result); |
|
352 |
|
353 return resultImpl; |
|
354 } |
|
355 |
|
356 template<typename StringType1, typename StringType2, typename StringType3> |
|
357 PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3) |
|
358 { |
|
359 StringTypeAdapter<StringType1> adapter1(string1); |
|
360 StringTypeAdapter<StringType2> adapter2(string2); |
|
361 StringTypeAdapter<StringType3> adapter3(string3); |
|
362 |
|
363 UChar* buffer = 0; |
|
364 bool overflow = false; |
|
365 unsigned length = adapter1.length(); |
|
366 sumWithOverflow(length, adapter2.length(), overflow); |
|
367 sumWithOverflow(length, adapter3.length(), overflow); |
|
368 if (overflow) |
|
369 return 0; |
|
370 PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); |
|
371 if (!resultImpl) |
|
372 return 0; |
|
373 |
|
374 UChar* result = buffer; |
|
375 adapter1.writeTo(result); |
|
376 result += adapter1.length(); |
|
377 adapter2.writeTo(result); |
|
378 result += adapter2.length(); |
|
379 adapter3.writeTo(result); |
|
380 |
|
381 return resultImpl; |
|
382 } |
|
383 |
|
384 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> |
|
385 PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) |
|
386 { |
|
387 StringTypeAdapter<StringType1> adapter1(string1); |
|
388 StringTypeAdapter<StringType2> adapter2(string2); |
|
389 StringTypeAdapter<StringType3> adapter3(string3); |
|
390 StringTypeAdapter<StringType4> adapter4(string4); |
|
391 |
|
392 UChar* buffer; |
|
393 bool overflow = false; |
|
394 unsigned length = adapter1.length(); |
|
395 sumWithOverflow(length, adapter2.length(), overflow); |
|
396 sumWithOverflow(length, adapter3.length(), overflow); |
|
397 sumWithOverflow(length, adapter4.length(), overflow); |
|
398 if (overflow) |
|
399 return 0; |
|
400 PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); |
|
401 if (!resultImpl) |
|
402 return 0; |
|
403 |
|
404 UChar* result = buffer; |
|
405 adapter1.writeTo(result); |
|
406 result += adapter1.length(); |
|
407 adapter2.writeTo(result); |
|
408 result += adapter2.length(); |
|
409 adapter3.writeTo(result); |
|
410 result += adapter3.length(); |
|
411 adapter4.writeTo(result); |
|
412 |
|
413 return resultImpl; |
|
414 } |
|
415 |
|
416 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> |
|
417 PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) |
|
418 { |
|
419 StringTypeAdapter<StringType1> adapter1(string1); |
|
420 StringTypeAdapter<StringType2> adapter2(string2); |
|
421 StringTypeAdapter<StringType3> adapter3(string3); |
|
422 StringTypeAdapter<StringType4> adapter4(string4); |
|
423 StringTypeAdapter<StringType5> adapter5(string5); |
|
424 |
|
425 UChar* buffer; |
|
426 bool overflow = false; |
|
427 unsigned length = adapter1.length(); |
|
428 sumWithOverflow(length, adapter2.length(), overflow); |
|
429 sumWithOverflow(length, adapter3.length(), overflow); |
|
430 sumWithOverflow(length, adapter4.length(), overflow); |
|
431 sumWithOverflow(length, adapter5.length(), overflow); |
|
432 if (overflow) |
|
433 return 0; |
|
434 PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); |
|
435 if (!resultImpl) |
|
436 return 0; |
|
437 |
|
438 UChar* result = buffer; |
|
439 adapter1.writeTo(result); |
|
440 result += adapter1.length(); |
|
441 adapter2.writeTo(result); |
|
442 result += adapter2.length(); |
|
443 adapter3.writeTo(result); |
|
444 result += adapter3.length(); |
|
445 adapter4.writeTo(result); |
|
446 result += adapter4.length(); |
|
447 adapter5.writeTo(result); |
|
448 |
|
449 return resultImpl; |
|
450 } |
|
451 |
|
452 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> |
|
453 PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) |
|
454 { |
|
455 StringTypeAdapter<StringType1> adapter1(string1); |
|
456 StringTypeAdapter<StringType2> adapter2(string2); |
|
457 StringTypeAdapter<StringType3> adapter3(string3); |
|
458 StringTypeAdapter<StringType4> adapter4(string4); |
|
459 StringTypeAdapter<StringType5> adapter5(string5); |
|
460 StringTypeAdapter<StringType6> adapter6(string6); |
|
461 |
|
462 UChar* buffer; |
|
463 bool overflow = false; |
|
464 unsigned length = adapter1.length(); |
|
465 sumWithOverflow(length, adapter2.length(), overflow); |
|
466 sumWithOverflow(length, adapter3.length(), overflow); |
|
467 sumWithOverflow(length, adapter4.length(), overflow); |
|
468 sumWithOverflow(length, adapter5.length(), overflow); |
|
469 sumWithOverflow(length, adapter6.length(), overflow); |
|
470 if (overflow) |
|
471 return 0; |
|
472 PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); |
|
473 if (!resultImpl) |
|
474 return 0; |
|
475 |
|
476 UChar* result = buffer; |
|
477 adapter1.writeTo(result); |
|
478 result += adapter1.length(); |
|
479 adapter2.writeTo(result); |
|
480 result += adapter2.length(); |
|
481 adapter3.writeTo(result); |
|
482 result += adapter3.length(); |
|
483 adapter4.writeTo(result); |
|
484 result += adapter4.length(); |
|
485 adapter5.writeTo(result); |
|
486 result += adapter5.length(); |
|
487 adapter6.writeTo(result); |
|
488 |
|
489 return resultImpl; |
|
490 } |
|
491 |
|
492 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7> |
|
493 PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7) |
|
494 { |
|
495 StringTypeAdapter<StringType1> adapter1(string1); |
|
496 StringTypeAdapter<StringType2> adapter2(string2); |
|
497 StringTypeAdapter<StringType3> adapter3(string3); |
|
498 StringTypeAdapter<StringType4> adapter4(string4); |
|
499 StringTypeAdapter<StringType5> adapter5(string5); |
|
500 StringTypeAdapter<StringType6> adapter6(string6); |
|
501 StringTypeAdapter<StringType7> adapter7(string7); |
|
502 |
|
503 UChar* buffer; |
|
504 bool overflow = false; |
|
505 unsigned length = adapter1.length(); |
|
506 sumWithOverflow(length, adapter2.length(), overflow); |
|
507 sumWithOverflow(length, adapter3.length(), overflow); |
|
508 sumWithOverflow(length, adapter4.length(), overflow); |
|
509 sumWithOverflow(length, adapter5.length(), overflow); |
|
510 sumWithOverflow(length, adapter6.length(), overflow); |
|
511 sumWithOverflow(length, adapter7.length(), overflow); |
|
512 if (overflow) |
|
513 return 0; |
|
514 PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); |
|
515 if (!resultImpl) |
|
516 return 0; |
|
517 |
|
518 UChar* result = buffer; |
|
519 adapter1.writeTo(result); |
|
520 result += adapter1.length(); |
|
521 adapter2.writeTo(result); |
|
522 result += adapter2.length(); |
|
523 adapter3.writeTo(result); |
|
524 result += adapter3.length(); |
|
525 adapter4.writeTo(result); |
|
526 result += adapter4.length(); |
|
527 adapter5.writeTo(result); |
|
528 result += adapter5.length(); |
|
529 adapter6.writeTo(result); |
|
530 result += adapter6.length(); |
|
531 adapter7.writeTo(result); |
|
532 |
|
533 return resultImpl; |
|
534 } |
|
535 |
|
536 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8> |
|
537 PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8) |
|
538 { |
|
539 StringTypeAdapter<StringType1> adapter1(string1); |
|
540 StringTypeAdapter<StringType2> adapter2(string2); |
|
541 StringTypeAdapter<StringType3> adapter3(string3); |
|
542 StringTypeAdapter<StringType4> adapter4(string4); |
|
543 StringTypeAdapter<StringType5> adapter5(string5); |
|
544 StringTypeAdapter<StringType6> adapter6(string6); |
|
545 StringTypeAdapter<StringType7> adapter7(string7); |
|
546 StringTypeAdapter<StringType8> adapter8(string8); |
|
547 |
|
548 UChar* buffer; |
|
549 bool overflow = false; |
|
550 unsigned length = adapter1.length(); |
|
551 sumWithOverflow(length, adapter2.length(), overflow); |
|
552 sumWithOverflow(length, adapter3.length(), overflow); |
|
553 sumWithOverflow(length, adapter4.length(), overflow); |
|
554 sumWithOverflow(length, adapter5.length(), overflow); |
|
555 sumWithOverflow(length, adapter6.length(), overflow); |
|
556 sumWithOverflow(length, adapter7.length(), overflow); |
|
557 sumWithOverflow(length, adapter8.length(), overflow); |
|
558 if (overflow) |
|
559 return 0; |
|
560 PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); |
|
561 if (!resultImpl) |
|
562 return 0; |
|
563 |
|
564 UChar* result = buffer; |
|
565 adapter1.writeTo(result); |
|
566 result += adapter1.length(); |
|
567 adapter2.writeTo(result); |
|
568 result += adapter2.length(); |
|
569 adapter3.writeTo(result); |
|
570 result += adapter3.length(); |
|
571 adapter4.writeTo(result); |
|
572 result += adapter4.length(); |
|
573 adapter5.writeTo(result); |
|
574 result += adapter5.length(); |
|
575 adapter6.writeTo(result); |
|
576 result += adapter6.length(); |
|
577 adapter7.writeTo(result); |
|
578 result += adapter7.length(); |
|
579 adapter8.writeTo(result); |
|
580 |
|
581 return resultImpl; |
|
582 } |
|
583 |
|
584 template<typename StringType1, typename StringType2> |
|
585 UString makeString(StringType1 string1, StringType2 string2) |
|
586 { |
|
587 PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2); |
|
588 if (!resultImpl) |
|
589 CRASH(); |
|
590 return resultImpl; |
|
591 } |
|
592 |
|
593 template<typename StringType1, typename StringType2, typename StringType3> |
|
594 UString makeString(StringType1 string1, StringType2 string2, StringType3 string3) |
|
595 { |
|
596 PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3); |
|
597 if (!resultImpl) |
|
598 CRASH(); |
|
599 return resultImpl; |
|
600 } |
|
601 |
|
602 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> |
|
603 UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) |
|
604 { |
|
605 PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4); |
|
606 if (!resultImpl) |
|
607 CRASH(); |
|
608 return resultImpl; |
|
609 } |
|
610 |
|
611 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> |
|
612 UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) |
|
613 { |
|
614 PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5); |
|
615 if (!resultImpl) |
|
616 CRASH(); |
|
617 return resultImpl; |
|
618 } |
|
619 |
|
620 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> |
|
621 UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) |
|
622 { |
|
623 PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6); |
|
624 if (!resultImpl) |
|
625 CRASH(); |
|
626 return resultImpl; |
|
627 } |
|
628 |
|
629 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7> |
|
630 UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7) |
|
631 { |
|
632 PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7); |
|
633 if (!resultImpl) |
|
634 CRASH(); |
|
635 return resultImpl; |
|
636 } |
|
637 |
|
638 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8> |
|
639 UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8) |
|
640 { |
|
641 PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8); |
|
642 if (!resultImpl) |
|
643 CRASH(); |
|
644 return resultImpl; |
|
645 } |
|
646 |
|
647 } // namespace JSC |
|
648 |
|
649 namespace WTF { |
|
650 |
|
651 template<typename T> struct DefaultHash; |
|
652 template<typename T> struct StrHash; |
|
653 |
|
654 template<> struct StrHash<JSC::UString::Rep*> { |
|
655 static unsigned hash(const JSC::UString::Rep* key) { return key->hash(); } |
|
656 static bool equal(const JSC::UString::Rep* a, const JSC::UString::Rep* b) { return ::equal(a, b); } |
|
657 static const bool safeToCompareToEmptyOrDeleted = false; |
|
658 }; |
|
659 |
|
660 template<> struct StrHash<RefPtr<JSC::UString::Rep> > : public StrHash<JSC::UString::Rep*> { |
|
661 using StrHash<JSC::UString::Rep*>::hash; |
|
662 static unsigned hash(const RefPtr<JSC::UString::Rep>& key) { return key->hash(); } |
|
663 using StrHash<JSC::UString::Rep*>::equal; |
|
664 static bool equal(const RefPtr<JSC::UString::Rep>& a, const RefPtr<JSC::UString::Rep>& b) { return ::equal(a.get(), b.get()); } |
|
665 static bool equal(const JSC::UString::Rep* a, const RefPtr<JSC::UString::Rep>& b) { return ::equal(a, b.get()); } |
|
666 static bool equal(const RefPtr<JSC::UString::Rep>& a, const JSC::UString::Rep* b) { return ::equal(a.get(), b); } |
|
667 |
|
668 static const bool safeToCompareToEmptyOrDeleted = false; |
|
669 }; |
|
670 |
|
671 template <> struct VectorTraits<JSC::UString> : SimpleClassVectorTraits |
|
672 { |
|
673 static const bool canInitializeWithMemset = true; |
|
674 }; |
|
675 |
|
676 } // namespace WTF |
|
677 |
|
678 #endif |