18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *           (C) 1999 Antti Koivisto (koivisto@kde.org)
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *           (C) 2001 Dirk Mueller ( mueller@kde.org )
58f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is free software; you can redistribute it and/or
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modify it under the terms of the GNU Library General Public
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License as published by the Free Software Foundation; either
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version 2 of the License, or (at your option) any later version.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is distributed in the hope that it will be useful,
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Library General Public License for more details.
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * You should have received a copy of the GNU Library General Public License
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * along with this library; see the file COPYING.LIB.  If not, write to
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Boston, MA 02110-1301, USA.
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "StringImpl.h"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "AtomicString.h"
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "StringBuffer.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "StringHash.h"
31dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include <wtf/StdLibExtras.h>
32dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include <wtf/WTFThreadData.h>
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
345ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenusing namespace std;
355ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
36dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochnamespace WTF {
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
38dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochusing namespace Unicode;
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic const unsigned minLengthToShare = 20;
415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
42e78cbe89e6f337f2f1fe40315be88f742b547151Steve BlockCOMPILE_ASSERT(sizeof(StringImpl) == 2 * sizeof(int) + 3 * sizeof(void*), StringImpl_should_stay_small);
43e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectStringImpl::~StringImpl()
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
46dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    ASSERT(!isStatic());
47dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
4821939df44de1705786c545cd1bf519d47250322dBen Murdoch    if (isAtomic())
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        AtomicString::remove(this);
50dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#if USE(JSC)
5168513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (isIdentifier()) {
5268513a70bcd92384395513322f1b801e7bf9c729Steve Block        if (!wtfThreadData().currentIdentifierTable()->remove(this))
5368513a70bcd92384395513322f1b801e7bf9c729Steve Block            CRASH();
5468513a70bcd92384395513322f1b801e7bf9c729Steve Block    }
55dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#endif
56692e5dbf12901edacf14812a6fae25462920af42Steve Block
57692e5dbf12901edacf14812a6fae25462920af42Steve Block    BufferOwnership ownership = bufferOwnership();
58692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (ownership != BufferInternal) {
59692e5dbf12901edacf14812a6fae25462920af42Steve Block        if (ownership == BufferOwned) {
60692e5dbf12901edacf14812a6fae25462920af42Steve Block            ASSERT(!m_sharedBuffer);
61692e5dbf12901edacf14812a6fae25462920af42Steve Block            ASSERT(m_data);
62692e5dbf12901edacf14812a6fae25462920af42Steve Block            fastFree(const_cast<UChar*>(m_data));
63dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } else if (ownership == BufferSubstring) {
64dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            ASSERT(m_substringBuffer);
65dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            m_substringBuffer->deref();
66692e5dbf12901edacf14812a6fae25462920af42Steve Block        } else {
67692e5dbf12901edacf14812a6fae25462920af42Steve Block            ASSERT(ownership == BufferShared);
68692e5dbf12901edacf14812a6fae25462920af42Steve Block            ASSERT(m_sharedBuffer);
69692e5dbf12901edacf14812a6fae25462920af42Steve Block            m_sharedBuffer->deref();
70692e5dbf12901edacf14812a6fae25462920af42Steve Block        }
715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
74dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockPassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, UChar*& data)
75dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
76dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!length) {
77dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        data = 0;
78dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return empty();
79dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
80dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
81dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // Allocate a single buffer large enough to contain the StringImpl
82dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // struct as well as the data which it contains. This removes one
83dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // heap allocation from this call.
84a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(UChar)))
85dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        CRASH();
86dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    size_t size = sizeof(StringImpl) + length * sizeof(UChar);
87dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    StringImpl* string = static_cast<StringImpl*>(fastMalloc(size));
88dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
89dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    data = reinterpret_cast<UChar*>(string + 1);
90dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return adoptRef(new (string) StringImpl(length));
91dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
92dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
93dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockPassRefPtr<StringImpl> StringImpl::create(const UChar* characters, unsigned length)
94dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
95dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!characters || !length)
96dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return empty();
97dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
98dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    UChar* data;
996b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    RefPtr<StringImpl> string = createUninitialized(length, data);
100dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    memcpy(data, characters, length * sizeof(UChar));
1016b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return string.release();
102dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
103dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
104dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockPassRefPtr<StringImpl> StringImpl::create(const char* characters, unsigned length)
105dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
106dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!characters || !length)
107dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return empty();
108dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
109dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    UChar* data;
1106b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    RefPtr<StringImpl> string = createUninitialized(length, data);
111dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    for (unsigned i = 0; i != length; ++i) {
112dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        unsigned char c = characters[i];
113dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        data[i] = c;
114dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1156b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return string.release();
116dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
117dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
118dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockPassRefPtr<StringImpl> StringImpl::create(const char* string)
119dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
120dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!string)
121dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return empty();
1226b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    size_t length = strlen(string);
1236b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (length > numeric_limits<unsigned>::max())
1246b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        CRASH();
1256b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return create(string, length);
126dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
127dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
128dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockPassRefPtr<StringImpl> StringImpl::create(const UChar* characters, unsigned length, PassRefPtr<SharedUChar> sharedBuffer)
129dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
130dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    ASSERT(characters);
131dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    ASSERT(minLengthToShare && length >= minLengthToShare);
132dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return adoptRef(new StringImpl(characters, length, sharedBuffer));
133dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
134dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
135dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockSharedUChar* StringImpl::sharedBuffer()
136dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
137dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (m_length < minLengthToShare)
138dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return 0;
139dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // All static strings are smaller that the minimim length to share.
140dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    ASSERT(!isStatic());
141dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
142dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    BufferOwnership ownership = bufferOwnership();
143dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
144dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (ownership == BufferInternal)
145dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return 0;
146dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (ownership == BufferSubstring)
147dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return m_substringBuffer->sharedBuffer();
148dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (ownership == BufferOwned) {
149dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        ASSERT(!m_sharedBuffer);
15028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        m_sharedBuffer = SharedUChar::create(new SharableUChar(m_data)).leakRef();
151dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        m_refCountAndFlags = (m_refCountAndFlags & ~s_refCountMaskBufferOwnership) | BufferShared;
152dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
153dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
154dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    ASSERT(bufferOwnership() == BufferShared);
155dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    ASSERT(m_sharedBuffer);
156dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return m_sharedBuffer;
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool StringImpl::containsOnlyWhitespace()
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: The definition of whitespace here includes a number of characters
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // that are not whitespace from the point of view of RenderText; I wonder if
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // that's a problem in practice.
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (unsigned i = 0; i < m_length; i++)
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!isASCIISpace(m_data[i]))
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochPassRefPtr<StringImpl> StringImpl::substring(unsigned start, unsigned length)
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (start >= m_length)
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return empty();
1740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    unsigned maxLength = m_length - start;
1750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (length >= maxLength) {
1760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (!start)
1770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            return this;
1780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        length = maxLength;
1790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
1800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return create(m_data + start, length);
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectUChar32 StringImpl::characterStartingAt(unsigned i)
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (U16_IS_SINGLE(m_data[i]))
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return m_data[i];
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (i + 1 < m_length && U16_IS_LEAD(m_data[i]) && U16_IS_TRAIL(m_data[i + 1]))
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return U16_GET_SUPPLEMENTARY(m_data[i], m_data[i + 1]);
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
192cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve BlockPassRefPtr<StringImpl> StringImpl::lower()
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
194cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // Note: This is a hot function in the Dromaeo benchmark, specifically the
195cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // no-op code path up through the first 'return' statement.
196cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
197cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // First scan the string for uppercase and non-ASCII characters:
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    UChar ored = 0;
199cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    bool noUpper = true;
200cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    const UChar *end = m_data + m_length;
201cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    for (const UChar* chp = m_data; chp != end; chp++) {
202cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        if (UNLIKELY(isASCIIUpper(*chp)))
203cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            noUpper = false;
204cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        ored |= *chp;
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
206cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
207cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // Nothing to do if the string is all ASCII with no uppercase.
208cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (noUpper && !(ored & ~0x7F))
209cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return this;
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2116b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (m_length > static_cast<unsigned>(numeric_limits<int32_t>::max()))
2126b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        CRASH();
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int32_t length = m_length;
2146b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
215cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    UChar* data;
216cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
218cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (!(ored & ~0x7F)) {
219cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        // Do a faster loop for the case where all the characters are ASCII.
220cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        for (int i = 0; i < length; i++) {
221cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            UChar c = m_data[i];
222cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            data[i] = toASCIILower(c);
223cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        }
2245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return newImpl;
225cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    }
226cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Do a slower implementation for cases that include non-ASCII characters.
2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool error;
2295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    int32_t realLength = Unicode::toLower(data, length, m_data, m_length, &error);
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!error && realLength == length)
2315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return newImpl;
2325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    newImpl = createUninitialized(realLength, data);
2335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    Unicode::toLower(data, realLength, m_data, m_length, &error);
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (error)
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return this;
2365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return newImpl;
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<StringImpl> StringImpl::upper()
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
241cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // This function could be optimized for no-op cases the way lower() is,
242cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // but in empirical testing, few actual calls to upper() are no-ops, so
243cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // it wouldn't be worth the extra time for pre-scanning.
2445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    UChar* data;
2456b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
2466b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2476b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (m_length > static_cast<unsigned>(numeric_limits<int32_t>::max()))
2486b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        CRASH();
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int32_t length = m_length;
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Do a faster loop for the case where all the characters are ASCII.
2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    UChar ored = 0;
2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (int i = 0; i < length; i++) {
2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        UChar c = m_data[i];
2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ored |= c;
2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        data[i] = toASCIIUpper(c);
2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!(ored & ~0x7F))
2596b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return newImpl.release();
2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Do a slower implementation for cases that include non-ASCII characters.
2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool error;
2635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    int32_t realLength = Unicode::toUpper(data, length, m_data, m_length, &error);
2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!error && realLength == length)
2655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return newImpl;
2665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    newImpl = createUninitialized(realLength, data);
2675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    Unicode::toUpper(data, realLength, m_data, m_length, &error);
2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (error)
2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return this;
2706b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return newImpl.release();
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2734576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) WangPassRefPtr<StringImpl> StringImpl::secure(UChar character, LastCharacterBehavior behavior)
2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2754576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    if (!m_length)
2764576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        return this;
2774576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
2785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    UChar* data;
2796b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
2804576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    unsigned lastCharacterIndex = m_length - 1;
2814576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    for (unsigned i = 0; i < lastCharacterIndex; ++i)
2826b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        data[i] = character;
2834576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    data[lastCharacterIndex] = (behavior == ObscureLastCharacter) ? character : m_data[lastCharacterIndex];
2846b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return newImpl.release();
2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<StringImpl> StringImpl::foldCase()
2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    UChar* data;
2906b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
2916b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2926b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (m_length > static_cast<unsigned>(numeric_limits<int32_t>::max()))
2936b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        CRASH();
2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int32_t length = m_length;
2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Do a faster loop for the case where all the characters are ASCII.
2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    UChar ored = 0;
2986b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    for (int32_t i = 0; i < length; i++) {
2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        UChar c = m_data[i];
3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ored |= c;
3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        data[i] = toASCIILower(c);
3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!(ored & ~0x7F))
3046b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return newImpl.release();
3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Do a slower implementation for cases that include non-ASCII characters.
3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool error;
3085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    int32_t realLength = Unicode::foldCase(data, length, m_data, m_length, &error);
3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!error && realLength == length)
3106b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return newImpl.release();
3115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    newImpl = createUninitialized(realLength, data);
3125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    Unicode::foldCase(data, realLength, m_data, m_length, &error);
3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (error)
3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return this;
3156b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return newImpl.release();
3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<StringImpl> StringImpl::stripWhiteSpace()
3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_length)
3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return empty();
3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned start = 0;
3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned end = m_length - 1;
3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // skip white space from start
3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (start <= end && isSpaceOrNewline(m_data[start]))
3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        start++;
3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // only white space
3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (start > end)
3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return empty();
3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // skip white space from end
3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (end && isSpaceOrNewline(m_data[end]))
3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        end--;
3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
338cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (!start && end == m_length - 1)
339cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return this;
3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return create(m_data + start, end + 1 - start);
3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
343635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectPassRefPtr<StringImpl> StringImpl::removeCharacters(CharacterMatchFunctionPtr findMatch)
344635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
345635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    const UChar* from = m_data;
346635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    const UChar* fromend = from + m_length;
347635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
348635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Assume the common case will not remove any characters
349635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    while (from != fromend && !findMatch(*from))
350635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        from++;
351635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (from == fromend)
352635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return this;
353635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
354635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    StringBuffer data(m_length);
355635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    UChar* to = data.characters();
356635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    unsigned outc = from - m_data;
357635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
358635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (outc)
359635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        memcpy(to, m_data, outc * sizeof(UChar));
360635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
361635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    while (true) {
362635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        while (from != fromend && findMatch(*from))
363635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            from++;
364635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        while (from != fromend && !findMatch(*from))
365635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            to[outc++] = *from++;
366635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (from == fromend)
367635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            break;
368635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
369635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
370635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    data.shrink(outc);
371635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
372635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return adopt(data);
373635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
374635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<StringImpl> StringImpl::simplifyWhiteSpace()
3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    StringBuffer data(m_length);
3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const UChar* from = m_data;
3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const UChar* fromend = from + m_length;
3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int outc = 0;
382cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    bool changedToSpace = false;
3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    UChar* to = data.characters();
3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (true) {
387cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        while (from != fromend && isSpaceOrNewline(*from)) {
388cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            if (*from != ' ')
389cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                changedToSpace = true;
3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            from++;
391cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        }
3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (from != fromend && !isSpaceOrNewline(*from))
3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            to[outc++] = *from++;
3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (from != fromend)
3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            to[outc++] = ' ';
3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else
3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (outc > 0 && to[outc - 1] == ' ')
4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        outc--;
4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
403cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (static_cast<unsigned>(outc) == m_length && !changedToSpace)
404cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return this;
405cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    data.shrink(outc);
4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return adopt(data);
4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint StringImpl::toIntStrict(bool* ok, int base)
4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return charactersToIntStrict(m_data, m_length, ok, base);
4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectunsigned StringImpl::toUIntStrict(bool* ok, int base)
4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return charactersToUIntStrict(m_data, m_length, ok, base);
4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint64_t StringImpl::toInt64Strict(bool* ok, int base)
4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return charactersToInt64Strict(m_data, m_length, ok, base);
4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectuint64_t StringImpl::toUInt64Strict(bool* ok, int base)
4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return charactersToUInt64Strict(m_data, m_length, ok, base);
4298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochintptr_t StringImpl::toIntPtrStrict(bool* ok, int base)
4320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
4330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return charactersToIntPtrStrict(m_data, m_length, ok, base);
4340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
4350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint StringImpl::toInt(bool* ok)
4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return charactersToInt(m_data, m_length, ok);
4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectunsigned StringImpl::toUInt(bool* ok)
4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return charactersToUInt(m_data, m_length, ok);
4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint64_t StringImpl::toInt64(bool* ok)
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return charactersToInt64(m_data, m_length, ok);
4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectuint64_t StringImpl::toUInt64(bool* ok)
4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return charactersToUInt64(m_data, m_length, ok);
4548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochintptr_t StringImpl::toIntPtr(bool* ok)
4570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
4580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return charactersToIntPtr(m_data, m_length, ok);
4590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
4600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
46181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochdouble StringImpl::toDouble(bool* ok, bool* didReadNumber)
4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
46381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return charactersToDouble(m_data, m_length, ok, didReadNumber);
4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
46681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochfloat StringImpl::toFloat(bool* ok, bool* didReadNumber)
4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
46881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return charactersToFloat(m_data, m_length, ok, didReadNumber);
4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool equal(const UChar* a, const char* b, int length)
4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(length >= 0);
4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (length--) {
4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        unsigned char bc = *b++;
4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (*a++ != bc)
4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochbool equalIgnoringCase(const UChar* a, const char* b, unsigned length)
4838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (length--) {
4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        unsigned char bc = *b++;
4868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (foldCase(*a++) != foldCase(bc))
4878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
4888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
4908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool equalIgnoringCase(const UChar* a, const UChar* b, int length)
4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(length >= 0);
4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return umemcasecmp(a, b, length) == 0;
4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4985af96e2c7b73ebc627c6894727826a7576d31758Leon Clarkeint codePointCompare(const StringImpl* s1, const StringImpl* s2)
4995af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke{
5005af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    const unsigned l1 = s1 ? s1->length() : 0;
5015af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    const unsigned l2 = s2 ? s2->length() : 0;
5025af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    const unsigned lmin = l1 < l2 ? l1 : l2;
5035af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    const UChar* c1 = s1 ? s1->characters() : 0;
5045af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    const UChar* c2 = s2 ? s2->characters() : 0;
5055af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    unsigned pos = 0;
5065af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    while (pos < lmin && *c1 == *c2) {
5075af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        c1++;
5085af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        c2++;
5095af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        pos++;
5105af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    }
5115af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
5125af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    if (pos < lmin)
5135af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        return (c1[0] > c2[0]) ? 1 : -1;
5145af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
5155af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    if (l1 == l2)
5165af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        return 0;
5175af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
5185af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    return (l1 > l2) ? 1 : -1;
5195af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke}
5205af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
521f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merricksize_t StringImpl::find(UChar c, unsigned start)
5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
523f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    return WTF::find(m_data, m_length, c, start);
524f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick}
5258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
526f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merricksize_t StringImpl::find(CharacterMatchFunctionPtr matchFunction, unsigned start)
527f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick{
528f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    return WTF::find(m_data, m_length, matchFunction, start);
529f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick}
5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
531f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merricksize_t StringImpl::find(const char* matchString, unsigned index)
532f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick{
533f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Check for null or empty string to match against
534f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (!matchString)
535f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return notFound;
5366b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    size_t matchStringLength = strlen(matchString);
5376b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (matchStringLength > numeric_limits<unsigned>::max())
5386b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        CRASH();
5396b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    unsigned matchLength = matchStringLength;
540f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (!matchLength)
541f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return min(index, length());
542f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
543f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Optimization 1: fast case for strings of length 1.
544f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (matchLength == 1)
545f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return WTF::find(characters(), length(), *(const unsigned char*)matchString, index);
546f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
547f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Check index & matchLength are in range.
548f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (index > length())
549f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return notFound;
550f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned searchLength = length() - index;
551f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (matchLength > searchLength)
552f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return notFound;
553f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // delta is the number of additional times to test; delta == 0 means test only once.
554f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned delta = searchLength - matchLength;
555f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
556f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const UChar* searchCharacters = characters() + index;
557f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const unsigned char* matchCharacters = (const unsigned char*)matchString;
558f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
559f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Optimization 2: keep a running hash of the strings,
560f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // only call memcmp if the hashes match.
561f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned searchHash = 0;
562f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned matchHash = 0;
563f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    for (unsigned i = 0; i < matchLength; ++i) {
564f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        searchHash += searchCharacters[i];
565f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        matchHash += matchCharacters[i];
5668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
568f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned i = 0;
569f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // keep looping until we match
570f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    while (searchHash != matchHash || !equal(searchCharacters + i, matchString, matchLength)) {
571f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        if (i == delta)
572f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick            return notFound;
573f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        searchHash += searchCharacters[i + matchLength];
574f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        searchHash -= searchCharacters[i];
575f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        ++i;
576f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    }
577f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    return index + i;
578f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick}
579f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
580f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merricksize_t StringImpl::findIgnoringCase(const char* matchString, unsigned index)
581f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick{
582f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Check for null or empty string to match against
583f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (!matchString)
584f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return notFound;
5856b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    size_t matchStringLength = strlen(matchString);
5866b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (matchStringLength > numeric_limits<unsigned>::max())
5876b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        CRASH();
5886b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    unsigned matchLength = matchStringLength;
589f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (!matchLength)
590f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return min(index, length());
591f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
592f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Check index & matchLength are in range.
593f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (index > length())
594f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return notFound;
595f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned searchLength = length() - index;
596f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (matchLength > searchLength)
597f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return notFound;
598f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // delta is the number of additional times to test; delta == 0 means test only once.
599f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned delta = searchLength - matchLength;
600f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
601f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const UChar* searchCharacters = characters() + index;
602f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
603f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned i = 0;
604f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // keep looping until we match
605f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    while (!equalIgnoringCase(searchCharacters + i, matchString, matchLength)) {
606f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        if (i == delta)
607f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick            return notFound;
608f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        ++i;
609f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    }
610f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    return index + i;
611f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick}
612f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
613f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merricksize_t StringImpl::find(StringImpl* matchString, unsigned index)
614f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick{
615f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Check for null or empty string to match against
616f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (!matchString)
617f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return notFound;
618f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned matchLength = matchString->length();
619f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (!matchLength)
620f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return min(index, length());
621f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
622f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Optimization 1: fast case for strings of length 1.
623f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (matchLength == 1)
624f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return WTF::find(characters(), length(), matchString->characters()[0], index);
625f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
626f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Check index & matchLength are in range.
627f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (index > length())
628f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return notFound;
629f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned searchLength = length() - index;
630f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (matchLength > searchLength)
631f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return notFound;
632f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // delta is the number of additional times to test; delta == 0 means test only once.
633f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned delta = searchLength - matchLength;
634f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
635f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const UChar* searchCharacters = characters() + index;
636f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const UChar* matchCharacters = matchString->characters();
637f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
638f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Optimization 2: keep a running hash of the strings,
639f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // only call memcmp if the hashes match.
640f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned searchHash = 0;
641f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned matchHash = 0;
642f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    for (unsigned i = 0; i < matchLength; ++i) {
643f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        searchHash += searchCharacters[i];
644f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        matchHash += matchCharacters[i];
645f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    }
646f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
647f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned i = 0;
648f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // keep looping until we match
649f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    while (searchHash != matchHash || memcmp(searchCharacters + i, matchCharacters, matchLength * sizeof(UChar))) {
650f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        if (i == delta)
651f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick            return notFound;
652f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        searchHash += searchCharacters[i + matchLength];
653f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        searchHash -= searchCharacters[i];
654f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        ++i;
655f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    }
656f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    return index + i;
657f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick}
658f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
659f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merricksize_t StringImpl::findIgnoringCase(StringImpl* matchString, unsigned index)
660f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick{
661f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Check for null or empty string to match against
662f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (!matchString)
663f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return notFound;
664f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned matchLength = matchString->length();
665f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (!matchLength)
666f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return min(index, length());
667f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
668f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Check index & matchLength are in range.
669f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (index > length())
670f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return notFound;
671f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned searchLength = length() - index;
672f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (matchLength > searchLength)
673f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return notFound;
674f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // delta is the number of additional times to test; delta == 0 means test only once.
675f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned delta = searchLength - matchLength;
676f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
677f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const UChar* searchCharacters = characters() + index;
678f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const UChar* matchCharacters = matchString->characters();
679f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
680f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned i = 0;
681f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // keep looping until we match
682f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    while (!equalIgnoringCase(searchCharacters + i, matchCharacters, matchLength)) {
683f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        if (i == delta)
684f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick            return notFound;
685f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        ++i;
686f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    }
687f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    return index + i;
6888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
690f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merricksize_t StringImpl::reverseFind(UChar c, unsigned index)
6918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
692f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    return WTF::reverseFind(m_data, m_length, c, index);
6938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
695f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merricksize_t StringImpl::reverseFind(StringImpl* matchString, unsigned index)
696635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
697f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Check for null or empty string to match against
698f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (!matchString)
699f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return notFound;
700f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned matchLength = matchString->length();
701f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (!matchLength)
702f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return min(index, length());
703635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
704f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Optimization 1: fast case for strings of length 1.
705f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (matchLength == 1)
706f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return WTF::reverseFind(characters(), length(), matchString->characters()[0], index);
707f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
708f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Check index & matchLength are in range.
709f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (matchLength > length())
710f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return notFound;
711f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // delta is the number of additional times to test; delta == 0 means test only once.
712f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned delta = min(index, length() - matchLength);
713f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
714f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const UChar *searchCharacters = characters();
715f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const UChar *matchCharacters = matchString->characters();
716f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
717f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Optimization 2: keep a running hash of the strings,
718f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // only call memcmp if the hashes match.
719f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned searchHash = 0;
720f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned matchHash = 0;
721f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    for (unsigned i = 0; i < matchLength; ++i) {
722f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        searchHash += searchCharacters[delta + i];
723f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        matchHash += matchCharacters[i];
7248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
7258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
726f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // keep looping until we match
727f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    while (searchHash != matchHash || memcmp(searchCharacters + delta, matchCharacters, matchLength * sizeof(UChar))) {
728f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        if (!delta)
729f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick            return notFound;
730f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        delta--;
731f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        searchHash -= searchCharacters[delta + matchLength];
732f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        searchHash += searchCharacters[delta];
733f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    }
734f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    return delta;
7358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
737f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merricksize_t StringImpl::reverseFindIgnoringCase(StringImpl* matchString, unsigned index)
7388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
739f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Check for null or empty string to match against
740f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (!matchString)
741f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return notFound;
742f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned matchLength = matchString->length();
743f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (!matchLength)
744f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return min(index, length());
745f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
746f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Check index & matchLength are in range.
747f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (matchLength > length())
748f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return notFound;
749f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // delta is the number of additional times to test; delta == 0 means test only once.
750f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned delta = min(index, length() - matchLength);
7518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
752f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const UChar *searchCharacters = characters();
753f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    const UChar *matchCharacters = matchString->characters();
754f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
755f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // keep looping until we match
756f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    while (!equalIgnoringCase(searchCharacters + delta, matchCharacters, matchLength)) {
757f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        if (!delta)
758f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick            return notFound;
759f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        delta--;
7608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
761f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    return delta;
7628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool StringImpl::endsWith(StringImpl* m_data, bool caseSensitive)
7658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(m_data);
767f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (m_length >= m_data->m_length) {
768f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        unsigned start = m_length - m_data->m_length;
769f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return (caseSensitive ? find(m_data, start) : findIgnoringCase(m_data, start)) == start;
770f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    }
7718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
7728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<StringImpl> StringImpl::replace(UChar oldC, UChar newC)
7758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (oldC == newC)
7778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return this;
7788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned i;
7798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (i = 0; i != m_length; ++i)
7808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (m_data[i] == oldC)
7818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
7828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (i == m_length)
7838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return this;
7848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    UChar* data;
7866b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
7875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
7888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (i = 0; i != m_length; ++i) {
7898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        UChar ch = m_data[i];
7908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (ch == oldC)
7918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ch = newC;
7928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        data[i] = ch;
7938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
7946b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return newImpl.release();
7958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<StringImpl> StringImpl::replace(unsigned position, unsigned lengthToReplace, StringImpl* str)
7988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    position = min(position, length());
8008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    lengthToReplace = min(lengthToReplace, length() - position);
8018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned lengthToInsert = str ? str->length() : 0;
8028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!lengthToReplace && !lengthToInsert)
8038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return this;
8045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    UChar* data;
8055ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
8065ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if ((length() - lengthToReplace) >= (numeric_limits<unsigned>::max() - lengthToInsert))
8075ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        CRASH();
8085ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
8096b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    RefPtr<StringImpl> newImpl =
8105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        createUninitialized(length() - lengthToReplace + lengthToInsert, data);
8115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    memcpy(data, characters(), position * sizeof(UChar));
8128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (str)
8135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        memcpy(data + position, str->characters(), lengthToInsert * sizeof(UChar));
8145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    memcpy(data + position + lengthToInsert, characters() + position + lengthToReplace,
8158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        (length() - position - lengthToReplace) * sizeof(UChar));
8166b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return newImpl.release();
8178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<StringImpl> StringImpl::replace(UChar pattern, StringImpl* replacement)
8208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!replacement)
8228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return this;
8238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
824f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned repStrLength = replacement->length();
825f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    size_t srcSegmentStart = 0;
826f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned matchCount = 0;
8278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Count the matches
829f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    while ((srcSegmentStart = find(pattern, srcSegmentStart)) != notFound) {
8308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ++matchCount;
8318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ++srcSegmentStart;
8328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // If we have 0 matches, we don't have to do any more work
8358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!matchCount)
8368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return this;
8378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8385ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (repStrLength && matchCount > numeric_limits<unsigned>::max() / repStrLength)
8395ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        CRASH();
8405ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
8415ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    unsigned replaceSize = matchCount * repStrLength;
8425ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    unsigned newSize = m_length - matchCount;
8435ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (newSize >= (numeric_limits<unsigned>::max() - replaceSize))
8445ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        CRASH();
8455ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
8465ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    newSize += replaceSize;
8475ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
8485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    UChar* data;
8496b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
8505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
8518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Construct the new data
852f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    size_t srcSegmentEnd;
853f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned srcSegmentLength;
8548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    srcSegmentStart = 0;
855f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned dstOffset = 0;
8568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
857f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != notFound) {
8588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        srcSegmentLength = srcSegmentEnd - srcSegmentStart;
8595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
8608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        dstOffset += srcSegmentLength;
8615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        memcpy(data + dstOffset, replacement->m_data, repStrLength * sizeof(UChar));
8628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        dstOffset += repStrLength;
8638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        srcSegmentStart = srcSegmentEnd + 1;
8648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    srcSegmentLength = m_length - srcSegmentStart;
8675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
8688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
869f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    ASSERT(dstOffset + srcSegmentLength == newImpl->length());
8708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8716b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return newImpl.release();
8728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<StringImpl> StringImpl::replace(StringImpl* pattern, StringImpl* replacement)
8758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!pattern || !replacement)
8778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return this;
8788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
879f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned patternLength = pattern->length();
8808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!patternLength)
8818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return this;
8828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
883f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned repStrLength = replacement->length();
884f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    size_t srcSegmentStart = 0;
885f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned matchCount = 0;
8868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Count the matches
888f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    while ((srcSegmentStart = find(pattern, srcSegmentStart)) != notFound) {
8898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ++matchCount;
8908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        srcSegmentStart += patternLength;
8918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // If we have 0 matches, we don't have to do any more work
8948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!matchCount)
8958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return this;
8968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8975ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    unsigned newSize = m_length - matchCount * patternLength;
8985ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (repStrLength && matchCount > numeric_limits<unsigned>::max() / repStrLength)
8995ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        CRASH();
9005ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
9015ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (newSize > (numeric_limits<unsigned>::max() - matchCount * repStrLength))
9025ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        CRASH();
9035ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
9045ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    newSize += matchCount * repStrLength;
9055ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
9065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    UChar* data;
9076b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
9088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Construct the new data
910f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    size_t srcSegmentEnd;
911f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned srcSegmentLength;
9128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    srcSegmentStart = 0;
913f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned dstOffset = 0;
9148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
915f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != notFound) {
9168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        srcSegmentLength = srcSegmentEnd - srcSegmentStart;
9175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
9188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        dstOffset += srcSegmentLength;
9195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        memcpy(data + dstOffset, replacement->m_data, repStrLength * sizeof(UChar));
9208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        dstOffset += repStrLength;
9218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        srcSegmentStart = srcSegmentEnd + patternLength;
9228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    srcSegmentLength = m_length - srcSegmentStart;
9255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
9268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
927f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    ASSERT(dstOffset + srcSegmentLength == newImpl->length());
9288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9296b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return newImpl.release();
9308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
932dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockbool equal(const StringImpl* a, const StringImpl* b)
9338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return StringHash::equal(a, b);
9358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
937dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockbool equal(const StringImpl* a, const char* b)
9388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!a)
9408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return !b;
9418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!b)
9428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return !a;
9438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned length = a->length();
9458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const UChar* as = a->characters();
9468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (unsigned i = 0; i != length; ++i) {
9478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        unsigned char bc = b[i];
9488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!bc)
9498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
9508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (as[i] != bc)
9518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
9528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return !b[length];
9558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool equalIgnoringCase(StringImpl* a, StringImpl* b)
9588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return CaseFoldingHash::equal(a, b);
9608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool equalIgnoringCase(StringImpl* a, const char* b)
9638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!a)
9658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return !b;
9668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!b)
9678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return !a;
9688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned length = a->length();
9708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const UChar* as = a->characters();
9718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Do a faster loop for the case where all the characters are ASCII.
9738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    UChar ored = 0;
9748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool equal = true;
9758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (unsigned i = 0; i != length; ++i) {
9768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        char bc = b[i];
9778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!bc)
9788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
9798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        UChar ac = as[i];
9808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ored |= ac;
9818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        equal = equal && (toASCIILower(ac) == toASCIILower(bc));
9828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Do a slower implementation for cases that include non-ASCII characters.
9858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (ored & ~0x7F) {
9868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        equal = true;
9878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (unsigned i = 0; i != length; ++i) {
9888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            unsigned char bc = b[i];
9898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            equal = equal && (foldCase(as[i]) == foldCase(bc));
9908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
9918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return equal && !b[length];
9948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochbool equalIgnoringNullity(StringImpl* a, StringImpl* b)
9970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
9980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (StringHash::equal(a, b))
9990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return true;
10000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!a && b && !b->length())
10010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return true;
10020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!b && a && !a->length())
10030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return true;
10040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
10050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return false;
10060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
10070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
100881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochWTF::Unicode::Direction StringImpl::defaultWritingDirection(bool* hasStrongDirectionality)
10098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
10108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (unsigned i = 0; i < m_length; ++i) {
10118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        WTF::Unicode::Direction charDirection = WTF::Unicode::direction(m_data[i]);
101281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (charDirection == WTF::Unicode::LeftToRight) {
101381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            if (hasStrongDirectionality)
101481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                *hasStrongDirectionality = true;
10158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return WTF::Unicode::LeftToRight;
101681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        }
101781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (charDirection == WTF::Unicode::RightToLeft || charDirection == WTF::Unicode::RightToLeftArabic) {
101881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            if (hasStrongDirectionality)
101981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                *hasStrongDirectionality = true;
10208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return WTF::Unicode::RightToLeft;
102181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        }
10228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
102381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (hasStrongDirectionality)
102481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        *hasStrongDirectionality = false;
10258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return WTF::Unicode::LeftToRight;
10268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// This is a hot function because it's used when parsing HTML.
10298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianPassRefPtr<StringImpl> StringImpl::createStrippingNullCharactersSlowCase(const UChar* characters, unsigned length)
10308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
10318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    StringBuffer strippedCopy(length);
10328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned strippedLength = 0;
10338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (unsigned i = 0; i < length; i++) {
10348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (int c = characters[i])
10358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            strippedCopy[strippedLength++] = c;
10368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
10378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(strippedLength < length);  // Only take the slow case when stripping.
10388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    strippedCopy.shrink(strippedLength);
10398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return adopt(strippedCopy);
10408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<StringImpl> StringImpl::adopt(StringBuffer& buffer)
10438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
10448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned length = buffer.length();
10458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (length == 0)
10468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return empty();
1047cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    return adoptRef(new StringImpl(buffer.release(), length));
10488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<StringImpl> StringImpl::createWithTerminatingNullCharacter(const StringImpl& string)
10518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1052231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // Use createUninitialized instead of 'new StringImpl' so that the string and its buffer
10536b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // get allocated in a single memory block.
1054231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    UChar* data;
10556b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    unsigned length = string.m_length;
10566b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (length >= numeric_limits<unsigned>::max())
10576b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        CRASH();
1058231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    RefPtr<StringImpl> terminatedString = createUninitialized(length + 1, data);
1059231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    memcpy(data, string.m_data, length * sizeof(UChar));
1060231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    data[length] = 0;
1061231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    terminatedString->m_length--;
1062231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    terminatedString->m_hash = string.m_hash;
1063692e5dbf12901edacf14812a6fae25462920af42Steve Block    terminatedString->m_refCountAndFlags |= s_refCountFlagHasTerminatingNullCharacter;
1064231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return terminatedString.release();
10658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1067231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockPassRefPtr<StringImpl> StringImpl::threadsafeCopy() const
10688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1069231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return create(m_data, m_length);
1070231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
1071231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1072231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockPassRefPtr<StringImpl> StringImpl::crossThreadString()
1073231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
1074692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (SharedUChar* sharedBuffer = this->sharedBuffer())
1075692e5dbf12901edacf14812a6fae25462920af42Steve Block        return adoptRef(new StringImpl(m_data, m_length, sharedBuffer->crossThreadCopy()));
1076231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1077231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // If no shared buffer is available, create a copy.
1078231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return threadsafeCopy();
10798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1081dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch} // namespace WTF
1082