15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *           (C) 1999 Antti Koivisto (koivisto@kde.org)
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *           (C) 2001 Dirk Mueller ( mueller@kde.org )
5926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved.
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version.
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful,
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details.
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB.  If not, write to
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA.
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
2693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "wtf/text/StringImpl.h"
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
28f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)#include "wtf/DynamicAnnotations.h"
298abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)#include "wtf/LeakAnnotations.h"
301e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "wtf/MainThread.h"
3109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "wtf/OwnPtr.h"
32bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "wtf/PartitionAlloc.h"
3309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "wtf/PassOwnPtr.h"
3493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "wtf/StdLibExtras.h"
35bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "wtf/WTF.h"
3693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "wtf/text/AtomicString.h"
3793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "wtf/text/StringBuffer.h"
3893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "wtf/text/StringHash.h"
3993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "wtf/unicode/CharacterNames.h"
4009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include <unicode/translit.h>
4109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include <unicode/unistr.h>
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifdef STRING_STATS
4493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "wtf/DataLog.h"
4551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "wtf/HashMap.h"
4651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "wtf/HashSet.h"
47f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#include "wtf/ProcessID.h"
485267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "wtf/RefCounted.h"
4951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "wtf/ThreadingPrimitives.h"
50926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#include <unistd.h>
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace std;
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WTF {
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace Unicode;
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
59f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)COMPILE_ASSERT(sizeof(StringImpl) == 3 * sizeof(int), StringImpl_should_stay_small);
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifdef STRING_STATS
6293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
6393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)static Mutex& statsMutex()
6493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
6593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    DEFINE_STATIC_LOCAL(Mutex, mutex, ());
6693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    return mutex;
6793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
6893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
6993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)static HashSet<void*>& liveStrings()
7093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
7193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    // Notice that we can't use HashSet<StringImpl*> because then HashSet would dedup identical strings.
7293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    DEFINE_STATIC_LOCAL(HashSet<void*>, strings, ());
7393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    return strings;
7493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
7593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
7693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)void addStringForStats(StringImpl* string)
7793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
7893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    MutexLocker locker(statsMutex());
7993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    liveStrings().add(string);
8093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
8193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
8293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)void removeStringForStats(StringImpl* string)
8393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
8493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    MutexLocker locker(statsMutex());
8593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    liveStrings().remove(string);
8693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
8793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
8893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)static void fillWithSnippet(const StringImpl* string, Vector<char>& snippet)
8993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
905267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    const unsigned kMaxSnippetLength = 64;
9193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    snippet.clear();
925267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
935267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    size_t expectedLength = std::min(string->length(), kMaxSnippetLength);
945267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (expectedLength == kMaxSnippetLength)
955267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        expectedLength += 3; // For the "...".
965267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    ++expectedLength; // For the terminating '\0'.
975267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    snippet.reserveCapacity(expectedLength);
985267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
9993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    size_t i;
1005267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    for (i = 0; i < string->length() && i < kMaxSnippetLength; ++i) {
10193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        UChar c = (*string)[i];
10293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (isASCIIPrintable(c))
10393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            snippet.append(c);
1045267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        else
1055267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            snippet.append('?');
10693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
10793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (i < string->length()) {
10893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        snippet.append('.');
10993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        snippet.append('.');
11093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        snippet.append('.');
11193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
11293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    snippet.append('\0');
11393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
11493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
1155267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)static bool isUnnecessarilyWide(const StringImpl* string)
1165267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
1175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (string->is8Bit())
1185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return false;
1195267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    UChar c = 0;
1205267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    for (unsigned i = 0; i < string->length(); ++i)
1215267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        c |= (*string)[i] >> 8;
1225267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return !c;
1235267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
1245267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
1255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)class PerStringStats : public RefCounted<PerStringStats> {
1265267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)public:
1275267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    static PassRefPtr<PerStringStats> create()
12893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    {
1295267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return adoptRef(new PerStringStats);
13093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
13193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
13293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    void add(const StringImpl* string)
13393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    {
13493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        ++m_numberOfCopies;
13593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (!m_length) {
13693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            m_length = string->length();
13793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            fillWithSnippet(string, m_snippet);
13893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        }
13993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (string->isAtomic())
14093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            ++m_numberOfAtomicCopies;
1415267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        if (isUnnecessarilyWide(string))
1425267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            m_unnecessarilyWide = true;
14393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
14493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
1455267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    size_t totalCharacters() const
14693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    {
1475267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return m_numberOfCopies * m_length;
14893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
14993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
15093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    void print()
15193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    {
1525267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        const char* status = "ok";
1537757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        if (m_unnecessarilyWide)
1545267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            status = "16";
1555267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        dataLogF("%8u copies (%s) of length %8u %s\n", m_numberOfCopies, status, m_length, m_snippet.data());
15693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
15793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
1585267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    bool m_unnecessarilyWide;
15993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    unsigned m_numberOfCopies;
16093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    unsigned m_length;
16193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    unsigned m_numberOfAtomicCopies;
16293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    Vector<char> m_snippet;
1635267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
1645267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)private:
1655267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    PerStringStats()
1667757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        : m_unnecessarilyWide(false)
1675267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        , m_numberOfCopies(0)
1685267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        , m_length(0)
1695267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        , m_numberOfAtomicCopies(0)
1705267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    {
1715267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    }
17293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)};
17393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
1745267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)bool operator<(const RefPtr<PerStringStats>& a, const RefPtr<PerStringStats>& b)
17593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
1765267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (a->m_unnecessarilyWide != b->m_unnecessarilyWide)
1775267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return !a->m_unnecessarilyWide && b->m_unnecessarilyWide;
1785267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (a->totalCharacters() != b->totalCharacters())
1795267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return a->totalCharacters() < b->totalCharacters();
1805267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (a->m_numberOfCopies != b->m_numberOfCopies)
1815267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return a->m_numberOfCopies < b->m_numberOfCopies;
1825267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (a->m_length != b->m_length)
1835267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return a->m_length < b->m_length;
1845267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return a->m_numberOfAtomicCopies < b->m_numberOfAtomicCopies;
18593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
18693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
18793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)static void printLiveStringStats(void*)
18893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
18993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    MutexLocker locker(statsMutex());
19093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    HashSet<void*>& strings = liveStrings();
19193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
1925267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    HashMap<StringImpl*, RefPtr<PerStringStats> > stats;
19393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    for (HashSet<void*>::iterator iter = strings.begin(); iter != strings.end(); ++iter) {
19493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        StringImpl* string = static_cast<StringImpl*>(*iter);
1955267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        HashMap<StringImpl*, RefPtr<PerStringStats> >::iterator entry = stats.find(string);
1965267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        RefPtr<PerStringStats> value = entry == stats.end() ? RefPtr<PerStringStats>(PerStringStats::create()) : entry->value;
1975267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        value->add(string);
1985267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        stats.set(string, value.release());
19993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
20093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
2015267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    Vector<RefPtr<PerStringStats> > all;
2025267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    for (HashMap<StringImpl*, RefPtr<PerStringStats> >::iterator iter = stats.begin(); iter != stats.end(); ++iter)
20393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        all.append(iter->value);
2045267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
20593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    std::sort(all.begin(), all.end());
20693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    std::reverse(all.begin(), all.end());
20793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    for (size_t i = 0; i < 20 && i < all.size(); ++i)
2085267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        all[i]->print();
20993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
21093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)StringStats StringImpl::m_stringStats;
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)unsigned StringStats::s_stringRemovesTillPrintStats = StringStats::s_printStringStatsFrequency;
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void StringStats::removeString(StringImpl* string)
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned length = string->length();
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    --m_totalNumberStrings;
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (string->is8Bit()) {
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        --m_number8BitStrings;
2227757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        m_total8BitData -= length;
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        --m_number16BitStrings;
2257757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        m_total16BitData -= length;
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!--s_stringRemovesTillPrintStats) {
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        s_stringRemovesTillPrintStats = s_printStringStatsFrequency;
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        printStats();
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void StringStats::printStats()
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
23653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    dataLogF("String stats for process id %d:\n", getCurrentProcessID());
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned long long totalNumberCharacters = m_total8BitData + m_total16BitData;
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double percent8Bit = m_totalNumberStrings ? ((double)m_number8BitStrings * 100) / (double)m_totalNumberStrings : 0.0;
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double average8bitLength = m_number8BitStrings ? (double)m_total8BitData / (double)m_number8BitStrings : 0.0;
241926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    dataLogF("%8u (%5.2f%%) 8 bit        %12llu chars  %12llu bytes  avg length %6.1f\n", m_number8BitStrings, percent8Bit, m_total8BitData, m_total8BitData, average8bitLength);
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double percent16Bit = m_totalNumberStrings ? ((double)m_number16BitStrings * 100) / (double)m_totalNumberStrings : 0.0;
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double average16bitLength = m_number16BitStrings ? (double)m_total16BitData / (double)m_number16BitStrings : 0.0;
245926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    dataLogF("%8u (%5.2f%%) 16 bit       %12llu chars  %12llu bytes  avg length %6.1f\n", m_number16BitStrings, percent16Bit, m_total16BitData, m_total16BitData * 2, average16bitLength);
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double averageLength = m_totalNumberStrings ? (double)totalNumberCharacters / (double)m_totalNumberStrings : 0.0;
2487757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    unsigned long long totalDataBytes = m_total8BitData + m_total16BitData * 2;
249926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    dataLogF("%8u Total                 %12llu chars  %12llu bytes  avg length %6.1f\n", m_totalNumberStrings, totalNumberCharacters, totalDataBytes, averageLength);
2507757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    unsigned long long totalSavedBytes = m_total8BitData;
251926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    double percentSavings = totalSavedBytes ? ((double)totalSavedBytes * 100) / (double)(totalDataBytes + totalSavedBytes) : 0.0;
252926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    dataLogF("         Total savings %12llu bytes (%5.2f%%)\n", totalSavedBytes, percentSavings);
25393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
2547757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    unsigned totalOverhead = m_totalNumberStrings * sizeof(StringImpl);
2557757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    double overheadPercent = (double)totalOverhead / (double)totalDataBytes * 100;
2567757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    dataLogF("         StringImpl overheader: %8u (%5.2f%%)\n", totalOverhead, overheadPercent);
2577757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
25893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    callOnMainThread(printLiveStringStats, 0);
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
262bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)void* StringImpl::operator new(size_t size)
263bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles){
264bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    ASSERT(size == sizeof(StringImpl));
265bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return partitionAllocGeneric(Partitions::getBufferPartition(), size);
266bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)}
267bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
268bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)void StringImpl::operator delete(void* ptr)
269bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles){
270bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    partitionFreeGeneric(Partitions::getBufferPartition(), ptr);
271bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)}
272bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
2738abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)inline StringImpl::~StringImpl()
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!isStatic());
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    STRING_STATS_REMOVE_STRING(this);
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isAtomic())
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        AtomicString::remove(this);
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2838abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)void StringImpl::destroyIfNotStatic()
2848abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles){
2858abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    if (!isStatic())
2868abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        delete this;
2878abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)}
2888abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, LChar*& data)
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!length) {
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        data = 0;
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return empty();
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Allocate a single buffer large enough to contain the StringImpl
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // struct as well as the data which it contains. This removes one
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // heap allocation from this call.
29909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    StringImpl* string = static_cast<StringImpl*>(partitionAllocGeneric(Partitions::getBufferPartition(), allocationSize<LChar>(length)));
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    data = reinterpret_cast<LChar*>(string + 1);
302bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return adoptRef(new (string) StringImpl(length, Force8BitConstructor));
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, UChar*& data)
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!length) {
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        data = 0;
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return empty();
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Allocate a single buffer large enough to contain the StringImpl
313591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // struct as well as the data which it contains. This removes one
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // heap allocation from this call.
31509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    StringImpl* string = static_cast<StringImpl*>(partitionAllocGeneric(Partitions::getBufferPartition(), allocationSize<UChar>(length)));
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    data = reinterpret_cast<UChar*>(string + 1);
318bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return adoptRef(new (string) StringImpl(length));
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
32109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::reallocate(PassRefPtr<StringImpl> originalString, unsigned length)
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(originalString->hasOneRef());
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
32509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!length)
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return empty();
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
32809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    bool is8Bit = originalString->is8Bit();
329bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    // Same as createUninitialized() except here we use realloc.
33009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    size_t size = is8Bit ? allocationSize<LChar>(length) : allocationSize<UChar>(length);
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    originalString->~StringImpl();
332bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    StringImpl* string = static_cast<StringImpl*>(partitionReallocGeneric(Partitions::getBufferPartition(), originalString.leakRef(), size));
33309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (is8Bit)
33409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return adoptRef(new (string) StringImpl(length, Force8BitConstructor));
335bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return adoptRef(new (string) StringImpl(length));
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)static StaticStringsTable& staticStrings()
3391e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles){
34009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    DEFINE_STATIC_LOCAL(StaticStringsTable, staticStrings, ());
3411e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    return staticStrings;
3421e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)}
3431e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
344197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT)
3451e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)static bool s_allowCreationOfStaticStrings = true;
3461e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#endif
3471e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
34809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const StaticStringsTable& StringImpl::allStaticStrings()
3491e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles){
3501e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    return staticStrings();
3511e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)}
3521e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
3531e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)void StringImpl::freezeStaticStrings()
3541e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles){
3551e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    ASSERT(isMainThread());
3561e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
357197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT)
3581e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    s_allowCreationOfStaticStrings = false;
3591e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#endif
3601e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)}
3611e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
36209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)unsigned StringImpl::m_highestStaticStringLength = 0;
36309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
364f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)StringImpl* StringImpl::createStatic(const char* string, unsigned length, unsigned hash)
365f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles){
3661e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    ASSERT(s_allowCreationOfStaticStrings);
367f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    ASSERT(string);
368f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    ASSERT(length);
369f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
37009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    StaticStringsTable::const_iterator it = staticStrings().find(hash);
37109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (it != staticStrings().end()) {
37209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        ASSERT(!memcmp(string, it->value + 1, length * sizeof(LChar)));
37309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return it->value;
37409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
37509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
376f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    // Allocate a single buffer large enough to contain the StringImpl
377f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    // struct as well as the data which it contains. This removes one
378f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    // heap allocation from this call.
379f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    RELEASE_ASSERT(length <= ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(LChar)));
380f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    size_t size = sizeof(StringImpl) + length * sizeof(LChar);
38109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
3828abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    WTF_ANNOTATE_SCOPED_MEMORY_LEAK;
383bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    StringImpl* impl = static_cast<StringImpl*>(partitionAllocGeneric(Partitions::getBufferPartition(), size));
384f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
385f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    LChar* data = reinterpret_cast<LChar*>(impl + 1);
386bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    impl = new (impl) StringImpl(length, hash, StaticString);
387f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    memcpy(data, string, length * sizeof(LChar));
388197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT)
389f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    impl->assertHashIsCorrect();
390f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#endif
3911e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
3921e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    ASSERT(isMainThread());
39309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_highestStaticStringLength = std::max(m_highestStaticStringLength, length);
39409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    staticStrings().add(hash, impl);
395f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    WTF_ANNOTATE_BENIGN_RACE(impl,
396f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        "Benign race on the reference counter of a static string created by StringImpl::createStatic");
3971e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
398f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    return impl;
399f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)}
400f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::create(const UChar* characters, unsigned length)
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!characters || !length)
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return empty();
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar* data;
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> string = createUninitialized(length, data);
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    memcpy(data, characters, length * sizeof(UChar));
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return string.release();
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::create(const LChar* characters, unsigned length)
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!characters || !length)
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return empty();
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LChar* data;
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> string = createUninitialized(length, data);
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    memcpy(data, characters, length * sizeof(LChar));
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return string.release();
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::create8BitIfPossible(const UChar* characters, unsigned length)
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!characters || !length)
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return empty();
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LChar* data;
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> string = createUninitialized(length, data);
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < length; ++i) {
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (characters[i] & 0xff00)
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return create(characters, length);
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        data[i] = static_cast<LChar>(characters[i]);
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return string.release();
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::create(const LChar* string)
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!string)
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return empty();
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t length = strlen(reinterpret_cast<const char*>(string));
44553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(length <= numeric_limits<unsigned>::max());
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return create(string, length);
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool StringImpl::containsOnlyWhitespace()
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: The definition of whitespace here includes a number of characters
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // that are not whitespace from the point of view of RenderText; I wonder if
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // that's a problem in practice.
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
455926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (unsigned i = 0; i < m_length; ++i) {
456f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            UChar c = characters8()[i];
4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!isASCIISpace(c))
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
464926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (unsigned i = 0; i < m_length; ++i) {
465f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        UChar c = characters16()[i];
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!isASCIISpace(c))
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::substring(unsigned start, unsigned length)
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (start >= m_length)
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return empty();
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned maxLength = m_length - start;
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (length >= maxLength) {
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!start)
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return this;
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        length = maxLength;
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
483f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        return create(characters8() + start, length);
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
485f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    return create(characters16() + start, length);
4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)UChar32 StringImpl::characterStartingAt(unsigned i)
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
491f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        return characters8()[i];
492f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    if (U16_IS_SINGLE(characters16()[i]))
493f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        return characters16()[i];
494f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    if (i + 1 < m_length && U16_IS_LEAD(characters16()[i]) && U16_IS_TRAIL(characters16()[i + 1]))
495f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        return U16_GET_SUPPLEMENTARY(characters16()[i], characters16()[i + 1]);
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::lower()
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Note: This is a hot function in the Dromaeo benchmark, specifically the
5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // no-op code path up through the first 'return' statement.
503591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // First scan the string for uppercase and non-ASCII characters:
5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool noUpper = true;
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar ored = 0;
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
508f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        const LChar* end = characters8() + m_length;
509f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        for (const LChar* chp = characters8(); chp != end; ++chp) {
5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (UNLIKELY(isASCIIUpper(*chp)))
5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                noUpper = false;
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ored |= *chp;
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Nothing to do if the string is all ASCII with no uppercase.
5155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (noUpper && !(ored & ~0x7F))
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return this;
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
51853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        RELEASE_ASSERT(m_length <= static_cast<unsigned>(numeric_limits<int32_t>::max()));
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int32_t length = m_length;
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar* data8;
5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<StringImpl> newImpl = createUninitialized(length, data8);
5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!(ored & ~0x7F)) {
525926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            for (int32_t i = 0; i < length; ++i)
526f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)                data8[i] = toASCIILower(characters8()[i]);
5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return newImpl.release();
5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Do a slower implementation for cases that include non-ASCII Latin-1 characters.
532926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (int32_t i = 0; i < length; ++i)
533f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            data8[i] = static_cast<LChar>(Unicode::toLower(characters8()[i]));
5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
538f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    const UChar* end = characters16() + m_length;
539f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    for (const UChar* chp = characters16(); chp != end; ++chp) {
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (UNLIKELY(isASCIIUpper(*chp)))
5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            noUpper = false;
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ored |= *chp;
5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Nothing to do if the string is all ASCII with no uppercase.
5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (noUpper && !(ored & ~0x7F))
5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
54853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(m_length <= static_cast<unsigned>(numeric_limits<int32_t>::max()));
5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int32_t length = m_length;
5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!(ored & ~0x7F)) {
5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        UChar* data16;
5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<StringImpl> newImpl = createUninitialized(m_length, data16);
554591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
555926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (int32_t i = 0; i < length; ++i) {
556f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            UChar c = characters16()[i];
5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            data16[i] = toASCIILower(c);
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
561591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Do a slower implementation for cases that include non-ASCII characters.
5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar* data16;
5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data16);
5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool error;
567f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    int32_t realLength = Unicode::toLower(data16, length, characters16(), m_length, &error);
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!error && realLength == length)
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newImpl = createUninitialized(realLength, data16);
572f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    Unicode::toLower(data16, realLength, characters16(), m_length, &error);
5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (error)
5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newImpl.release();
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::upper()
5795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // This function could be optimized for no-op cases the way lower() is,
5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // but in empirical testing, few actual calls to upper() are no-ops, so
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // it wouldn't be worth the extra time for pre-scanning.
5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
58453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(m_length <= static_cast<unsigned>(numeric_limits<int32_t>::max()));
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int32_t length = m_length;
5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar* data8;
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<StringImpl> newImpl = createUninitialized(m_length, data8);
590591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Do a faster loop for the case where all the characters are ASCII.
5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar ored = 0;
593926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (int i = 0; i < length; ++i) {
594f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            LChar c = characters8()[i];
5955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ored |= c;
5965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            data8[i] = toASCIIUpper(c);
5975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!(ored & ~0x7F))
5995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return newImpl.release();
6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Do a slower implementation for cases that include non-ASCII Latin-1 characters.
6025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int numberSharpSCharacters = 0;
6035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // There are two special cases.
6055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        //  1. latin-1 characters when converted to upper case are 16 bit characters.
6065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        //  2. Lower case sharp-S converts to "SS" (two characters)
607926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (int32_t i = 0; i < length; ++i) {
608f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            LChar c = characters8()[i];
6095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (UNLIKELY(c == smallLetterSharpS))
610926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                ++numberSharpSCharacters;
6115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            UChar upper = Unicode::toUpper(c);
6125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (UNLIKELY(upper > 0xff)) {
6135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // Since this upper-cased character does not fit in an 8-bit string, we need to take the 16-bit path.
6145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                goto upconvert;
6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            data8[i] = static_cast<LChar>(upper);
6175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!numberSharpSCharacters)
6205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return newImpl.release();
6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // We have numberSSCharacters sharp-s characters, but none of the other special characters.
6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        newImpl = createUninitialized(m_length + numberSharpSCharacters, data8);
6245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar* dest = data8;
6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
627926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (int32_t i = 0; i < length; ++i) {
628f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            LChar c = characters8()[i];
6295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (c == smallLetterSharpS) {
6305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                *dest++ = 'S';
6315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                *dest++ = 'S';
6325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            } else
6335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                *dest++ = static_cast<LChar>(Unicode::toUpper(c));
6345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
6355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
6375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)upconvert:
6401e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    RefPtr<StringImpl> upconverted = upconvertedString();
6411e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    const UChar* source16 = upconverted->characters16();
6425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar* data16;
6445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data16);
645591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
6465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Do a faster loop for the case where all the characters are ASCII.
6475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar ored = 0;
648926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (int i = 0; i < length; ++i) {
6495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        UChar c = source16[i];
6505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ored |= c;
6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        data16[i] = toASCIIUpper(c);
6525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!(ored & ~0x7F))
6545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
6555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Do a slower implementation for cases that include non-ASCII characters.
6575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool error;
6585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int32_t realLength = Unicode::toUpper(data16, length, source16, m_length, &error);
6595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!error && realLength == length)
6605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl;
6615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newImpl = createUninitialized(realLength, data16);
6625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Unicode::toUpper(data16, realLength, source16, m_length, &error);
6635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (error)
6645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
6655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newImpl.release();
6665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
66809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)static bool inline localeIdMatchesLang(const AtomicString& localeId, const char* lang)
6695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
67009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (equalIgnoringCase(localeId, lang))
67109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return true;
67209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static char localeIdPrefix[4];
67309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static const char delimeter[4] = "-_@";
67409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
67509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    size_t langLength = strlen(lang);
67609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RELEASE_ASSERT(langLength >= 2 && langLength <= 3);
67709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    strncpy(localeIdPrefix, lang, langLength);
67809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    for (int i = 0; i < 3; ++i) {
67909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        localeIdPrefix[langLength] = delimeter[i];
68009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // case-insensitive comparison
68109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (localeId.impl() && localeId.impl()->startsWith(localeIdPrefix, langLength + 1, false))
68209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return true;
68309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
68409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return false;
68509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
6861e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
68709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)typedef int32_t (*icuCaseConverter)(UChar*, int32_t, const UChar*, int32_t, const char*, UErrorCode*);
6885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
68909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)static PassRefPtr<StringImpl> caseConvert(const UChar* source16, size_t length, icuCaseConverter converter, const char* locale, StringImpl* originalString)
69009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
6911e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    UChar* data16;
69209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    int32_t targetLength = length;
69309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RefPtr<StringImpl> output = StringImpl::createUninitialized(length, data16);
6941e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    do {
6951e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        UErrorCode status = U_ZERO_ERROR;
69609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        targetLength = converter(data16, targetLength, source16, length, locale, &status);
6971e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        if (U_SUCCESS(status)) {
69809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            output->truncateAssumingIsolated(targetLength);
69909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return output.release();
7001e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        }
7011e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        if (status != U_BUFFER_OVERFLOW_ERROR)
70209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return originalString;
7031e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        // Expand the buffer.
70409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        output = StringImpl::createUninitialized(targetLength, data16);
7051e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    } while (true);
7061e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)}
7071e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
70809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::lower(const AtomicString& localeIdentifier)
70909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
71009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Use the more-optimized code path most of the time.
71109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Only Turkic (tr and az) languages and Lithuanian requires
71209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // locale-specific lowercasing rules. Even though CLDR has el-Lower,
71309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // it's identical to the locale-agnostic lowercasing. Context-dependent
71409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // handling of Greek capital sigma is built into the common lowercasing
71509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // function in ICU.
71609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    const char* localeForConversion = 0;
71709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (localeIdMatchesLang(localeIdentifier, "tr") || localeIdMatchesLang(localeIdentifier, "az"))
71809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        localeForConversion = "tr";
71909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    else if (localeIdMatchesLang(localeIdentifier, "lt"))
72009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        localeForConversion = "lt";
72109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    else
72209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return lower();
72309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
72409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (m_length > static_cast<unsigned>(numeric_limits<int32_t>::max()))
72509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        CRASH();
72609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    int length = m_length;
72709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
72809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RefPtr<StringImpl> upconverted = upconvertedString();
72909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    const UChar* source16 = upconverted->characters16();
73009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return caseConvert(source16, length, u_strToLower, localeForConversion, this);
73109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
73209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
7331e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)PassRefPtr<StringImpl> StringImpl::upper(const AtomicString& localeIdentifier)
7341e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles){
7351e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // Use the more-optimized code path most of the time.
73609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Only Turkic (tr and az) languages and Greek require locale-specific
73709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // lowercasing rules.
73809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    icu::UnicodeString transliteratorId;
73909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    const char* localeForConversion = 0;
74009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (localeIdMatchesLang(localeIdentifier, "tr") || localeIdMatchesLang(localeIdentifier, "az"))
74109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        localeForConversion = "tr";
74209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    else if (localeIdMatchesLang(localeIdentifier, "el"))
74309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        transliteratorId = UNICODE_STRING_SIMPLE("el-Upper");
74409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    else if (localeIdMatchesLang(localeIdentifier, "lt"))
74509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        localeForConversion = "lt";
74609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    else
7471e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        return upper();
7481e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
7491e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    if (m_length > static_cast<unsigned>(numeric_limits<int32_t>::max()))
7501e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        CRASH();
7511e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    int length = m_length;
7521e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
7531e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    RefPtr<StringImpl> upconverted = upconvertedString();
7541e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    const UChar* source16 = upconverted->characters16();
75509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
75609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (localeForConversion)
75709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return caseConvert(source16, length, u_strToUpper, localeForConversion, this);
75809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
75909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // TODO(jungshik): Cache transliterator if perf penaly warrants it for Greek.
76009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    UErrorCode status = U_ZERO_ERROR;
76109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    OwnPtr<icu::Transliterator> translit =
76209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        adoptPtr(icu::Transliterator::createInstance(transliteratorId, UTRANS_FORWARD, status));
76309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (U_FAILURE(status))
76409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return upper();
76509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
76609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // target will be copy-on-write.
76709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    icu::UnicodeString target(false, source16, length);
76809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    translit->transliterate(target);
76909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
77009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return create(target.getBuffer(), target.length());
7711e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)}
7721e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
7731e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)PassRefPtr<StringImpl> StringImpl::fill(UChar character)
7741e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles){
7755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!(character & ~0x7F)) {
7765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar* data;
7775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
7785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0; i < m_length; ++i)
7795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            data[i] = character;
7805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
7815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
7825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar* data;
7835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
7845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i < m_length; ++i)
7855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        data[i] = character;
7865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newImpl.release();
7875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::foldCase()
7905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
79153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(m_length <= static_cast<unsigned>(numeric_limits<int32_t>::max()));
7925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int32_t length = m_length;
7935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
7955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Do a faster loop for the case where all the characters are ASCII.
7965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar* data;
7975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr <StringImpl>newImpl = createUninitialized(m_length, data);
7985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar ored = 0;
7995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
800926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (int32_t i = 0; i < length; ++i) {
801f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            LChar c = characters8()[i];
8025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            data[i] = toASCIILower(c);
8035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ored |= c;
8045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
8055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!(ored & ~0x7F))
8075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return newImpl.release();
8085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Do a slower implementation for cases that include non-ASCII Latin-1 characters.
810926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (int32_t i = 0; i < length; ++i)
811f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            data[i] = static_cast<LChar>(Unicode::toLower(characters8()[i]));
8125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
8145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Do a faster loop for the case where all the characters are ASCII.
8175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar* data;
8185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
8195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar ored = 0;
820926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (int32_t i = 0; i < length; ++i) {
821f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        UChar c = characters16()[i];
8225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ored |= c;
8235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        data[i] = toASCIILower(c);
8245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!(ored & ~0x7F))
8265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
8275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Do a slower implementation for cases that include non-ASCII characters.
8295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool error;
830f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    int32_t realLength = Unicode::foldCase(data, length, characters16(), m_length, &error);
8315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!error && realLength == length)
8325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
8335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newImpl = createUninitialized(realLength, data);
834f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    Unicode::foldCase(data, realLength, characters16(), m_length, &error);
8355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (error)
8365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
8375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newImpl.release();
8385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template <class UCharPredicate>
8415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline PassRefPtr<StringImpl> StringImpl::stripMatchedCharacters(UCharPredicate predicate)
8425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_length)
8445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return empty();
8455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned start = 0;
8475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned end = m_length - 1;
848591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
8495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // skip white space from start
850f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    while (start <= end && predicate(is8Bit() ? characters8()[start] : characters16()[start]))
851926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ++start;
852591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
8535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // only white space
854591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (start > end)
8555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return empty();
8565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // skip white space from end
858f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    while (end && predicate(is8Bit() ? characters8()[end] : characters16()[end]))
859926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        --end;
8605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!start && end == m_length - 1)
8625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
8635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
864f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        return create(characters8() + start, end + 1 - start);
865f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    return create(characters16() + start, end + 1 - start);
8665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class UCharPredicate {
8695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
8705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    inline UCharPredicate(CharacterMatchFunctionPtr function): m_function(function) { }
8715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    inline bool operator()(UChar ch) const
8735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return m_function(ch);
8755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private:
8785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const CharacterMatchFunctionPtr m_function;
8795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
8805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class SpaceOrNewlinePredicate {
8825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
8835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    inline bool operator()(UChar ch) const
8845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return isSpaceOrNewline(ch);
8865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
8885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::stripWhiteSpace()
8905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return stripMatchedCharacters(SpaceOrNewlinePredicate());
8925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::stripWhiteSpace(IsWhiteSpaceFunctionPtr isWhiteSpace)
8955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return stripMatchedCharacters(UCharPredicate(isWhiteSpace));
8975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template <typename CharType>
9005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ALWAYS_INLINE PassRefPtr<StringImpl> StringImpl::removeCharacters(const CharType* characters, CharacterMatchFunctionPtr findMatch)
9015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const CharType* from = characters;
9035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const CharType* fromend = from + m_length;
904591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
9055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Assume the common case will not remove any characters
9065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (from != fromend && !findMatch(*from))
907926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ++from;
9085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (from == fromend)
9095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
910591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
9115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StringBuffer<CharType> data(m_length);
9125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CharType* to = data.characters();
9135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned outc = from - characters;
914591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
9155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (outc)
9165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        memcpy(to, characters, outc * sizeof(CharType));
9175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (true) {
9195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (from != fromend && findMatch(*from))
920926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            ++from;
9215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (from != fromend && !findMatch(*from))
9225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            to[outc++] = *from++;
9235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (from == fromend)
9245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
9255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
9265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    data.shrink(outc);
9285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
92983750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch    return data.release();
9305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::removeCharacters(CharacterMatchFunctionPtr findMatch)
9335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
9355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return removeCharacters(characters8(), findMatch);
9365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return removeCharacters(characters16(), findMatch);
9375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template <typename CharType, class UCharPredicate>
94019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)inline PassRefPtr<StringImpl> StringImpl::simplifyMatchedCharactersToSpace(UCharPredicate predicate, StripBehavior stripBehavior)
9415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StringBuffer<CharType> data(m_length);
9435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const CharType* from = getCharacters<CharType>();
9455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const CharType* fromend = from + m_length;
9465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int outc = 0;
9475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool changedToSpace = false;
948591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
9495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CharType* to = data.characters();
950591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
95119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)    if (stripBehavior == StripExtraWhiteSpace) {
95219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)        while (true) {
95319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)            while (from != fromend && predicate(*from)) {
95419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)                if (*from != ' ')
95519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)                    changedToSpace = true;
95619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)                ++from;
95719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)            }
95819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)            while (from != fromend && !predicate(*from))
95919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)                to[outc++] = *from++;
96019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)            if (from != fromend)
96119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)                to[outc++] = ' ';
96219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)            else
96319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)                break;
9645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
965591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
96619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)        if (outc > 0 && to[outc - 1] == ' ')
96719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)            --outc;
96819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)    } else {
96919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)        for (; from != fromend; ++from) {
97019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)            if (predicate(*from)) {
97119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)                if (*from != ' ')
97219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)                    changedToSpace = true;
97319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)                to[outc++] = ' ';
97419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)            } else {
97519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)                to[outc++] = *from;
97619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)            }
97719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)        }
97819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)    }
979591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
9805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (static_cast<unsigned>(outc) == m_length && !changedToSpace)
9815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
982591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
9835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    data.shrink(outc);
984591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
98583750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch    return data.release();
9865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
98819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)PassRefPtr<StringImpl> StringImpl::simplifyWhiteSpace(StripBehavior stripBehavior)
9895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
99119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)        return StringImpl::simplifyMatchedCharactersToSpace<LChar>(SpaceOrNewlinePredicate(), stripBehavior);
99219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)    return StringImpl::simplifyMatchedCharactersToSpace<UChar>(SpaceOrNewlinePredicate(), stripBehavior);
9935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
99519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)PassRefPtr<StringImpl> StringImpl::simplifyWhiteSpace(IsWhiteSpaceFunctionPtr isWhiteSpace, StripBehavior stripBehavior)
9965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
99819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)        return StringImpl::simplifyMatchedCharactersToSpace<LChar>(UCharPredicate(isWhiteSpace), stripBehavior);
99919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)    return StringImpl::simplifyMatchedCharactersToSpace<UChar>(UCharPredicate(isWhiteSpace), stripBehavior);
10005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)int StringImpl::toIntStrict(bool* ok, int base)
10035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToIntStrict(characters8(), m_length, ok, base);
10065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToIntStrict(characters16(), m_length, ok, base);
10075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)unsigned StringImpl::toUIntStrict(bool* ok, int base)
10105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToUIntStrict(characters8(), m_length, ok, base);
10135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToUIntStrict(characters16(), m_length, ok, base);
10145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)int64_t StringImpl::toInt64Strict(bool* ok, int base)
10175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToInt64Strict(characters8(), m_length, ok, base);
10205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToInt64Strict(characters16(), m_length, ok, base);
10215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)uint64_t StringImpl::toUInt64Strict(bool* ok, int base)
10245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToUInt64Strict(characters8(), m_length, ok, base);
10275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToUInt64Strict(characters16(), m_length, ok, base);
10285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)intptr_t StringImpl::toIntPtrStrict(bool* ok, int base)
10315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToIntPtrStrict(characters8(), m_length, ok, base);
10345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToIntPtrStrict(characters16(), m_length, ok, base);
10355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)int StringImpl::toInt(bool* ok)
10385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToInt(characters8(), m_length, ok);
10415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToInt(characters16(), m_length, ok);
10425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)unsigned StringImpl::toUInt(bool* ok)
10455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToUInt(characters8(), m_length, ok);
10485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToUInt(characters16(), m_length, ok);
10495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)int64_t StringImpl::toInt64(bool* ok)
10525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToInt64(characters8(), m_length, ok);
10555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToInt64(characters16(), m_length, ok);
10565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)uint64_t StringImpl::toUInt64(bool* ok)
10595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToUInt64(characters8(), m_length, ok);
10625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToUInt64(characters16(), m_length, ok);
10635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)intptr_t StringImpl::toIntPtr(bool* ok)
10665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToIntPtr(characters8(), m_length, ok);
10695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToIntPtr(characters16(), m_length, ok);
10705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)double StringImpl::toDouble(bool* ok)
10735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToDouble(characters8(), m_length, ok);
10765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToDouble(characters16(), m_length, ok);
10775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float StringImpl::toFloat(bool* ok)
10805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToFloat(characters8(), m_length, ok);
10835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToFloat(characters16(), m_length, ok);
10845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool equalIgnoringCase(const LChar* a, const LChar* b, unsigned length)
10875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (length--) {
10895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar bc = *b++;
10905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (foldCase(*a++) != foldCase(bc))
10915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
10925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
10935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
10945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool equalIgnoringCase(const UChar* a, const LChar* b, unsigned length)
10975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (length--) {
10995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar bc = *b++;
11005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (foldCase(*a++) != foldCase(bc))
11015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
11025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
11035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
11045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
11055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)size_t StringImpl::find(CharacterMatchFunctionPtr matchFunction, unsigned start)
11075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
11085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
11095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return WTF::find(characters8(), m_length, matchFunction, start);
11105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return WTF::find(characters16(), m_length, matchFunction, start);
11115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
11125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)size_t StringImpl::find(const LChar* matchString, unsigned index)
11145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
11155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check for null or empty string to match against
11165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchString)
111706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
11185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t matchStringLength = strlen(reinterpret_cast<const char*>(matchString));
111953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(matchStringLength <= numeric_limits<unsigned>::max());
11205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchLength = matchStringLength;
11215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchLength)
11225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return min(index, length());
11235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Optimization 1: fast case for strings of length 1.
11255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength == 1)
11265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return WTF::find(characters16(), length(), *matchString, index);
11275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check index & matchLength are in range.
11295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (index > length())
113006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
11315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned searchLength = length() - index;
11325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength > searchLength)
113306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
11345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // delta is the number of additional times to test; delta == 0 means test only once.
11355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned delta = searchLength - matchLength;
11365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11377757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    const UChar* searchCharacters = characters16() + index;
11385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Optimization 2: keep a running hash of the strings,
11405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // only call equal if the hashes match.
11415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned searchHash = 0;
11425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchHash = 0;
11435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i < matchLength; ++i) {
11445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        searchHash += searchCharacters[i];
11455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        matchHash += matchString[i];
11465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
11475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned i = 0;
11495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // keep looping until we match
11505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (searchHash != matchHash || !equal(searchCharacters + i, matchString, matchLength)) {
11515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (i == delta)
115206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)            return kNotFound;
11535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        searchHash += searchCharacters[i + matchLength];
11545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        searchHash -= searchCharacters[i];
11555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++i;
11565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
11575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return index + i;
11585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
11595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11607757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochtemplate<typename CharType>
11617757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochALWAYS_INLINE size_t findIgnoringCaseInternal(const CharType* searchCharacters, const LChar* matchString, unsigned index, unsigned searchLength, unsigned matchLength)
11627757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch{
11637757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    // delta is the number of additional times to test; delta == 0 means test only once.
11647757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    unsigned delta = searchLength - matchLength;
11657757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
11667757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    unsigned i = 0;
11677757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    while (!equalIgnoringCase(searchCharacters + i, matchString, matchLength)) {
11687757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        if (i == delta)
116906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)            return kNotFound;
11707757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        ++i;
11717757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    }
11727757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    return index + i;
11737757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch}
11747757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
11755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)size_t StringImpl::findIgnoringCase(const LChar* matchString, unsigned index)
11765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
11775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check for null or empty string to match against
11785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchString)
117906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
11805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t matchStringLength = strlen(reinterpret_cast<const char*>(matchString));
118153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(matchStringLength <= numeric_limits<unsigned>::max());
11825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchLength = matchStringLength;
11835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchLength)
11845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return min(index, length());
11855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check index & matchLength are in range.
11875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (index > length())
118806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
11895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned searchLength = length() - index;
11905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength > searchLength)
119106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
11925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11937757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    if (is8Bit())
11947757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return findIgnoringCaseInternal(characters8() + index, matchString, index, searchLength, matchLength);
11957757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    return findIgnoringCaseInternal(characters16() + index, matchString, index, searchLength, matchLength);
11965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
11975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template <typename SearchCharacterType, typename MatchCharacterType>
11997757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochALWAYS_INLINE static size_t findInternal(const SearchCharacterType* searchCharacters, const MatchCharacterType* matchCharacters, unsigned index, unsigned searchLength, unsigned matchLength)
12005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
12015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Optimization: keep a running hash of the strings,
12025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // only call equal() if the hashes match.
12035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // delta is the number of additional times to test; delta == 0 means test only once.
12055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned delta = searchLength - matchLength;
12065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned searchHash = 0;
12085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchHash = 0;
12095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i < matchLength; ++i) {
12115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        searchHash += searchCharacters[i];
12125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        matchHash += matchCharacters[i];
12135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned i = 0;
12165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // keep looping until we match
12175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (searchHash != matchHash || !equal(searchCharacters + i, matchCharacters, matchLength)) {
12185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (i == delta)
121906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)            return kNotFound;
12205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        searchHash += searchCharacters[i + matchLength];
12215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        searchHash -= searchCharacters[i];
12225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++i;
12235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1224591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return index + i;
12255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
12265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)size_t StringImpl::find(StringImpl* matchString)
12285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
12295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check for null string to match against
12305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (UNLIKELY(!matchString))
123106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
12325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchLength = matchString->length();
12335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Optimization 1: fast case for strings of length 1.
12355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength == 1) {
12365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (is8Bit()) {
12375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (matchString->is8Bit())
12385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return WTF::find(characters8(), length(), matchString->characters8()[0]);
12395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return WTF::find(characters8(), length(), matchString->characters16()[0]);
12405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
12415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (matchString->is8Bit())
12425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return WTF::find(characters16(), length(), matchString->characters8()[0]);
12435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return WTF::find(characters16(), length(), matchString->characters16()[0]);
12445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check matchLength is in range.
12475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength > length())
124806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
12495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check for empty string to match against
12515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (UNLIKELY(!matchLength))
12525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
12535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
12555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (matchString->is8Bit())
12567757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            return findInternal(characters8(), matchString->characters8(), 0, length(), matchLength);
12577757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return findInternal(characters8(), matchString->characters16(), 0, length(), matchLength);
12585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchString->is8Bit())
12617757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return findInternal(characters16(), matchString->characters8(), 0, length(), matchLength);
12625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12637757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    return findInternal(characters16(), matchString->characters16(), 0, length(), matchLength);
12645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
12655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)size_t StringImpl::find(StringImpl* matchString, unsigned index)
12675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
12685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check for null or empty string to match against
12695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (UNLIKELY(!matchString))
127006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
12715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchLength = matchString->length();
12735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Optimization 1: fast case for strings of length 1.
12755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength == 1) {
12765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (is8Bit())
12775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return WTF::find(characters8(), length(), (*matchString)[0], index);
12785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return WTF::find(characters16(), length(), (*matchString)[0], index);
12795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (UNLIKELY(!matchLength))
12825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return min(index, length());
12835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check index & matchLength are in range.
12855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (index > length())
128606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
12875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned searchLength = length() - index;
12885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength > searchLength)
128906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
12905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
12925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (matchString->is8Bit())
12937757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            return findInternal(characters8() + index, matchString->characters8(), index, searchLength, matchLength);
12947757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return findInternal(characters8() + index, matchString->characters16(), index, searchLength, matchLength);
12955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchString->is8Bit())
12987757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return findInternal(characters16() + index, matchString->characters8(), index, searchLength, matchLength);
12995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13007757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    return findInternal(characters16() + index, matchString->characters16(), index, searchLength, matchLength);
13015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
13025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template <typename SearchCharacterType, typename MatchCharacterType>
13045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ALWAYS_INLINE static size_t findIgnoringCaseInner(const SearchCharacterType* searchCharacters, const MatchCharacterType* matchCharacters, unsigned index, unsigned searchLength, unsigned matchLength)
13055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
13065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // delta is the number of additional times to test; delta == 0 means test only once.
13075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned delta = searchLength - matchLength;
13085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned i = 0;
13105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // keep looping until we match
13115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (!equalIgnoringCase(searchCharacters + i, matchCharacters, matchLength)) {
13125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (i == delta)
131306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)            return kNotFound;
13145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++i;
13155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
13165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return index + i;
13175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
13185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)size_t StringImpl::findIgnoringCase(StringImpl* matchString, unsigned index)
13205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
13215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check for null or empty string to match against
13225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchString)
132306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
13245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchLength = matchString->length();
13255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchLength)
13265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return min(index, length());
13275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check index & matchLength are in range.
13295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (index > length())
133006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
13315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned searchLength = length() - index;
13325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength > searchLength)
133306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
13345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
13365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (matchString->is8Bit())
13375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return findIgnoringCaseInner(characters8() + index, matchString->characters8(), index, searchLength, matchLength);
13385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return findIgnoringCaseInner(characters8() + index, matchString->characters16(), index, searchLength, matchLength);
13395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
13405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchString->is8Bit())
13425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return findIgnoringCaseInner(characters16() + index, matchString->characters8(), index, searchLength, matchLength);
13435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return findIgnoringCaseInner(characters16() + index, matchString->characters16(), index, searchLength, matchLength);
13455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
13465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1347926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)size_t StringImpl::findNextLineStart(unsigned index)
1348926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
1349926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (is8Bit())
1350926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return WTF::findNextLineStart(characters8(), m_length, index);
1351926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return WTF::findNextLineStart(characters16(), m_length, index);
1352926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
1353926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1354591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochsize_t StringImpl::count(LChar c) const
1355591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
1356591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    int count = 0;
1357591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (is8Bit()) {
1358591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        for (size_t i = 0; i < m_length; ++i)
1359591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            count += characters8()[i] == c;
1360591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    } else {
1361591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        for (size_t i = 0; i < m_length; ++i)
1362591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            count += characters16()[i] == c;
1363591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
1364591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return count;
1365591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
1366591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
13671e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)size_t StringImpl::reverseFind(UChar c, unsigned index)
13685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
13695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
13701e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        return WTF::reverseFind(characters8(), m_length, c, index);
13711e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    return WTF::reverseFind(characters16(), m_length, c, index);
13725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
13735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template <typename SearchCharacterType, typename MatchCharacterType>
13751e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)ALWAYS_INLINE static size_t reverseFindInner(const SearchCharacterType* searchCharacters, const MatchCharacterType* matchCharacters, unsigned index, unsigned length, unsigned matchLength)
13765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
13775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Optimization: keep a running hash of the strings,
13785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // only call equal if the hashes match.
13795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // delta is the number of additional times to test; delta == 0 means test only once.
13815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned delta = min(index, length - matchLength);
1382591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
13835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned searchHash = 0;
13845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchHash = 0;
13855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i < matchLength; ++i) {
13865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        searchHash += searchCharacters[delta + i];
13875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        matchHash += matchCharacters[i];
13885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
13895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // keep looping until we match
13915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (searchHash != matchHash || !equal(searchCharacters + delta, matchCharacters, matchLength)) {
13925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!delta)
139306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)            return kNotFound;
1394926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        --delta;
13955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        searchHash -= searchCharacters[delta + matchLength];
13965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        searchHash += searchCharacters[delta];
13975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
13981e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    return delta;
13995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
14005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14011e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)size_t StringImpl::reverseFind(StringImpl* matchString, unsigned index)
14025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
14035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check for null or empty string to match against
14045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchString)
140506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
14065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchLength = matchString->length();
14075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned ourLength = length();
14085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchLength)
14095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return min(index, ourLength);
14105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Optimization 1: fast case for strings of length 1.
14125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength == 1) {
14135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (is8Bit())
14141e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            return WTF::reverseFind(characters8(), ourLength, (*matchString)[0], index);
14151e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        return WTF::reverseFind(characters16(), ourLength, (*matchString)[0], index);
14165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
14175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check index & matchLength are in range.
14191e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    if (matchLength > ourLength)
142006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
14215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
14235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (matchString->is8Bit())
14241e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            return reverseFindInner(characters8(), matchString->characters8(), index, ourLength, matchLength);
14251e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        return reverseFindInner(characters8(), matchString->characters16(), index, ourLength, matchLength);
14265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1427591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
14285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchString->is8Bit())
14291e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        return reverseFindInner(characters16(), matchString->characters8(), index, ourLength, matchLength);
14305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14311e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    return reverseFindInner(characters16(), matchString->characters16(), index, ourLength, matchLength);
14325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
14335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template <typename SearchCharacterType, typename MatchCharacterType>
14355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ALWAYS_INLINE static size_t reverseFindIgnoringCaseInner(const SearchCharacterType* searchCharacters, const MatchCharacterType* matchCharacters, unsigned index, unsigned length, unsigned matchLength)
14365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
14375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // delta is the number of additional times to test; delta == 0 means test only once.
14385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned delta = min(index, length - matchLength);
14395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // keep looping until we match
14415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (!equalIgnoringCase(searchCharacters + delta, matchCharacters, matchLength)) {
14425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!delta)
144306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)            return kNotFound;
1444926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        --delta;
14455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
14465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return delta;
14475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
14485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)size_t StringImpl::reverseFindIgnoringCase(StringImpl* matchString, unsigned index)
14505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
14515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check for null or empty string to match against
14525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchString)
145306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
14545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchLength = matchString->length();
14555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned ourLength = length();
14565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchLength)
14575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return min(index, ourLength);
14585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check index & matchLength are in range.
14605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength > ourLength)
146106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
14625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
14645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (matchString->is8Bit())
14655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return reverseFindIgnoringCaseInner(characters8(), matchString->characters8(), index, ourLength, matchLength);
14665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return reverseFindIgnoringCaseInner(characters8(), matchString->characters16(), index, ourLength, matchLength);
14675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
14685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchString->is8Bit())
14705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return reverseFindIgnoringCaseInner(characters16(), matchString->characters8(), index, ourLength, matchLength);
14715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return reverseFindIgnoringCaseInner(characters16(), matchString->characters16(), index, ourLength, matchLength);
14735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
14745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ALWAYS_INLINE static bool equalInner(const StringImpl* stringImpl, unsigned startOffset, const char* matchString, unsigned matchLength, bool caseSensitive)
14765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
14775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(stringImpl);
14785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(matchLength <= stringImpl->length());
14795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(startOffset + matchLength <= stringImpl->length());
14805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (caseSensitive) {
14825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (stringImpl->is8Bit())
14835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return equal(stringImpl->characters8() + startOffset, reinterpret_cast<const LChar*>(matchString), matchLength);
14845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return equal(stringImpl->characters16() + startOffset, reinterpret_cast<const LChar*>(matchString), matchLength);
14855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
14865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (stringImpl->is8Bit())
14875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return equalIgnoringCase(stringImpl->characters8() + startOffset, reinterpret_cast<const LChar*>(matchString), matchLength);
14885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return equalIgnoringCase(stringImpl->characters16() + startOffset, reinterpret_cast<const LChar*>(matchString), matchLength);
14895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
14905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool StringImpl::startsWith(UChar character) const
14925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
14935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_length && (*this)[0] == character;
14945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
14955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool StringImpl::startsWith(const char* matchString, unsigned matchLength, bool caseSensitive) const
14975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
14985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(matchLength);
14995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength > length())
15005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
15015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return equalInner(this, 0, matchString, matchLength, caseSensitive);
15025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
15035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool StringImpl::endsWith(StringImpl* matchString, bool caseSensitive)
15055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
15065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(matchString);
15075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_length >= matchString->m_length) {
15085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unsigned start = m_length - matchString->m_length;
15095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return (caseSensitive ? find(matchString, start) : findIgnoringCase(matchString, start)) == start;
15105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
15115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
15125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
15135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool StringImpl::endsWith(UChar character) const
15155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
15165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_length && (*this)[m_length - 1] == character;
15175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
15185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool StringImpl::endsWith(const char* matchString, unsigned matchLength, bool caseSensitive) const
15205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
15215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(matchLength);
15225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength > length())
15235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
15245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned startOffset = length() - matchLength;
15255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return equalInner(this, startOffset, matchString, matchLength, caseSensitive);
15265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
15275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::replace(UChar oldC, UChar newC)
15295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
15305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (oldC == newC)
15315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
1532f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
1533f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (find(oldC) == kNotFound)
15345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
15355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1536f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    unsigned i;
15375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
15385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (newC <= 0xff) {
15395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            LChar* data;
15405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            LChar oldChar = static_cast<LChar>(oldC);
15415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            LChar newChar = static_cast<LChar>(newC);
15425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
15445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for (i = 0; i != m_length; ++i) {
1546f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)                LChar ch = characters8()[i];
15475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (ch == oldChar)
15485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    ch = newChar;
15495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                data[i] = ch;
15505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
15515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return newImpl.release();
15525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
15535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // There is the possibility we need to up convert from 8 to 16 bit,
15555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // create a 16 bit string for the result.
15565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        UChar* data;
15575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
15585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (i = 0; i != m_length; ++i) {
1560f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            UChar ch = characters8()[i];
15615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (ch == oldC)
15625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ch = newC;
15635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            data[i] = ch;
15645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
15655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
15675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
15685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar* data;
15705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
15715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (i = 0; i != m_length; ++i) {
1573f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        UChar ch = characters16()[i];
15745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (ch == oldC)
15755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ch = newC;
15765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        data[i] = ch;
15775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
15785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newImpl.release();
15795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
15805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::replace(unsigned position, unsigned lengthToReplace, StringImpl* str)
15825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
15835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    position = min(position, length());
15845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    lengthToReplace = min(lengthToReplace, length() - position);
15855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned lengthToInsert = str ? str->length() : 0;
15865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!lengthToReplace && !lengthToInsert)
15875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
15885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
158953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT((length() - lengthToReplace) < (numeric_limits<unsigned>::max() - lengthToInsert));
15905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit() && (!str || str->is8Bit())) {
15925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar* data;
15935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<StringImpl> newImpl =
15945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        createUninitialized(length() - lengthToReplace + lengthToInsert, data);
1595f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        memcpy(data, characters8(), position * sizeof(LChar));
15965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (str)
1597f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            memcpy(data + position, str->characters8(), lengthToInsert * sizeof(LChar));
1598f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        memcpy(data + position + lengthToInsert, characters8() + position + lengthToReplace,
15995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)               (length() - position - lengthToReplace) * sizeof(LChar));
16005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
16015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
16025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar* data;
16035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> newImpl =
16045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        createUninitialized(length() - lengthToReplace + lengthToInsert, data);
16055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
1606926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (unsigned i = 0; i < position; ++i)
1607f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            data[i] = characters8()[i];
16085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
1609f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        memcpy(data, characters16(), position * sizeof(UChar));
16105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (str) {
16115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (str->is8Bit())
1612926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            for (unsigned i = 0; i < lengthToInsert; ++i)
1613f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)                data[i + position] = str->characters8()[i];
16145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else
1615f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            memcpy(data + position, str->characters16(), lengthToInsert * sizeof(UChar));
16165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
16175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
1618926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (unsigned i = 0; i < length() - position - lengthToReplace; ++i)
1619f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            data[i + position + lengthToInsert] = characters8()[i + position + lengthToReplace];
16205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
16217757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        memcpy(data + position + lengthToInsert, characters16() + position + lengthToReplace,
16225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            (length() - position - lengthToReplace) * sizeof(UChar));
16235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
16245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newImpl.release();
16255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
16265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::replace(UChar pattern, StringImpl* replacement)
16285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
16295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!replacement)
16305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
16315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (replacement->is8Bit())
1633f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        return replace(pattern, replacement->characters8(), replacement->length());
16345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1635f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    return replace(pattern, replacement->characters16(), replacement->length());
16365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
16375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::replace(UChar pattern, const LChar* replacement, unsigned repStrLength)
16395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
16405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(replacement);
16415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t srcSegmentStart = 0;
16435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchCount = 0;
16445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Count the matches.
164606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    while ((srcSegmentStart = find(pattern, srcSegmentStart)) != kNotFound) {
16475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++matchCount;
16485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++srcSegmentStart;
16495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
16505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If we have 0 matches then we don't have to do any more work.
16525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchCount)
16535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
16545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
165553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(!repStrLength || matchCount <= numeric_limits<unsigned>::max() / repStrLength);
16565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned replaceSize = matchCount * repStrLength;
16585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned newSize = m_length - matchCount;
165953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(newSize < (numeric_limits<unsigned>::max() - replaceSize));
16605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newSize += replaceSize;
16625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Construct the new data.
16645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t srcSegmentEnd;
16655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned srcSegmentLength;
16665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    srcSegmentStart = 0;
16675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned dstOffset = 0;
16685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
16705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar* data;
16715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
16725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
167306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != kNotFound) {
16745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            srcSegmentLength = srcSegmentEnd - srcSegmentStart;
1675f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            memcpy(data + dstOffset, characters8() + srcSegmentStart, srcSegmentLength * sizeof(LChar));
16765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            dstOffset += srcSegmentLength;
16775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            memcpy(data + dstOffset, replacement, repStrLength * sizeof(LChar));
16785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            dstOffset += repStrLength;
16795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            srcSegmentStart = srcSegmentEnd + 1;
16805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
16815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        srcSegmentLength = m_length - srcSegmentStart;
1683f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        memcpy(data + dstOffset, characters8() + srcSegmentStart, srcSegmentLength * sizeof(LChar));
16845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(dstOffset + srcSegmentLength == newImpl->length());
16865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
16885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
16895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar* data;
16915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
16925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
169306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != kNotFound) {
16945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        srcSegmentLength = srcSegmentEnd - srcSegmentStart;
1695f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        memcpy(data + dstOffset, characters16() + srcSegmentStart, srcSegmentLength * sizeof(UChar));
16965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        dstOffset += srcSegmentLength;
16985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0; i < repStrLength; ++i)
16995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            data[i + dstOffset] = replacement[i];
17005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        dstOffset += repStrLength;
17025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        srcSegmentStart = srcSegmentEnd + 1;
17035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
17045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    srcSegmentLength = m_length - srcSegmentStart;
1706f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    memcpy(data + dstOffset, characters16() + srcSegmentStart, srcSegmentLength * sizeof(UChar));
17075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(dstOffset + srcSegmentLength == newImpl->length());
17095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newImpl.release();
17115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
17125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::replace(UChar pattern, const UChar* replacement, unsigned repStrLength)
17145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
17155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(replacement);
17165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t srcSegmentStart = 0;
17185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchCount = 0;
17195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Count the matches.
172106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    while ((srcSegmentStart = find(pattern, srcSegmentStart)) != kNotFound) {
17225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++matchCount;
17235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++srcSegmentStart;
17245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
17255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If we have 0 matches then we don't have to do any more work.
17275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchCount)
17285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
17295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
173053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(!repStrLength || matchCount <= numeric_limits<unsigned>::max() / repStrLength);
17315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned replaceSize = matchCount * repStrLength;
17335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned newSize = m_length - matchCount;
173453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(newSize < (numeric_limits<unsigned>::max() - replaceSize));
17355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newSize += replaceSize;
17375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Construct the new data.
17395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t srcSegmentEnd;
17405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned srcSegmentLength;
17415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    srcSegmentStart = 0;
17425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned dstOffset = 0;
17435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
17455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        UChar* data;
17465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
17475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
174806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != kNotFound) {
17495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            srcSegmentLength = srcSegmentEnd - srcSegmentStart;
17505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for (unsigned i = 0; i < srcSegmentLength; ++i)
1751f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)                data[i + dstOffset] = characters8()[i + srcSegmentStart];
17525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            dstOffset += srcSegmentLength;
17545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            memcpy(data + dstOffset, replacement, repStrLength * sizeof(UChar));
17555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            dstOffset += repStrLength;
17575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            srcSegmentStart = srcSegmentEnd + 1;
17585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
17595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        srcSegmentLength = m_length - srcSegmentStart;
17615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0; i < srcSegmentLength; ++i)
1762f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            data[i + dstOffset] = characters8()[i + srcSegmentStart];
17635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(dstOffset + srcSegmentLength == newImpl->length());
17655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
17675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
17685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar* data;
17705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
17715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
177206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != kNotFound) {
17735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        srcSegmentLength = srcSegmentEnd - srcSegmentStart;
1774f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        memcpy(data + dstOffset, characters16() + srcSegmentStart, srcSegmentLength * sizeof(UChar));
17755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        dstOffset += srcSegmentLength;
17775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        memcpy(data + dstOffset, replacement, repStrLength * sizeof(UChar));
17785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        dstOffset += repStrLength;
17805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        srcSegmentStart = srcSegmentEnd + 1;
17815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
17825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    srcSegmentLength = m_length - srcSegmentStart;
1784f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    memcpy(data + dstOffset, characters16() + srcSegmentStart, srcSegmentLength * sizeof(UChar));
17855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(dstOffset + srcSegmentLength == newImpl->length());
17875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newImpl.release();
17895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
17905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::replace(StringImpl* pattern, StringImpl* replacement)
17925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
17935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!pattern || !replacement)
17945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
17955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned patternLength = pattern->length();
17975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!patternLength)
17985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
1799591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
18005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned repStrLength = replacement->length();
18015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t srcSegmentStart = 0;
18025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchCount = 0;
1803591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
18045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Count the matches.
180506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    while ((srcSegmentStart = find(pattern, srcSegmentStart)) != kNotFound) {
18065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++matchCount;
18075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        srcSegmentStart += patternLength;
18085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1809591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
18105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If we have 0 matches, we don't have to do any more work
18115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchCount)
18125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
1813591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
18145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned newSize = m_length - matchCount * patternLength;
181553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(!repStrLength || matchCount <= numeric_limits<unsigned>::max() / repStrLength);
18165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
181753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(newSize <= (numeric_limits<unsigned>::max() - matchCount * repStrLength));
18185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newSize += matchCount * repStrLength;
18205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1821591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
18225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Construct the new data
18235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t srcSegmentEnd;
18245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned srcSegmentLength;
18255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    srcSegmentStart = 0;
18265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned dstOffset = 0;
18275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool srcIs8Bit = is8Bit();
18285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool replacementIs8Bit = replacement->is8Bit();
1829591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
18305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // There are 4 cases:
18315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // 1. This and replacement are both 8 bit.
18325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // 2. This and replacement are both 16 bit.
18335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // 3. This is 8 bit and replacement is 16 bit.
18345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // 4. This is 16 bit and replacement is 8 bit.
18355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (srcIs8Bit && replacementIs8Bit) {
18365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Case 1
18375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar* data;
18385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
183906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != kNotFound) {
18405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            srcSegmentLength = srcSegmentEnd - srcSegmentStart;
1841f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            memcpy(data + dstOffset, characters8() + srcSegmentStart, srcSegmentLength * sizeof(LChar));
18425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            dstOffset += srcSegmentLength;
1843f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            memcpy(data + dstOffset, replacement->characters8(), repStrLength * sizeof(LChar));
18445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            dstOffset += repStrLength;
18455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            srcSegmentStart = srcSegmentEnd + patternLength;
18465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
18475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        srcSegmentLength = m_length - srcSegmentStart;
1849f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        memcpy(data + dstOffset, characters8() + srcSegmentStart, srcSegmentLength * sizeof(LChar));
18505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(dstOffset + srcSegmentLength == newImpl->length());
18525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
18545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
18555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar* data;
18575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
185806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != kNotFound) {
18595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        srcSegmentLength = srcSegmentEnd - srcSegmentStart;
18605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (srcIs8Bit) {
18615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Case 3.
1862926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            for (unsigned i = 0; i < srcSegmentLength; ++i)
1863f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)                data[i + dstOffset] = characters8()[i + srcSegmentStart];
18645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
18655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Case 2 & 4.
1866f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            memcpy(data + dstOffset, characters16() + srcSegmentStart, srcSegmentLength * sizeof(UChar));
18675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
18685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        dstOffset += srcSegmentLength;
18695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (replacementIs8Bit) {
18705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Cases 2 & 3.
1871926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            for (unsigned i = 0; i < repStrLength; ++i)
1872f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)                data[i + dstOffset] = replacement->characters8()[i];
18735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
18745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Case 4
1875f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            memcpy(data + dstOffset, replacement->characters16(), repStrLength * sizeof(UChar));
18765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
18775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        dstOffset += repStrLength;
18785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        srcSegmentStart = srcSegmentEnd + patternLength;
18795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
18805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    srcSegmentLength = m_length - srcSegmentStart;
18825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (srcIs8Bit) {
18835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Case 3.
1884926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (unsigned i = 0; i < srcSegmentLength; ++i)
1885f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            data[i + dstOffset] = characters8()[i + srcSegmentStart];
18865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
18875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Cases 2 & 4.
1888f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        memcpy(data + dstOffset, characters16() + srcSegmentStart, srcSegmentLength * sizeof(UChar));
18895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
18905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(dstOffset + srcSegmentLength == newImpl->length());
18925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newImpl.release();
18945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
18955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18961e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)PassRefPtr<StringImpl> StringImpl::upconvertedString()
18971e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles){
18981e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    if (is8Bit())
18991e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        return String::make16BitFrom8BitSource(characters8(), m_length).releaseImpl();
19001e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    return this;
19011e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)}
19021e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
1903926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)static inline bool stringImplContentEqual(const StringImpl* a, const StringImpl* b)
1904926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
1905926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    unsigned aLength = a->length();
1906926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    unsigned bLength = b->length();
1907926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (aLength != bLength)
1908926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return false;
1909926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1910926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (a->is8Bit()) {
1911926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (b->is8Bit())
1912926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return equal(a->characters8(), b->characters8(), aLength);
1913926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1914926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return equal(a->characters8(), b->characters16(), aLength);
1915926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
1916926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1917926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (b->is8Bit())
1918926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return equal(a->characters16(), b->characters8(), aLength);
1919926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1920926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return equal(a->characters16(), b->characters16(), aLength);
1921926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
1922926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
19235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool equal(const StringImpl* a, const StringImpl* b)
19245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1925926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (a == b)
1926926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return true;
1927926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!a || !b)
1928926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return false;
1929d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (a->isAtomic() && b->isAtomic())
1930d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return false;
1931926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1932926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return stringImplContentEqual(a, b);
19335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
19345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1935e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochtemplate <typename CharType>
1936e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochinline bool equalInternal(const StringImpl* a, const CharType* b, unsigned length)
19375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
19385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!a)
19395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return !b;
19405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!b)
19415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
19425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1943e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (a->length() != length)
1944e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        return false;
19455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (a->is8Bit())
19465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return equal(a->characters8(), b, length);
19475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return equal(a->characters16(), b, length);
19485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
19495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1950e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochbool equal(const StringImpl* a, const LChar* b, unsigned length)
1951e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch{
1952e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    return equalInternal(a, b, length);
1953e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch}
1954e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
1955e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochbool equal(const StringImpl* a, const UChar* b, unsigned length)
1956e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch{
1957e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    return equalInternal(a, b, length);
1958e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch}
1959e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
19605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool equal(const StringImpl* a, const LChar* b)
19615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
19625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!a)
19635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return !b;
19645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!b)
19655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return !a;
19665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned length = a->length();
19685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (a->is8Bit()) {
19705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const LChar* aPtr = a->characters8();
19715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0; i != length; ++i) {
19725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            LChar bc = b[i];
19735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            LChar ac = aPtr[i];
19745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!bc)
19755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
19765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (ac != bc)
19775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
19785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
19795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return !b[length];
19815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
19825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const UChar* aPtr = a->characters16();
19845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i != length; ++i) {
19855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar bc = b[i];
19865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!bc)
19875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
19885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (aPtr[i] != bc)
19895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
19905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
19915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return !b[length];
19935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
19945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1995926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool equalNonNull(const StringImpl* a, const StringImpl* b)
1996926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
1997926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(a && b);
1998926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (a == b)
1999926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return true;
2000926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2001926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return stringImplContentEqual(a, b);
2002926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
2003926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2004926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool equalIgnoringCase(const StringImpl* a, const StringImpl* b)
20055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2006926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (a == b)
2007926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return true;
2008926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!a || !b)
2009926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return false;
2010926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
20115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return CaseFoldingHash::equal(a, b);
20125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
20135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2014926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool equalIgnoringCase(const StringImpl* a, const LChar* b)
20155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
20165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!a)
20175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return !b;
20185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!b)
20195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return !a;
20205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned length = a->length();
20225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Do a faster loop for the case where all the characters are ASCII.
20245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar ored = 0;
20255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool equal = true;
20265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (a->is8Bit()) {
20275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const LChar* as = a->characters8();
20285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0; i != length; ++i) {
20295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            LChar bc = b[i];
20305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!bc)
20315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
20325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            UChar ac = as[i];
20335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ored |= ac;
20345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            equal = equal && (toASCIILower(ac) == toASCIILower(bc));
20355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2036591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
20375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Do a slower implementation for cases that include non-ASCII characters.
20385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (ored & ~0x7F) {
20395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            equal = true;
20405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for (unsigned i = 0; i != length; ++i)
20415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                equal = equal && (foldCase(as[i]) == foldCase(b[i]));
20425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2043591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
2044591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return equal && !b[length];
20455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
20465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const UChar* as = a->characters16();
20485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i != length; ++i) {
20495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar bc = b[i];
20505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!bc)
20515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
20525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        UChar ac = as[i];
20535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ored |= ac;
20545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        equal = equal && (toASCIILower(ac) == toASCIILower(bc));
20555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
20565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Do a slower implementation for cases that include non-ASCII characters.
20585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (ored & ~0x7F) {
20595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        equal = true;
20605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0; i != length; ++i) {
20615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            equal = equal && (foldCase(as[i]) == foldCase(b[i]));
20625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
20635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
20645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return equal && !b[length];
20665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
20675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2068926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool equalIgnoringCaseNonNull(const StringImpl* a, const StringImpl* b)
20695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2070926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(a && b);
2071926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (a == b)
20725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
2073926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2074926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    unsigned length = a->length();
2075926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (length != b->length())
2076926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return false;
2077926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2078926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (a->is8Bit()) {
2079926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (b->is8Bit())
2080926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return equalIgnoringCase(a->characters8(), b->characters8(), length);
2081926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2082926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return equalIgnoringCase(b->characters16(), a->characters8(), length);
2083926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2084926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2085926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (b->is8Bit())
2086926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return equalIgnoringCase(a->characters16(), b->characters8(), length);
2087926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2088926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return equalIgnoringCase(a->characters16(), b->characters16(), length);
2089926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
2090926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2091926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool equalIgnoringNullity(StringImpl* a, StringImpl* b)
2092926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
20935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!a && b && !b->length())
20945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
20955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!b && a && !a->length())
20965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
2097926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return equal(a, b);
20985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
20995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
21005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)size_t StringImpl::sizeInBytes() const
21015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
21025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t size = length();
21037757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    if (!is8Bit())
21045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        size *= 2;
21055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return size + sizeof(*this);
21065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
21075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
21085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WTF
2109