18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
35f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian *  Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
55f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian *  Copyright (C) 2009 Google Inc. All rights reserved.
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  This library is free software; you can redistribute it and/or
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  modify it under the terms of the GNU Library General Public
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  License as published by the Free Software Foundation; either
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  version 2 of the License, or (at your option) any later version.
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  This library is distributed in the hope that it will be useful,
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  but WITHOUT ANY WARRANTY; without even the implied warranty of
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  Library General Public License for more details.
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  You should have received a copy of the GNU Library General Public License
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  along with this library; see the file COPYING.LIB.  If not, write to
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  Boston, MA 02110-1301, USA.
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
25635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "UString.h"
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "JSGlobalObjectFunctions.h"
2865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include "Heap.h"
29635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "Identifier.h"
30635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "Operations.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <ctype.h>
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <limits.h>
33231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <limits>
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <stdio.h>
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <stdlib.h>
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/ASCIICType.h>
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/Assertions.h>
385ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen#include <wtf/DecimalNumber.h>
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/MathExtras.h>
40231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <wtf/StringExtras.h>
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/Vector.h>
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/unicode/UTF8.h>
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if HAVE(STRINGS_H)
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <strings.h>
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace WTF;
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace WTF::Unicode;
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace std;
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace JSC {
538a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectextern const double NaN;
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectextern const double Inf;
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
57e78cbe89e6f337f2f1fe40315be88f742b547151Steve BlockCOMPILE_ASSERT(sizeof(UString) == sizeof(void*), UString_should_stay_small);
58e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block
59f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick// Construct a string with UTF-16 data.
60f486d19d62f1bc33246748b14b14a9dfa617b57fIain MerrickUString::UString(const UChar* characters, unsigned length)
61f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    : m_impl(characters ? StringImpl::create(characters, length) : 0)
62635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
63643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
64643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
65f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick// Construct a string with UTF-16 data, from a null-terminated source.
66f486d19d62f1bc33246748b14b14a9dfa617b57fIain MerrickUString::UString(const UChar* characters)
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
68f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (!characters)
69f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return;
70f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
71f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    int length = 0;
72f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    while (characters[length] != UChar(0))
73f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        ++length;
74f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
75f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    m_impl = StringImpl::create(characters, length);
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
78f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick// Construct a string with latin1 data.
79f486d19d62f1bc33246748b14b14a9dfa617b57fIain MerrickUString::UString(const char* characters, unsigned length)
80f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    : m_impl(characters ? StringImpl::create(characters, length) : 0)
81643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
82643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
83643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
84f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick// Construct a string with latin1 data, from a null-terminated source.
85f486d19d62f1bc33246748b14b14a9dfa617b57fIain MerrickUString::UString(const char* characters)
86f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    : m_impl(characters ? StringImpl::create(characters) : 0)
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
90f486d19d62f1bc33246748b14b14a9dfa617b57fIain MerrickUString UString::number(int i)
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    UChar buf[1 + sizeof(i) * 3];
93e14391e94c850b8bd03680c23b38978db68687a8John Reck    UChar* end = buf + WTF_ARRAY_LENGTH(buf);
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    UChar* p = end;
958a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (i == 0)
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        *--p = '0';
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else if (i == INT_MIN) {
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        char minBuf[1 + sizeof(i) * 3];
100ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        snprintf(minBuf, sizeof(minBuf), "%d", INT_MIN);
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return UString(minBuf);
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool negative = false;
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (i < 0) {
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            negative = true;
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            i = -i;
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (i) {
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            *--p = static_cast<unsigned short>((i % 10) + '0');
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            i /= 10;
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (negative)
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            *--p = '-';
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
116692e5dbf12901edacf14812a6fae25462920af42Steve Block    return UString(p, static_cast<unsigned>(end - p));
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
119f486d19d62f1bc33246748b14b14a9dfa617b57fIain MerrickUString UString::number(long long i)
120231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
121231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    UChar buf[1 + sizeof(i) * 3];
122e14391e94c850b8bd03680c23b38978db68687a8John Reck    UChar* end = buf + WTF_ARRAY_LENGTH(buf);
123231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    UChar* p = end;
124231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
125231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (i == 0)
126231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        *--p = '0';
127231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    else if (i == std::numeric_limits<long long>::min()) {
128231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        char minBuf[1 + sizeof(i) * 3];
129d0825bca7fe65beaee391d30da42e937db621564Steve Block#if OS(WINDOWS)
130ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        snprintf(minBuf, sizeof(minBuf), "%I64d", std::numeric_limits<long long>::min());
131231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#else
132ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        snprintf(minBuf, sizeof(minBuf), "%lld", std::numeric_limits<long long>::min());
133231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif
134231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return UString(minBuf);
135231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    } else {
136231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        bool negative = false;
137231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (i < 0) {
138231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            negative = true;
139231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            i = -i;
140231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
141231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        while (i) {
142231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            *--p = static_cast<unsigned short>((i % 10) + '0');
143231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            i /= 10;
144231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
145231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (negative)
146231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            *--p = '-';
147231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
148231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
149692e5dbf12901edacf14812a6fae25462920af42Steve Block    return UString(p, static_cast<unsigned>(end - p));
150231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
151231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
152f486d19d62f1bc33246748b14b14a9dfa617b57fIain MerrickUString UString::number(unsigned u)
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    UChar buf[sizeof(u) * 3];
155e14391e94c850b8bd03680c23b38978db68687a8John Reck    UChar* end = buf + WTF_ARRAY_LENGTH(buf);
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    UChar* p = end;
1578a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (u == 0)
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        *--p = '0';
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else {
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (u) {
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            *--p = static_cast<unsigned short>((u % 10) + '0');
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            u /= 10;
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1668a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
167692e5dbf12901edacf14812a6fae25462920af42Steve Block    return UString(p, static_cast<unsigned>(end - p));
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
170f486d19d62f1bc33246748b14b14a9dfa617b57fIain MerrickUString UString::number(long l)
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    UChar buf[1 + sizeof(l) * 3];
173e14391e94c850b8bd03680c23b38978db68687a8John Reck    UChar* end = buf + WTF_ARRAY_LENGTH(buf);
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    UChar* p = end;
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (l == 0)
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        *--p = '0';
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else if (l == LONG_MIN) {
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        char minBuf[1 + sizeof(l) * 3];
180ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        snprintf(minBuf, sizeof(minBuf), "%ld", LONG_MIN);
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return UString(minBuf);
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool negative = false;
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (l < 0) {
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            negative = true;
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            l = -l;
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (l) {
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            *--p = static_cast<unsigned short>((l % 10) + '0');
1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            l /= 10;
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (negative)
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            *--p = '-';
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
196692e5dbf12901edacf14812a6fae25462920af42Steve Block    return UString(p, end - p);
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
199f486d19d62f1bc33246748b14b14a9dfa617b57fIain MerrickUString UString::number(double d)
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
201e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    NumberToStringBuffer buffer;
2025ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    unsigned length = numberToString(d, buffer);
2035ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    return UString(buffer, length);
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
206f486d19d62f1bc33246748b14b14a9dfa617b57fIain MerrickUString UString::substringSharingImpl(unsigned offset, unsigned length) const
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
208f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // FIXME: We used to check against a limit of Heap::minExtraCost / sizeof(UChar).
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
210f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned stringLength = this->length();
211f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    offset = min(offset, stringLength);
212f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    length = min(length, stringLength - offset);
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
214f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (!offset && length == stringLength)
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return *this;
216f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    return UString(StringImpl::create(m_impl, offset, length));
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool operator==(const UString& s1, const char *s2)
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (s2 == 0)
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return s1.isEmpty();
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
224f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const UChar* u = s1.characters();
225f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const UChar* uend = u + s1.length();
2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (u != uend && *s2) {
2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (u[0] != (unsigned char)*s2)
2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        s2++;
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        u++;
2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return u == uend && *s2 == 0;
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool operator<(const UString& s1, const UString& s2)
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
238f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const unsigned l1 = s1.length();
239f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const unsigned l2 = s2.length();
240692e5dbf12901edacf14812a6fae25462920af42Steve Block    const unsigned lmin = l1 < l2 ? l1 : l2;
241f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const UChar* c1 = s1.characters();
242f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const UChar* c2 = s2.characters();
243692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned l = 0;
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (l < lmin && *c1 == *c2) {
2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        c1++;
2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        c2++;
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        l++;
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (l < lmin)
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return (c1[0] < c2[0]);
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return (l1 < l2);
2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool operator>(const UString& s1, const UString& s2)
2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
257f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const unsigned l1 = s1.length();
258f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const unsigned l2 = s2.length();
259692e5dbf12901edacf14812a6fae25462920af42Steve Block    const unsigned lmin = l1 < l2 ? l1 : l2;
260f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const UChar* c1 = s1.characters();
261f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const UChar* c2 = s2.characters();
262692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned l = 0;
2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (l < lmin && *c1 == *c2) {
2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        c1++;
2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        c2++;
2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        l++;
2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (l < lmin)
2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return (c1[0] > c2[0]);
2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return (l1 > l2);
2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
274f486d19d62f1bc33246748b14b14a9dfa617b57fIain MerrickCString UString::ascii() const
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
276f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Basic Latin1 (ISO) encoding - Unicode characters 0..255 are
277f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // preserved, characters outside of this range are converted to '?'.
278f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
279f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned length = this->length();
280f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const UChar* characters = this->characters();
281f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
282f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    char* characterBuffer;
283f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    CString result = CString::newUninitialized(length, characterBuffer);
284f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
285f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    for (unsigned i = 0; i < length; ++i) {
286f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        UChar ch = characters[i];
287f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        characterBuffer[i] = ch && (ch < 0x20 || ch >= 0x7f) ? '?' : ch;
288f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    }
289f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
290f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    return result;
291f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick}
292f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
293f486d19d62f1bc33246748b14b14a9dfa617b57fIain MerrickCString UString::latin1() const
294f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick{
295f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Basic Latin1 (ISO) encoding - Unicode characters 0..255 are
296f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // preserved, characters outside of this range are converted to '?'.
297f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
298f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned length = this->length();
299f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const UChar* characters = this->characters();
300f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
301f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    char* characterBuffer;
302f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    CString result = CString::newUninitialized(length, characterBuffer);
303f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
304f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    for (unsigned i = 0; i < length; ++i) {
305f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        UChar ch = characters[i];
306f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        characterBuffer[i] = ch > 0xff ? '?' : ch;
307f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    }
308f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
309f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    return result;
310f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick}
311f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
312f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick// Helper to write a three-byte UTF-8 code point to the buffer, caller must check room is available.
313f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickstatic inline void putUTF8Triple(char*& buffer, UChar ch)
314f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick{
315f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    ASSERT(ch >= 0x0800);
316f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    *buffer++ = static_cast<char>(((ch >> 12) & 0x0F) | 0xE0);
317f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    *buffer++ = static_cast<char>(((ch >> 6) & 0x3F) | 0x80);
318f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    *buffer++ = static_cast<char>((ch & 0x3F) | 0x80);
319f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick}
320f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
321f486d19d62f1bc33246748b14b14a9dfa617b57fIain MerrickCString UString::utf8(bool strict) const
322f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick{
323f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned length = this->length();
324f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const UChar* characters = this->characters();
325f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
326f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Allocate a buffer big enough to hold all the characters
327f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // (an individual UTF-16 UChar can only expand to 3 UTF-8 bytes).
328f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Optimization ideas, if we find this function is hot:
329f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    //  * We could speculatively create a CStringBuffer to contain 'length'
330f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    //    characters, and resize if necessary (i.e. if the buffer contains
331f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    //    non-ascii characters). (Alternatively, scan the buffer first for
332f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    //    ascii characters, so we know this will be sufficient).
333f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    //  * We could allocate a CStringBuffer with an appropriate size to
334f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    //    have a good chance of being able to write the string into the
335f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    //    buffer without reallocing (say, 1.5 x length).
336e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (length > numeric_limits<unsigned>::max() / 3)
337e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        return CString();
338f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    Vector<char, 1024> bufferVector(length * 3);
339f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
340f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    char* buffer = bufferVector.data();
341f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    ConversionResult result = convertUTF16ToUTF8(&characters, characters + length, &buffer, buffer + bufferVector.size(), strict);
342f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    ASSERT(result != targetExhausted); // (length * 3) should be sufficient for any conversion
343f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
344f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Only produced from strict conversion.
345f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (result == sourceIllegal)
3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return CString();
3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
348f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Check for an unconverted high surrogate.
349f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (result == sourceExhausted) {
350f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        if (strict)
351f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick            return CString();
352f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        // This should be one unpaired high surrogate. Treat it the same
353f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        // was as an unpaired high surrogate would have been handled in
354f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        // the middle of a string with non-strict conversion - which is
355f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        // to say, simply encode it to UTF-8.
356f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        ASSERT((characters + 1) == (this->characters() + length));
357f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        ASSERT((*characters >= 0xD800) && (*characters <= 0xDBFF));
358f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        // There should be room left, since one UChar hasn't been converted.
359f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        ASSERT((buffer + 3) <= (buffer + bufferVector.size()));
360f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        putUTF8Triple(buffer, *characters);
361f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    }
362f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
363f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    return CString(bufferVector.data(), buffer - bufferVector.data());
3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace JSC
367