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