#include <stdlib.h>
#include <wtf/ASCIICType.h>
#include <wtf/Assertions.h>
-#include <wtf/DecimalNumber.h>
#include <wtf/MathExtras.h>
#include <wtf/StringExtras.h>
#include <wtf/Vector.h>
+#include <wtf/dtoa.h>
#include <wtf/unicode/UTF8.h>
#if HAVE(STRINGS_H)
namespace JSC {
-extern const double NaN;
-extern const double Inf;
-
COMPILE_ASSERT(sizeof(UString) == sizeof(void*), UString_should_stay_small);
// Construct a string with UTF-16 data.
}
// Construct a string with latin1 data.
-UString::UString(const char* characters, unsigned length)
+UString::UString(const LChar* characters, unsigned length)
: m_impl(characters ? StringImpl::create(characters, length) : 0)
{
}
+UString::UString(const char* characters, unsigned length)
+ : m_impl(characters ? StringImpl::create(reinterpret_cast<const LChar*>(characters), length) : 0)
+{
+}
+
// Construct a string with latin1 data, from a null-terminated source.
-UString::UString(const char* characters)
+UString::UString(const LChar* characters)
: m_impl(characters ? StringImpl::create(characters) : 0)
{
}
+UString::UString(const char* characters)
+ : m_impl(characters ? StringImpl::create(reinterpret_cast<const LChar*>(characters)) : 0)
+{
+}
+
UString UString::number(int i)
{
- UChar buf[1 + sizeof(i) * 3];
- UChar* end = buf + WTF_ARRAY_LENGTH(buf);
- UChar* p = end;
+ LChar buf[1 + sizeof(i) * 3];
+ LChar* end = buf + WTF_ARRAY_LENGTH(buf);
+ LChar* p = end;
if (i == 0)
*--p = '0';
UString UString::number(long long i)
{
- UChar buf[1 + sizeof(i) * 3];
- UChar* end = buf + WTF_ARRAY_LENGTH(buf);
- UChar* p = end;
+ LChar buf[1 + sizeof(i) * 3];
+ LChar* end = buf + WTF_ARRAY_LENGTH(buf);
+ LChar* p = end;
if (i == 0)
*--p = '0';
UString UString::number(unsigned u)
{
- UChar buf[sizeof(u) * 3];
- UChar* end = buf + WTF_ARRAY_LENGTH(buf);
- UChar* p = end;
+ LChar buf[sizeof(u) * 3];
+ LChar* end = buf + WTF_ARRAY_LENGTH(buf);
+ LChar* p = end;
if (u == 0)
*--p = '0';
UString UString::number(long l)
{
- UChar buf[1 + sizeof(l) * 3];
- UChar* end = buf + WTF_ARRAY_LENGTH(buf);
- UChar* p = end;
+ LChar buf[1 + sizeof(l) * 3];
+ LChar* end = buf + WTF_ARRAY_LENGTH(buf);
+ LChar* p = end;
if (l == 0)
*--p = '0';
UString UString::number(double d)
{
NumberToStringBuffer buffer;
- unsigned length = numberToString(d, buffer);
- return UString(buffer, length);
+ return UString(numberToString(d, buffer));
}
UString UString::substringSharingImpl(unsigned offset, unsigned length) const
bool operator==(const UString& s1, const char *s2)
{
- if (s2 == 0)
- return s1.isEmpty();
-
- const UChar* u = s1.characters();
- const UChar* uend = u + s1.length();
- while (u != uend && *s2) {
- if (u[0] != (unsigned char)*s2)
- return false;
- s2++;
- u++;
- }
+ if (s1.isEmpty())
+ return !s2;
- return u == uend && *s2 == 0;
+ return equal(s1.impl(), s2);
+}
+
+// This method assumes that all simple checks have been performed by
+// the inlined operator==() in the header file.
+bool equalSlowCase(const UString& s1, const UString& s2)
+{
+ StringImpl* rep1 = s1.impl();
+ StringImpl* rep2 = s2.impl();
+ unsigned size1 = rep1->length();
+
+ // At this point we know
+ // (a) that the strings are the same length and
+ // (b) that they are greater than zero length.
+ bool s1Is8Bit = rep1->is8Bit();
+ bool s2Is8Bit = rep2->is8Bit();
+
+ if (s1Is8Bit) {
+ const LChar* d1 = rep1->characters8();
+ if (s2Is8Bit) {
+ const LChar* d2 = rep2->characters8();
+
+ if (d1 == d2) // Check to see if the data pointers are the same.
+ return true;
+
+ // Do quick checks for sizes 1 and 2.
+ switch (size1) {
+ case 1:
+ return d1[0] == d2[0];
+ case 2:
+ return (d1[0] == d2[0]) & (d1[1] == d2[1]);
+ default:
+ return (!memcmp(d1, d2, size1 * sizeof(LChar)));
+ }
+ }
+
+ const UChar* d2 = rep2->characters16();
+
+ for (unsigned i = 0; i < size1; i++) {
+ if (d1[i] != d2[i])
+ return false;
+ }
+ return true;
+ }
+
+ if (s2Is8Bit) {
+ const UChar* d1 = rep1->characters16();
+ const LChar* d2 = rep2->characters8();
+
+ for (unsigned i = 0; i < size1; i++) {
+ if (d1[i] != d2[i])
+ return false;
+ }
+ return true;
+
+ }
+
+ const UChar* d1 = rep1->characters16();
+ const UChar* d2 = rep2->characters16();
+
+ if (d1 == d2) // Check to see if the data pointers are the same.
+ return true;
+
+ // Do quick checks for sizes 1 and 2.
+ switch (size1) {
+ case 1:
+ return d1[0] == d2[0];
+ case 2:
+ return (d1[0] == d2[0]) & (d1[1] == d2[1]);
+ default:
+ return (!memcmp(d1, d2, size1 * sizeof(UChar)));
+ }
}
bool operator<(const UString& s1, const UString& s2)
const unsigned l1 = s1.length();
const unsigned l2 = s2.length();
const unsigned lmin = l1 < l2 ? l1 : l2;
+ if (s1.is8Bit() && s2.is8Bit()) {
+ const LChar* c1 = s1.characters8();
+ const LChar* c2 = s2.characters8();
+ unsigned length = 0;
+ while (length < lmin && *c1 == *c2) {
+ c1++;
+ c2++;
+ length++;
+ }
+ if (length < lmin)
+ return (c1[0] < c2[0]);
+
+ return (l1 < l2);
+ }
const UChar* c1 = s1.characters();
const UChar* c2 = s2.characters();
- unsigned l = 0;
- while (l < lmin && *c1 == *c2) {
+ unsigned length = 0;
+ while (length < lmin && *c1 == *c2) {
c1++;
c2++;
- l++;
+ length++;
}
- if (l < lmin)
+ if (length < lmin)
return (c1[0] < c2[0]);
return (l1 < l2);
// preserved, characters outside of this range are converted to '?'.
unsigned length = this->length();
- const UChar* characters = this->characters();
+
+ if (this->is8Bit()) {
+ const LChar* characters = this->characters8();
+
+ char* characterBuffer;
+ CString result = CString::newUninitialized(length, characterBuffer);
+
+ for (unsigned i = 0; i < length; ++i) {
+ LChar ch = characters[i];
+ characterBuffer[i] = ch && (ch < 0x20 || ch > 0x7f) ? '?' : ch;
+ }
+
+ return result;
+ }
+
+ const UChar* characters = this->characters16();
char* characterBuffer;
CString result = CString::newUninitialized(length, characterBuffer);
CString UString::utf8(bool strict) const
{
unsigned length = this->length();
- const UChar* characters = this->characters();
+
+ if (!length)
+ return CString("", 0);
// Allocate a buffer big enough to hold all the characters
// (an individual UTF-16 UChar can only expand to 3 UTF-8 bytes).
// buffer without reallocing (say, 1.5 x length).
if (length > numeric_limits<unsigned>::max() / 3)
return CString();
- Vector<char, 1024> bufferVector(length * 3);
+ Vector<char, 1024> bufferVector(length * 3);
char* buffer = bufferVector.data();
- ConversionResult result = convertUTF16ToUTF8(&characters, characters + length, &buffer, buffer + bufferVector.size(), strict);
- ASSERT(result != targetExhausted); // (length * 3) should be sufficient for any conversion
- // Only produced from strict conversion.
- if (result == sourceIllegal)
- return CString();
+ if (is8Bit()) {
+ const LChar* characters = this->characters8();
- // Check for an unconverted high surrogate.
- if (result == sourceExhausted) {
- if (strict)
+ ConversionResult result = convertLatin1ToUTF8(&characters, characters + length, &buffer, buffer + bufferVector.size());
+ ASSERT_UNUSED(result, result != targetExhausted); // (length * 3) should be sufficient for any conversion
+ } else {
+ const UChar* characters = this->characters16();
+
+ ConversionResult result = convertUTF16ToUTF8(&characters, characters + length, &buffer, buffer + bufferVector.size(), strict);
+ ASSERT(result != targetExhausted); // (length * 3) should be sufficient for any conversion
+
+ // Only produced from strict conversion.
+ if (result == sourceIllegal)
return CString();
- // This should be one unpaired high surrogate. Treat it the same
- // was as an unpaired high surrogate would have been handled in
- // the middle of a string with non-strict conversion - which is
- // to say, simply encode it to UTF-8.
- ASSERT((characters + 1) == (this->characters() + length));
- ASSERT((*characters >= 0xD800) && (*characters <= 0xDBFF));
- // There should be room left, since one UChar hasn't been converted.
- ASSERT((buffer + 3) <= (buffer + bufferVector.size()));
- putUTF8Triple(buffer, *characters);
+
+ // Check for an unconverted high surrogate.
+ if (result == sourceExhausted) {
+ if (strict)
+ return CString();
+ // This should be one unpaired high surrogate. Treat it the same
+ // was as an unpaired high surrogate would have been handled in
+ // the middle of a string with non-strict conversion - which is
+ // to say, simply encode it to UTF-8.
+ ASSERT((characters + 1) == (this->characters() + length));
+ ASSERT((*characters >= 0xD800) && (*characters <= 0xDBFF));
+ // There should be room left, since one UChar hasn't been converted.
+ ASSERT((buffer + 3) <= (buffer + bufferVector.size()));
+ putUTF8Triple(buffer, *characters);
+ }
}
return CString(bufferVector.data(), buffer - bufferVector.data());