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) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
5 * Copyright (C) 2009 Google Inc. All rights reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 */
23
24#include "config.h"
25#include "UString.h"
26
27#include "JSGlobalObjectFunctions.h"
28#include "Collector.h"
29#include "dtoa.h"
30#include "Identifier.h"
31#include "Operations.h"
32#include <ctype.h>
33#include <limits.h>
34#include <limits>
35#include <math.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <wtf/ASCIICType.h>
40#include <wtf/Assertions.h>
41#include <wtf/MathExtras.h>
42#include <wtf/StringExtras.h>
43#include <wtf/Vector.h>
44#include <wtf/unicode/UTF8.h>
45#include <wtf/StringExtras.h>
46
47#if HAVE(STRINGS_H)
48#include <strings.h>
49#endif
50
51using namespace WTF;
52using namespace WTF::Unicode;
53using namespace std;
54
55namespace JSC {
56
57extern const double NaN;
58extern const double Inf;
59
60CString::CString(const char* c)
61 : m_length(strlen(s: c))
62 , m_data(new char[m_length + 1])
63{
64 memcpy(dest: m_data, src: c, n: m_length + 1);
65}
66
67CString::CString(const char* c, size_t length)
68 : m_length(length)
69 , m_data(new char[length + 1])
70{
71 memcpy(dest: m_data, src: c, n: m_length);
72 m_data[m_length] = 0;
73}
74
75CString::CString(const CString& b)
76{
77 m_length = b.m_length;
78 if (b.m_data) {
79 m_data = new char[m_length + 1];
80 memcpy(dest: m_data, src: b.m_data, n: m_length + 1);
81 } else
82 m_data = 0;
83}
84
85CString::~CString()
86{
87 delete [] m_data;
88}
89
90CString CString::adopt(char* c, size_t length)
91{
92 CString s;
93 s.m_data = c;
94 s.m_length = length;
95 return s;
96}
97
98CString& CString::append(const CString& t)
99{
100 char* n;
101 n = new char[m_length + t.m_length + 1];
102 if (m_length)
103 memcpy(dest: n, src: m_data, n: m_length);
104 if (t.m_length)
105 memcpy(dest: n + m_length, src: t.m_data, n: t.m_length);
106 m_length += t.m_length;
107 n[m_length] = 0;
108
109 delete [] m_data;
110 m_data = n;
111
112 return *this;
113}
114
115CString& CString::operator=(const char* c)
116{
117 if (m_data)
118 delete [] m_data;
119 m_length = strlen(s: c);
120 m_data = new char[m_length + 1];
121 memcpy(dest: m_data, src: c, n: m_length + 1);
122
123 return *this;
124}
125
126CString& CString::operator=(const CString& str)
127{
128 if (this == &str)
129 return *this;
130
131 if (m_data)
132 delete [] m_data;
133 m_length = str.m_length;
134 if (str.m_data) {
135 m_data = new char[m_length + 1];
136 memcpy(dest: m_data, src: str.m_data, n: m_length + 1);
137 } else
138 m_data = 0;
139
140 return *this;
141}
142
143bool operator==(const CString& c1, const CString& c2)
144{
145 size_t len = c1.size();
146 return len == c2.size() && (len == 0 || memcmp(s1: c1.c_str(), s2: c2.c_str(), n: len) == 0);
147}
148
149// These static strings are immutable, except for rc, whose initial value is chosen to
150// reduce the possibility of it becoming zero due to ref/deref not being thread-safe.
151static UChar sharedEmptyChar;
152UStringImpl* UStringImpl::s_null;
153UStringImpl* UStringImpl::s_empty;
154UString* UString::nullUString;
155
156void initializeUString()
157{
158 UStringImpl::s_null = new UStringImpl(0, 0, UStringImpl::ConstructStaticString);
159 UStringImpl::s_empty = new UStringImpl(&sharedEmptyChar, 0, UStringImpl::ConstructStaticString);
160 UString::nullUString = new UString;
161}
162
163static PassRefPtr<UString::Rep> createRep(const char* c)
164{
165 if (!c)
166 return &UString::Rep::null();
167
168 if (!c[0])
169 return &UString::Rep::empty();
170
171 size_t length = strlen(s: c);
172 UChar* d;
173 PassRefPtr<UStringImpl> result = UStringImpl::tryCreateUninitialized(length, output&: d);
174 if (!result)
175 return &UString::Rep::null();
176
177 for (size_t i = 0; i < length; i++)
178 d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
179 return result;
180}
181
182static inline PassRefPtr<UString::Rep> createRep(const char* c, int length)
183{
184 if (!c)
185 return &UString::Rep::null();
186
187 if (!length)
188 return &UString::Rep::empty();
189
190 UChar* d;
191 PassRefPtr<UStringImpl> result = UStringImpl::tryCreateUninitialized(length, output&: d);
192 if (!result)
193 return &UString::Rep::null();
194
195 for (int i = 0; i < length; i++)
196 d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
197 return result;
198}
199
200UString::UString(const char* c)
201 : m_rep(createRep(c))
202{
203}
204
205UString::UString(const char* c, int length)
206 : m_rep(createRep(c, length))
207{
208}
209
210UString::UString(const UChar* c, int length)
211{
212 if (length == 0)
213 m_rep = &Rep::empty();
214 else
215 m_rep = Rep::create(buffer: c, length);
216}
217
218UString UString::createFromUTF8(const char* string)
219{
220 if (!string)
221 return null();
222
223 size_t length = strlen(s: string);
224 Vector<UChar, 1024> buffer(length);
225 UChar* p = buffer.data();
226 if (conversionOK != convertUTF8ToUTF16(sourceStart: &string, sourceEnd: string + length, targetStart: &p, targetEnd: p + length))
227 return null();
228
229 return UString(buffer.data(), p - buffer.data());
230}
231
232UString UString::from(int i)
233{
234 UChar buf[1 + sizeof(i) * 3];
235 UChar* end = buf + sizeof(buf) / sizeof(UChar);
236 UChar* p = end;
237
238 if (i == 0)
239 *--p = '0';
240 else if (i == INT_MIN) {
241 char minBuf[1 + sizeof(i) * 3];
242 sprintf(s: minBuf, format: "%d", INT_MIN);
243 return UString(minBuf);
244 } else {
245 bool negative = false;
246 if (i < 0) {
247 negative = true;
248 i = -i;
249 }
250 while (i) {
251 *--p = static_cast<unsigned short>((i % 10) + '0');
252 i /= 10;
253 }
254 if (negative)
255 *--p = '-';
256 }
257
258 return UString(p, static_cast<int>(end - p));
259}
260
261UString UString::from(long long i)
262{
263 UChar buf[1 + sizeof(i) * 3];
264 UChar* end = buf + sizeof(buf) / sizeof(UChar);
265 UChar* p = end;
266
267 if (i == 0)
268 *--p = '0';
269 else if (i == std::numeric_limits<long long>::min()) {
270 char minBuf[1 + sizeof(i) * 3];
271#if OS(WINDOWS)
272 snprintf(minBuf, sizeof(minBuf) - 1, "%I64d", std::numeric_limits<long long>::min());
273#else
274 snprintf(s: minBuf, maxlen: sizeof(minBuf) - 1, format: "%lld", std::numeric_limits<long long>::min());
275#endif
276 return UString(minBuf);
277 } else {
278 bool negative = false;
279 if (i < 0) {
280 negative = true;
281 i = -i;
282 }
283 while (i) {
284 *--p = static_cast<unsigned short>((i % 10) + '0');
285 i /= 10;
286 }
287 if (negative)
288 *--p = '-';
289 }
290
291 return UString(p, static_cast<int>(end - p));
292}
293
294UString UString::from(unsigned int u)
295{
296 UChar buf[sizeof(u) * 3];
297 UChar* end = buf + sizeof(buf) / sizeof(UChar);
298 UChar* p = end;
299
300 if (u == 0)
301 *--p = '0';
302 else {
303 while (u) {
304 *--p = static_cast<unsigned short>((u % 10) + '0');
305 u /= 10;
306 }
307 }
308
309 return UString(p, static_cast<int>(end - p));
310}
311
312UString UString::from(long l)
313{
314 UChar buf[1 + sizeof(l) * 3];
315 UChar* end = buf + sizeof(buf) / sizeof(UChar);
316 UChar* p = end;
317
318 if (l == 0)
319 *--p = '0';
320 else if (l == LONG_MIN) {
321 char minBuf[1 + sizeof(l) * 3];
322 sprintf(s: minBuf, format: "%ld", LONG_MIN);
323 return UString(minBuf);
324 } else {
325 bool negative = false;
326 if (l < 0) {
327 negative = true;
328 l = -l;
329 }
330 while (l) {
331 *--p = static_cast<unsigned short>((l % 10) + '0');
332 l /= 10;
333 }
334 if (negative)
335 *--p = '-';
336 }
337
338 return UString(p, static_cast<int>(end - p));
339}
340
341UString UString::from(double d)
342{
343 DtoaBuffer buffer;
344 unsigned length;
345 doubleToStringInJavaScriptFormat(d, buffer, resultLength: &length);
346 return UString(buffer, length);
347}
348
349UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const
350{
351 m_rep->checkConsistency();
352
353 if (rangeCount == 1 && separatorCount == 0) {
354 int thisSize = size();
355 int position = substringRanges[0].position;
356 int length = substringRanges[0].length;
357 if (position <= 0 && length >= thisSize)
358 return *this;
359 return UString::Rep::create(rep: m_rep, offset: max(a: 0, b: position), length: min(a: thisSize, b: length));
360 }
361
362 int totalLength = 0;
363 for (int i = 0; i < rangeCount; i++)
364 totalLength += substringRanges[i].length;
365 for (int i = 0; i < separatorCount; i++)
366 totalLength += separators[i].size();
367
368 if (totalLength == 0)
369 return "";
370
371 UChar* buffer;
372 PassRefPtr<Rep> rep = Rep::tryCreateUninitialized(length: totalLength, output&: buffer);
373 if (!rep)
374 return null();
375
376 int maxCount = max(a: rangeCount, b: separatorCount);
377 int bufferPos = 0;
378 for (int i = 0; i < maxCount; i++) {
379 if (i < rangeCount) {
380 UStringImpl::copyChars(destination: buffer + bufferPos, source: data() + substringRanges[i].position, numCharacters: substringRanges[i].length);
381 bufferPos += substringRanges[i].length;
382 }
383 if (i < separatorCount) {
384 UStringImpl::copyChars(destination: buffer + bufferPos, source: separators[i].data(), numCharacters: separators[i].size());
385 bufferPos += separators[i].size();
386 }
387 }
388
389 return rep;
390}
391
392UString UString::replaceRange(int rangeStart, int rangeLength, const UString& replacement) const
393{
394 m_rep->checkConsistency();
395
396 int replacementLength = replacement.size();
397 int totalLength = size() - rangeLength + replacementLength;
398 if (totalLength == 0)
399 return "";
400
401 UChar* buffer;
402 PassRefPtr<Rep> rep = Rep::tryCreateUninitialized(length: totalLength, output&: buffer);
403 if (!rep)
404 return null();
405
406 UStringImpl::copyChars(destination: buffer, source: data(), numCharacters: rangeStart);
407 UStringImpl::copyChars(destination: buffer + rangeStart, source: replacement.data(), numCharacters: replacementLength);
408 int rangeEnd = rangeStart + rangeLength;
409 UStringImpl::copyChars(destination: buffer + rangeStart + replacementLength, source: data() + rangeEnd, numCharacters: size() - rangeEnd);
410
411 return rep;
412}
413
414bool UString::getCString(CStringBuffer& buffer) const
415{
416 int length = size();
417 int neededSize = length + 1;
418 buffer.resize(size: neededSize);
419 char* buf = buffer.data();
420
421 UChar ored = 0;
422 const UChar* p = data();
423 char* q = buf;
424 const UChar* limit = p + length;
425 while (p != limit) {
426 UChar c = p[0];
427 ored |= c;
428 *q = static_cast<char>(c);
429 ++p;
430 ++q;
431 }
432 *q = '\0';
433
434 return !(ored & 0xFF00);
435}
436
437char* UString::ascii() const
438{
439 static char* asciiBuffer = 0;
440
441 int length = size();
442 int neededSize = length + 1;
443 delete[] asciiBuffer;
444 asciiBuffer = new char[neededSize];
445
446 const UChar* p = data();
447 char* q = asciiBuffer;
448 const UChar* limit = p + length;
449 while (p != limit) {
450 *q = static_cast<char>(p[0]);
451 ++p;
452 ++q;
453 }
454 *q = '\0';
455
456 return asciiBuffer;
457}
458
459UString& UString::operator=(const char* c)
460{
461 if (!c) {
462 m_rep = &Rep::null();
463 return *this;
464 }
465
466 if (!c[0]) {
467 m_rep = &Rep::empty();
468 return *this;
469 }
470
471 int l = static_cast<int>(strlen(s: c));
472 UChar* d = 0;
473 m_rep = Rep::tryCreateUninitialized(length: l, output&: d);
474 if (m_rep) {
475 for (int i = 0; i < l; i++)
476 d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
477 } else
478 makeNull();
479
480 return *this;
481}
482
483bool UString::is8Bit() const
484{
485 const UChar* u = data();
486 const UChar* limit = u + size();
487 while (u < limit) {
488 if (u[0] > 0xFF)
489 return false;
490 ++u;
491 }
492
493 return true;
494}
495
496UChar UString::operator[](int pos) const
497{
498 if (pos >= size())
499 return '\0';
500 return data()[pos];
501}
502
503double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const
504{
505 if (size() == 1) {
506 UChar c = data()[0];
507 if (isASCIIDigit(c))
508 return c - '0';
509 if (isASCIISpace(c) && tolerateEmptyString)
510 return 0;
511 return NaN;
512 }
513
514 // FIXME: If tolerateTrailingJunk is true, then we want to tolerate non-8-bit junk
515 // after the number, so this is too strict a check.
516 CStringBuffer s;
517 if (!getCString(buffer&: s))
518 return NaN;
519 const char* c = s.data();
520
521 // skip leading white space
522 while (isASCIISpace(c: *c))
523 c++;
524
525 // empty string ?
526 if (*c == '\0')
527 return tolerateEmptyString ? 0.0 : NaN;
528
529 double d;
530
531 // hex number ?
532 if (*c == '0' && (*(c + 1) == 'x' || *(c + 1) == 'X')) {
533 const char* firstDigitPosition = c + 2;
534 c++;
535 d = 0.0;
536 while (*(++c)) {
537 if (*c >= '0' && *c <= '9')
538 d = d * 16.0 + *c - '0';
539 else if ((*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f'))
540 d = d * 16.0 + (*c & 0xdf) - 'A' + 10.0;
541 else
542 break;
543 }
544
545 if (d >= mantissaOverflowLowerBound)
546 d = parseIntOverflow(firstDigitPosition, length: c - firstDigitPosition, radix: 16);
547 } else {
548 // regular number ?
549 char* end;
550 d = WTF::strtod(s00: c, se: &end);
551 if ((d != 0.0 || end != c) && d != Inf && d != -Inf) {
552 c = end;
553 } else {
554 double sign = 1.0;
555
556 if (*c == '+')
557 c++;
558 else if (*c == '-') {
559 sign = -1.0;
560 c++;
561 }
562
563 // We used strtod() to do the conversion. However, strtod() handles
564 // infinite values slightly differently than JavaScript in that it
565 // converts the string "inf" with any capitalization to infinity,
566 // whereas the ECMA spec requires that it be converted to NaN.
567
568 if (c[0] == 'I' && c[1] == 'n' && c[2] == 'f' && c[3] == 'i' && c[4] == 'n' && c[5] == 'i' && c[6] == 't' && c[7] == 'y') {
569 d = sign * Inf;
570 c += 8;
571 } else if ((d == Inf || d == -Inf) && *c != 'I' && *c != 'i')
572 c = end;
573 else
574 return NaN;
575 }
576 }
577
578 // allow trailing white space
579 while (isASCIISpace(c: *c))
580 c++;
581 // don't allow anything after - unless tolerant=true
582 if (!tolerateTrailingJunk && *c != '\0')
583 d = NaN;
584
585 return d;
586}
587
588double UString::toDouble(bool tolerateTrailingJunk) const
589{
590 return toDouble(tolerateTrailingJunk, tolerateEmptyString: true);
591}
592
593double UString::toDouble() const
594{
595 return toDouble(tolerateTrailingJunk: false, tolerateEmptyString: true);
596}
597
598uint32_t UString::toUInt32(bool* ok) const
599{
600 double d = toDouble();
601 bool b = true;
602
603 if (d != static_cast<uint32_t>(d)) {
604 b = false;
605 d = 0;
606 }
607
608 if (ok)
609 *ok = b;
610
611 return static_cast<uint32_t>(d);
612}
613
614uint32_t UString::toUInt32(bool* ok, bool tolerateEmptyString) const
615{
616 double d = toDouble(tolerateTrailingJunk: false, tolerateEmptyString);
617 bool b = true;
618
619 if (d != static_cast<uint32_t>(d)) {
620 b = false;
621 d = 0;
622 }
623
624 if (ok)
625 *ok = b;
626
627 return static_cast<uint32_t>(d);
628}
629
630uint32_t UString::toStrictUInt32(bool* ok) const
631{
632 if (ok)
633 *ok = false;
634
635 // Empty string is not OK.
636 int len = m_rep->size();
637 if (len == 0)
638 return 0;
639 const UChar* p = m_rep->data();
640 unsigned short c = p[0];
641
642 // If the first digit is 0, only 0 itself is OK.
643 if (c == '0') {
644 if (len == 1 && ok)
645 *ok = true;
646 return 0;
647 }
648
649 // Convert to UInt32, checking for overflow.
650 uint32_t i = 0;
651 while (1) {
652 // Process character, turning it into a digit.
653 if (c < '0' || c > '9')
654 return 0;
655 const unsigned d = c - '0';
656
657 // Multiply by 10, checking for overflow out of 32 bits.
658 if (i > 0xFFFFFFFFU / 10)
659 return 0;
660 i *= 10;
661
662 // Add in the digit, checking for overflow out of 32 bits.
663 const unsigned max = 0xFFFFFFFFU - d;
664 if (i > max)
665 return 0;
666 i += d;
667
668 // Handle end of string.
669 if (--len == 0) {
670 if (ok)
671 *ok = true;
672 return i;
673 }
674
675 // Get next character.
676 c = *(++p);
677 }
678}
679
680int UString::find(const UString& f, int pos) const
681{
682 int fsz = f.size();
683
684 if (pos < 0)
685 pos = 0;
686
687 if (fsz == 1) {
688 UChar ch = f[0];
689 const UChar* end = data() + size();
690 for (const UChar* c = data() + pos; c < end; c++) {
691 if (*c == ch)
692 return static_cast<int>(c - data());
693 }
694 return -1;
695 }
696
697 int sz = size();
698 if (sz < fsz)
699 return -1;
700 if (fsz == 0)
701 return pos;
702 const UChar* end = data() + sz - fsz;
703 int fsizeminusone = (fsz - 1) * sizeof(UChar);
704 const UChar* fdata = f.data();
705 unsigned short fchar = fdata[0];
706 ++fdata;
707 for (const UChar* c = data() + pos; c <= end; c++) {
708 if (c[0] == fchar && !memcmp(s1: c + 1, s2: fdata, n: fsizeminusone))
709 return static_cast<int>(c - data());
710 }
711
712 return -1;
713}
714
715int UString::find(UChar ch, int pos) const
716{
717 if (pos < 0)
718 pos = 0;
719 const UChar* end = data() + size();
720 for (const UChar* c = data() + pos; c < end; c++) {
721 if (*c == ch)
722 return static_cast<int>(c - data());
723 }
724
725 return -1;
726}
727
728int UString::rfind(const UString& f, int pos) const
729{
730 int sz = size();
731 int fsz = f.size();
732 if (sz < fsz)
733 return -1;
734 if (pos < 0)
735 pos = 0;
736 if (pos > sz - fsz)
737 pos = sz - fsz;
738 if (fsz == 0)
739 return pos;
740 int fsizeminusone = (fsz - 1) * sizeof(UChar);
741 const UChar* fdata = f.data();
742 for (const UChar* c = data() + pos; c >= data(); c--) {
743 if (*c == *fdata && !memcmp(s1: c + 1, s2: fdata + 1, n: fsizeminusone))
744 return static_cast<int>(c - data());
745 }
746
747 return -1;
748}
749
750int UString::rfind(UChar ch, int pos) const
751{
752 if (isEmpty())
753 return -1;
754 if (pos + 1 >= size())
755 pos = size() - 1;
756 for (const UChar* c = data() + pos; c >= data(); c--) {
757 if (*c == ch)
758 return static_cast<int>(c - data());
759 }
760
761 return -1;
762}
763
764UString UString::substr(int pos, int len) const
765{
766 int s = size();
767
768 if (pos < 0)
769 pos = 0;
770 else if (pos >= s)
771 pos = s;
772 if (len < 0)
773 len = s;
774 if (pos + len >= s)
775 len = s - pos;
776
777 if (pos == 0 && len == s)
778 return *this;
779
780 return UString(Rep::create(rep: m_rep, offset: pos, length: len));
781}
782
783bool operator==(const UString& s1, const char *s2)
784{
785 if (s2 == 0)
786 return s1.isEmpty();
787
788 const UChar* u = s1.data();
789 const UChar* uend = u + s1.size();
790 while (u != uend && *s2) {
791 if (u[0] != (unsigned char)*s2)
792 return false;
793 s2++;
794 u++;
795 }
796
797 return u == uend && *s2 == 0;
798}
799
800bool operator<(const UString& s1, const UString& s2)
801{
802 const int l1 = s1.size();
803 const int l2 = s2.size();
804 const int lmin = l1 < l2 ? l1 : l2;
805 const UChar* c1 = s1.data();
806 const UChar* c2 = s2.data();
807 int l = 0;
808 while (l < lmin && *c1 == *c2) {
809 c1++;
810 c2++;
811 l++;
812 }
813 if (l < lmin)
814 return (c1[0] < c2[0]);
815
816 return (l1 < l2);
817}
818
819bool operator>(const UString& s1, const UString& s2)
820{
821 const int l1 = s1.size();
822 const int l2 = s2.size();
823 const int lmin = l1 < l2 ? l1 : l2;
824 const UChar* c1 = s1.data();
825 const UChar* c2 = s2.data();
826 int l = 0;
827 while (l < lmin && *c1 == *c2) {
828 c1++;
829 c2++;
830 l++;
831 }
832 if (l < lmin)
833 return (c1[0] > c2[0]);
834
835 return (l1 > l2);
836}
837
838int compare(const UString& s1, const UString& s2)
839{
840 const int l1 = s1.size();
841 const int l2 = s2.size();
842 const int lmin = l1 < l2 ? l1 : l2;
843 const UChar* c1 = s1.data();
844 const UChar* c2 = s2.data();
845 int l = 0;
846 while (l < lmin && *c1 == *c2) {
847 c1++;
848 c2++;
849 l++;
850 }
851
852 if (l < lmin)
853 return (c1[0] > c2[0]) ? 1 : -1;
854
855 if (l1 == l2)
856 return 0;
857
858 return (l1 > l2) ? 1 : -1;
859}
860
861#if OS(SOLARIS) && COMPILER(SUNCC)
862// Signature must match that of UStringImpl.h, otherwise the linker complains about undefined symbol.
863bool equal(const UStringImpl* r, const UStringImpl* b)
864#else
865bool equal(const UString::Rep* r, const UString::Rep* b)
866#endif
867{
868 int length = r->size();
869 if (length != b->size())
870 return false;
871 const UChar* d = r->data();
872 const UChar* s = b->data();
873 for (int i = 0; i != length; ++i) {
874 if (d[i] != s[i])
875 return false;
876 }
877 return true;
878}
879
880CString UString::UTF8String(bool strict) const
881{
882 // Allocate a buffer big enough to hold all the characters.
883 const int length = size();
884 Vector<char, 1024> buffer(length * 3);
885
886 // Convert to runs of 8-bit characters.
887 char* p = buffer.data();
888 const UChar* d = reinterpret_cast<const UChar*>(&data()[0]);
889 ConversionResult result = convertUTF16ToUTF8(sourceStart: &d, sourceEnd: d + length, targetStart: &p, targetEnd: p + buffer.size(), strict);
890 if (result != conversionOK)
891 return CString();
892
893 return CString(buffer.data(), p - buffer.data());
894}
895
896// For use in error handling code paths -- having this not be inlined helps avoid PIC branches to fetch the global on Mac OS X.
897NEVER_INLINE void UString::makeNull()
898{
899 m_rep = &Rep::null();
900}
901
902// For use in error handling code paths -- having this not be inlined helps avoid PIC branches to fetch the global on Mac OS X.
903NEVER_INLINE UString::Rep* UString::nullRep()
904{
905 return &Rep::null();
906}
907
908} // namespace JSC
909

source code of qtscript/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UString.cpp