source: webkit/trunk/JavaScriptCore/runtime/UString.cpp@ 54510

Last change on this file since 54510 was 54464, checked in by [email protected], 15 years ago

Change UStringImpl::create to CRASH if the string cannot be allocated,
rather than returning a null string (which will behave like a zero-length
string if used).

Reviewed by Geoff Garen.

Also move createRep function from UString to become new overloaded
UStringImpl::create methods. In doing so, bring their behaviour closer to
being in line with WebCore::StringImpl, in removing the behaviour that they
can be used to produce null UStrings (ASSERT the char* provided is non-null).
This behaviour of converting null C-strings to null UStrings is inefficient
(cmompared to just using UString::null()), incompatible with WebCore::StringImpl's
behaviour, and may generate unexpected behaviour, since in many cases a null
UString can be used like an empty string.

With these changes UStringImpl need not have a concept of null impls, we can
start transitioning this to become an implementation detail of UString, that
internally it chooses to use a null-object rather than an actually zero impl
pointer.

(JSC::Debugger::recompileAllJSFunctions):

  • debugger/DebuggerCallFrame.cpp:

(JSC::DebuggerCallFrame::calculatedFunctionName):

  • parser/Parser.cpp:

(JSC::Parser::parse):

  • profiler/Profile.cpp:

(JSC::Profile::Profile):

  • profiler/ProfileGenerator.cpp:

(JSC::ProfileGenerator::stopProfiling):

  • runtime/Error.cpp:

(JSC::Error::create):
(JSC::throwError):

  • runtime/ExceptionHelpers.cpp:

(JSC::createError):

  • runtime/Identifier.cpp:

(JSC::Identifier::add):

  • runtime/PropertyNameArray.cpp:

(JSC::PropertyNameArray::add):

  • runtime/UString.cpp:

(JSC::initializeUString):
(JSC::UString::UString):
(JSC::UString::operator=):

  • runtime/UString.h:

(JSC::UString::isNull):
(JSC::UString::null):
(JSC::UString::rep):
(JSC::UString::UString):

  • runtime/UStringImpl.cpp:

(JSC::UStringImpl::create):

  • runtime/UStringImpl.h:
  • Property svn:eol-style set to native
File size: 20.1 KB
Line 
1/*
2 * Copyright (C) 1999-2000 Harri Porten ([email protected])
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
4 * Copyright (C) 2007 Cameron Zwarich ([email protected])
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(c))
62 , m_data(new char[m_length + 1])
63{
64 memcpy(m_data, c, 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(m_data, c, 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(m_data, b.m_data, 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(n, m_data, m_length);
104 if (t.m_length)
105 memcpy(n + m_length, t.m_data, 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(c);
120 m_data = new char[m_length + 1];
121 memcpy(m_data, c, 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(m_data, str.m_data, 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(c1.c_str(), c2.c_str(), 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_empty;
153
154UString::Rep* UString::s_nullRep;
155UString* UString::s_nullUString;
156
157void initializeUString()
158{
159 UStringImpl::s_empty = new UStringImpl(&sharedEmptyChar, 0, UStringImpl::ConstructStaticString);
160
161 UString::s_nullRep = new UStringImpl(0, 0, UStringImpl::ConstructStaticString);
162 UString::s_nullUString = new UString;
163}
164
165UString::UString(const char* c)
166 : m_rep(Rep::create(c))
167{
168}
169
170UString::UString(const char* c, int length)
171 : m_rep(Rep::create(c, length))
172{
173}
174
175UString::UString(const UChar* c, int length)
176{
177 if (length == 0)
178 m_rep = &Rep::empty();
179 else
180 m_rep = Rep::create(c, length);
181}
182
183UString UString::createFromUTF8(const char* string)
184{
185 if (!string)
186 return null();
187
188 size_t length = strlen(string);
189 Vector<UChar, 1024> buffer(length);
190 UChar* p = buffer.data();
191 if (conversionOK != convertUTF8ToUTF16(&string, string + length, &p, p + length))
192 return null();
193
194 return UString(buffer.data(), p - buffer.data());
195}
196
197UString UString::from(int i)
198{
199 UChar buf[1 + sizeof(i) * 3];
200 UChar* end = buf + sizeof(buf) / sizeof(UChar);
201 UChar* p = end;
202
203 if (i == 0)
204 *--p = '0';
205 else if (i == INT_MIN) {
206 char minBuf[1 + sizeof(i) * 3];
207 sprintf(minBuf, "%d", INT_MIN);
208 return UString(minBuf);
209 } else {
210 bool negative = false;
211 if (i < 0) {
212 negative = true;
213 i = -i;
214 }
215 while (i) {
216 *--p = static_cast<unsigned short>((i % 10) + '0');
217 i /= 10;
218 }
219 if (negative)
220 *--p = '-';
221 }
222
223 return UString(p, static_cast<int>(end - p));
224}
225
226UString UString::from(long long i)
227{
228 UChar buf[1 + sizeof(i) * 3];
229 UChar* end = buf + sizeof(buf) / sizeof(UChar);
230 UChar* p = end;
231
232 if (i == 0)
233 *--p = '0';
234 else if (i == std::numeric_limits<long long>::min()) {
235 char minBuf[1 + sizeof(i) * 3];
236#if OS(WINDOWS)
237 snprintf(minBuf, sizeof(minBuf) - 1, "%I64d", std::numeric_limits<long long>::min());
238#else
239 snprintf(minBuf, sizeof(minBuf) - 1, "%lld", std::numeric_limits<long long>::min());
240#endif
241 return UString(minBuf);
242 } else {
243 bool negative = false;
244 if (i < 0) {
245 negative = true;
246 i = -i;
247 }
248 while (i) {
249 *--p = static_cast<unsigned short>((i % 10) + '0');
250 i /= 10;
251 }
252 if (negative)
253 *--p = '-';
254 }
255
256 return UString(p, static_cast<int>(end - p));
257}
258
259UString UString::from(unsigned int u)
260{
261 UChar buf[sizeof(u) * 3];
262 UChar* end = buf + sizeof(buf) / sizeof(UChar);
263 UChar* p = end;
264
265 if (u == 0)
266 *--p = '0';
267 else {
268 while (u) {
269 *--p = static_cast<unsigned short>((u % 10) + '0');
270 u /= 10;
271 }
272 }
273
274 return UString(p, static_cast<int>(end - p));
275}
276
277UString UString::from(long l)
278{
279 UChar buf[1 + sizeof(l) * 3];
280 UChar* end = buf + sizeof(buf) / sizeof(UChar);
281 UChar* p = end;
282
283 if (l == 0)
284 *--p = '0';
285 else if (l == LONG_MIN) {
286 char minBuf[1 + sizeof(l) * 3];
287 sprintf(minBuf, "%ld", LONG_MIN);
288 return UString(minBuf);
289 } else {
290 bool negative = false;
291 if (l < 0) {
292 negative = true;
293 l = -l;
294 }
295 while (l) {
296 *--p = static_cast<unsigned short>((l % 10) + '0');
297 l /= 10;
298 }
299 if (negative)
300 *--p = '-';
301 }
302
303 return UString(p, static_cast<int>(end - p));
304}
305
306UString UString::from(double d)
307{
308 DtoaBuffer buffer;
309 unsigned length;
310 doubleToStringInJavaScriptFormat(d, buffer, &length);
311 return UString(buffer, length);
312}
313
314UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const
315{
316 m_rep->checkConsistency();
317
318 if (rangeCount == 1 && separatorCount == 0) {
319 int thisSize = size();
320 int position = substringRanges[0].position;
321 int length = substringRanges[0].length;
322 if (position <= 0 && length >= thisSize)
323 return *this;
324 return UString::Rep::create(m_rep, max(0, position), min(thisSize, length));
325 }
326
327 int totalLength = 0;
328 for (int i = 0; i < rangeCount; i++)
329 totalLength += substringRanges[i].length;
330 for (int i = 0; i < separatorCount; i++)
331 totalLength += separators[i].size();
332
333 if (totalLength == 0)
334 return "";
335
336 UChar* buffer;
337 PassRefPtr<Rep> rep = Rep::tryCreateUninitialized(totalLength, buffer);
338 if (!rep)
339 return null();
340
341 int maxCount = max(rangeCount, separatorCount);
342 int bufferPos = 0;
343 for (int i = 0; i < maxCount; i++) {
344 if (i < rangeCount) {
345 UStringImpl::copyChars(buffer + bufferPos, data() + substringRanges[i].position, substringRanges[i].length);
346 bufferPos += substringRanges[i].length;
347 }
348 if (i < separatorCount) {
349 UStringImpl::copyChars(buffer + bufferPos, separators[i].data(), separators[i].size());
350 bufferPos += separators[i].size();
351 }
352 }
353
354 return rep;
355}
356
357UString UString::replaceRange(int rangeStart, int rangeLength, const UString& replacement) const
358{
359 m_rep->checkConsistency();
360
361 int replacementLength = replacement.size();
362 int totalLength = size() - rangeLength + replacementLength;
363 if (totalLength == 0)
364 return "";
365
366 UChar* buffer;
367 PassRefPtr<Rep> rep = Rep::tryCreateUninitialized(totalLength, buffer);
368 if (!rep)
369 return null();
370
371 UStringImpl::copyChars(buffer, data(), rangeStart);
372 UStringImpl::copyChars(buffer + rangeStart, replacement.data(), replacementLength);
373 int rangeEnd = rangeStart + rangeLength;
374 UStringImpl::copyChars(buffer + rangeStart + replacementLength, data() + rangeEnd, size() - rangeEnd);
375
376 return rep;
377}
378
379bool UString::getCString(CStringBuffer& buffer) const
380{
381 int length = size();
382 int neededSize = length + 1;
383 buffer.resize(neededSize);
384 char* buf = buffer.data();
385
386 UChar ored = 0;
387 const UChar* p = data();
388 char* q = buf;
389 const UChar* limit = p + length;
390 while (p != limit) {
391 UChar c = p[0];
392 ored |= c;
393 *q = static_cast<char>(c);
394 ++p;
395 ++q;
396 }
397 *q = '\0';
398
399 return !(ored & 0xFF00);
400}
401
402char* UString::ascii() const
403{
404 static char* asciiBuffer = 0;
405
406 int length = size();
407 int neededSize = length + 1;
408 delete[] asciiBuffer;
409 asciiBuffer = new char[neededSize];
410
411 const UChar* p = data();
412 char* q = asciiBuffer;
413 const UChar* limit = p + length;
414 while (p != limit) {
415 *q = static_cast<char>(p[0]);
416 ++p;
417 ++q;
418 }
419 *q = '\0';
420
421 return asciiBuffer;
422}
423
424UString& UString::operator=(const char* c)
425{
426 if (!c) {
427 m_rep = s_nullRep;
428 return *this;
429 }
430
431 if (!c[0]) {
432 m_rep = &Rep::empty();
433 return *this;
434 }
435
436 int l = static_cast<int>(strlen(c));
437 UChar* d = 0;
438 m_rep = Rep::tryCreateUninitialized(l, d);
439 if (m_rep) {
440 for (int i = 0; i < l; i++)
441 d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
442 } else
443 m_rep = s_nullRep;;
444
445 return *this;
446}
447
448bool UString::is8Bit() const
449{
450 const UChar* u = data();
451 const UChar* limit = u + size();
452 while (u < limit) {
453 if (u[0] > 0xFF)
454 return false;
455 ++u;
456 }
457
458 return true;
459}
460
461UChar UString::operator[](int pos) const
462{
463 if (pos >= size())
464 return '\0';
465 return data()[pos];
466}
467
468double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const
469{
470 if (size() == 1) {
471 UChar c = data()[0];
472 if (isASCIIDigit(c))
473 return c - '0';
474 if (isASCIISpace(c) && tolerateEmptyString)
475 return 0;
476 return NaN;
477 }
478
479 // FIXME: If tolerateTrailingJunk is true, then we want to tolerate non-8-bit junk
480 // after the number, so this is too strict a check.
481 CStringBuffer s;
482 if (!getCString(s))
483 return NaN;
484 const char* c = s.data();
485
486 // skip leading white space
487 while (isASCIISpace(*c))
488 c++;
489
490 // empty string ?
491 if (*c == '\0')
492 return tolerateEmptyString ? 0.0 : NaN;
493
494 double d;
495
496 // hex number ?
497 if (*c == '0' && (*(c + 1) == 'x' || *(c + 1) == 'X')) {
498 const char* firstDigitPosition = c + 2;
499 c++;
500 d = 0.0;
501 while (*(++c)) {
502 if (*c >= '0' && *c <= '9')
503 d = d * 16.0 + *c - '0';
504 else if ((*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f'))
505 d = d * 16.0 + (*c & 0xdf) - 'A' + 10.0;
506 else
507 break;
508 }
509
510 if (d >= mantissaOverflowLowerBound)
511 d = parseIntOverflow(firstDigitPosition, c - firstDigitPosition, 16);
512 } else {
513 // regular number ?
514 char* end;
515 d = WTF::strtod(c, &end);
516 if ((d != 0.0 || end != c) && d != Inf && d != -Inf) {
517 c = end;
518 } else {
519 double sign = 1.0;
520
521 if (*c == '+')
522 c++;
523 else if (*c == '-') {
524 sign = -1.0;
525 c++;
526 }
527
528 // We used strtod() to do the conversion. However, strtod() handles
529 // infinite values slightly differently than JavaScript in that it
530 // converts the string "inf" with any capitalization to infinity,
531 // whereas the ECMA spec requires that it be converted to NaN.
532
533 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') {
534 d = sign * Inf;
535 c += 8;
536 } else if ((d == Inf || d == -Inf) && *c != 'I' && *c != 'i')
537 c = end;
538 else
539 return NaN;
540 }
541 }
542
543 // allow trailing white space
544 while (isASCIISpace(*c))
545 c++;
546 // don't allow anything after - unless tolerant=true
547 if (!tolerateTrailingJunk && *c != '\0')
548 d = NaN;
549
550 return d;
551}
552
553double UString::toDouble(bool tolerateTrailingJunk) const
554{
555 return toDouble(tolerateTrailingJunk, true);
556}
557
558double UString::toDouble() const
559{
560 return toDouble(false, true);
561}
562
563uint32_t UString::toUInt32(bool* ok) const
564{
565 double d = toDouble();
566 bool b = true;
567
568 if (d != static_cast<uint32_t>(d)) {
569 b = false;
570 d = 0;
571 }
572
573 if (ok)
574 *ok = b;
575
576 return static_cast<uint32_t>(d);
577}
578
579uint32_t UString::toUInt32(bool* ok, bool tolerateEmptyString) const
580{
581 double d = toDouble(false, tolerateEmptyString);
582 bool b = true;
583
584 if (d != static_cast<uint32_t>(d)) {
585 b = false;
586 d = 0;
587 }
588
589 if (ok)
590 *ok = b;
591
592 return static_cast<uint32_t>(d);
593}
594
595uint32_t UString::toStrictUInt32(bool* ok) const
596{
597 if (ok)
598 *ok = false;
599
600 // Empty string is not OK.
601 int len = m_rep->size();
602 if (len == 0)
603 return 0;
604 const UChar* p = m_rep->data();
605 unsigned short c = p[0];
606
607 // If the first digit is 0, only 0 itself is OK.
608 if (c == '0') {
609 if (len == 1 && ok)
610 *ok = true;
611 return 0;
612 }
613
614 // Convert to UInt32, checking for overflow.
615 uint32_t i = 0;
616 while (1) {
617 // Process character, turning it into a digit.
618 if (c < '0' || c > '9')
619 return 0;
620 const unsigned d = c - '0';
621
622 // Multiply by 10, checking for overflow out of 32 bits.
623 if (i > 0xFFFFFFFFU / 10)
624 return 0;
625 i *= 10;
626
627 // Add in the digit, checking for overflow out of 32 bits.
628 const unsigned max = 0xFFFFFFFFU - d;
629 if (i > max)
630 return 0;
631 i += d;
632
633 // Handle end of string.
634 if (--len == 0) {
635 if (ok)
636 *ok = true;
637 return i;
638 }
639
640 // Get next character.
641 c = *(++p);
642 }
643}
644
645int UString::find(const UString& f, int pos) const
646{
647 int fsz = f.size();
648
649 if (pos < 0)
650 pos = 0;
651
652 if (fsz == 1) {
653 UChar ch = f[0];
654 const UChar* end = data() + size();
655 for (const UChar* c = data() + pos; c < end; c++) {
656 if (*c == ch)
657 return static_cast<int>(c - data());
658 }
659 return -1;
660 }
661
662 int sz = size();
663 if (sz < fsz)
664 return -1;
665 if (fsz == 0)
666 return pos;
667 const UChar* end = data() + sz - fsz;
668 int fsizeminusone = (fsz - 1) * sizeof(UChar);
669 const UChar* fdata = f.data();
670 unsigned short fchar = fdata[0];
671 ++fdata;
672 for (const UChar* c = data() + pos; c <= end; c++) {
673 if (c[0] == fchar && !memcmp(c + 1, fdata, fsizeminusone))
674 return static_cast<int>(c - data());
675 }
676
677 return -1;
678}
679
680int UString::find(UChar ch, int pos) const
681{
682 if (pos < 0)
683 pos = 0;
684 const UChar* end = data() + size();
685 for (const UChar* c = data() + pos; c < end; c++) {
686 if (*c == ch)
687 return static_cast<int>(c - data());
688 }
689
690 return -1;
691}
692
693int UString::rfind(const UString& f, int pos) const
694{
695 int sz = size();
696 int fsz = f.size();
697 if (sz < fsz)
698 return -1;
699 if (pos < 0)
700 pos = 0;
701 if (pos > sz - fsz)
702 pos = sz - fsz;
703 if (fsz == 0)
704 return pos;
705 int fsizeminusone = (fsz - 1) * sizeof(UChar);
706 const UChar* fdata = f.data();
707 for (const UChar* c = data() + pos; c >= data(); c--) {
708 if (*c == *fdata && !memcmp(c + 1, fdata + 1, fsizeminusone))
709 return static_cast<int>(c - data());
710 }
711
712 return -1;
713}
714
715int UString::rfind(UChar ch, int pos) const
716{
717 if (isEmpty())
718 return -1;
719 if (pos + 1 >= size())
720 pos = size() - 1;
721 for (const UChar* c = data() + pos; c >= data(); c--) {
722 if (*c == ch)
723 return static_cast<int>(c - data());
724 }
725
726 return -1;
727}
728
729UString UString::substr(int pos, int len) const
730{
731 int s = size();
732
733 if (pos < 0)
734 pos = 0;
735 else if (pos >= s)
736 pos = s;
737 if (len < 0)
738 len = s;
739 if (pos + len >= s)
740 len = s - pos;
741
742 if (pos == 0 && len == s)
743 return *this;
744
745 return UString(Rep::create(m_rep, pos, len));
746}
747
748bool operator==(const UString& s1, const char *s2)
749{
750 if (s2 == 0)
751 return s1.isEmpty();
752
753 const UChar* u = s1.data();
754 const UChar* uend = u + s1.size();
755 while (u != uend && *s2) {
756 if (u[0] != (unsigned char)*s2)
757 return false;
758 s2++;
759 u++;
760 }
761
762 return u == uend && *s2 == 0;
763}
764
765bool operator<(const UString& s1, const UString& s2)
766{
767 const int l1 = s1.size();
768 const int l2 = s2.size();
769 const int lmin = l1 < l2 ? l1 : l2;
770 const UChar* c1 = s1.data();
771 const UChar* c2 = s2.data();
772 int l = 0;
773 while (l < lmin && *c1 == *c2) {
774 c1++;
775 c2++;
776 l++;
777 }
778 if (l < lmin)
779 return (c1[0] < c2[0]);
780
781 return (l1 < l2);
782}
783
784bool operator>(const UString& s1, const UString& s2)
785{
786 const int l1 = s1.size();
787 const int l2 = s2.size();
788 const int lmin = l1 < l2 ? l1 : l2;
789 const UChar* c1 = s1.data();
790 const UChar* c2 = s2.data();
791 int l = 0;
792 while (l < lmin && *c1 == *c2) {
793 c1++;
794 c2++;
795 l++;
796 }
797 if (l < lmin)
798 return (c1[0] > c2[0]);
799
800 return (l1 > l2);
801}
802
803int compare(const UString& s1, const UString& s2)
804{
805 const int l1 = s1.size();
806 const int l2 = s2.size();
807 const int lmin = l1 < l2 ? l1 : l2;
808 const UChar* c1 = s1.data();
809 const UChar* c2 = s2.data();
810 int l = 0;
811 while (l < lmin && *c1 == *c2) {
812 c1++;
813 c2++;
814 l++;
815 }
816
817 if (l < lmin)
818 return (c1[0] > c2[0]) ? 1 : -1;
819
820 if (l1 == l2)
821 return 0;
822
823 return (l1 > l2) ? 1 : -1;
824}
825
826bool equal(const UString::Rep* r, const UString::Rep* b)
827{
828 int length = r->size();
829 if (length != b->size())
830 return false;
831 const UChar* d = r->data();
832 const UChar* s = b->data();
833 for (int i = 0; i != length; ++i) {
834 if (d[i] != s[i])
835 return false;
836 }
837 return true;
838}
839
840CString UString::UTF8String(bool strict) const
841{
842 // Allocate a buffer big enough to hold all the characters.
843 const int length = size();
844 Vector<char, 1024> buffer(length * 3);
845
846 // Convert to runs of 8-bit characters.
847 char* p = buffer.data();
848 const UChar* d = reinterpret_cast<const UChar*>(&data()[0]);
849 ConversionResult result = convertUTF16ToUTF8(&d, d + length, &p, p + buffer.size(), strict);
850 if (result != conversionOK)
851 return CString();
852
853 return CString(buffer.data(), p - buffer.data());
854}
855
856} // namespace JSC
Note: See TracBrowser for help on using the repository browser.