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"
31bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "wtf/PartitionAlloc.h"
3293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "wtf/StdLibExtras.h"
33bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "wtf/WTF.h"
3493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "wtf/text/AtomicString.h"
3593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "wtf/text/StringBuffer.h"
3693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "wtf/text/StringHash.h"
3793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "wtf/unicode/CharacterNames.h"
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifdef STRING_STATS
4093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "wtf/DataLog.h"
4151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "wtf/HashMap.h"
4251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "wtf/HashSet.h"
43f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#include "wtf/ProcessID.h"
445267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "wtf/RefCounted.h"
4551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "wtf/ThreadingPrimitives.h"
46926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#include <unistd.h>
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace std;
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WTF {
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace Unicode;
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
55f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)COMPILE_ASSERT(sizeof(StringImpl) == 3 * sizeof(int), StringImpl_should_stay_small);
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifdef STRING_STATS
5893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
5993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)static Mutex& statsMutex()
6093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
6193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    DEFINE_STATIC_LOCAL(Mutex, mutex, ());
6293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    return mutex;
6393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
6493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
6593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)static HashSet<void*>& liveStrings()
6693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
6793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    // Notice that we can't use HashSet<StringImpl*> because then HashSet would dedup identical strings.
6893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    DEFINE_STATIC_LOCAL(HashSet<void*>, strings, ());
6993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    return strings;
7093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
7193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
7293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)void addStringForStats(StringImpl* string)
7393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
7493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    MutexLocker locker(statsMutex());
7593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    liveStrings().add(string);
7693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
7793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
7893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)void removeStringForStats(StringImpl* string)
7993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
8093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    MutexLocker locker(statsMutex());
8193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    liveStrings().remove(string);
8293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
8393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
8493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)static void fillWithSnippet(const StringImpl* string, Vector<char>& snippet)
8593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
865267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    const unsigned kMaxSnippetLength = 64;
8793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    snippet.clear();
885267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
895267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    size_t expectedLength = std::min(string->length(), kMaxSnippetLength);
905267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (expectedLength == kMaxSnippetLength)
915267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        expectedLength += 3; // For the "...".
925267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    ++expectedLength; // For the terminating '\0'.
935267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    snippet.reserveCapacity(expectedLength);
945267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
9593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    size_t i;
965267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    for (i = 0; i < string->length() && i < kMaxSnippetLength; ++i) {
9793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        UChar c = (*string)[i];
9893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (isASCIIPrintable(c))
9993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            snippet.append(c);
1005267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        else
1015267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            snippet.append('?');
10293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
10393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (i < string->length()) {
10493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        snippet.append('.');
10593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        snippet.append('.');
10693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        snippet.append('.');
10793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
10893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    snippet.append('\0');
10993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
11093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
1115267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)static bool isUnnecessarilyWide(const StringImpl* string)
1125267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
1135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (string->is8Bit())
1145267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return false;
1155267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    UChar c = 0;
1165267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    for (unsigned i = 0; i < string->length(); ++i)
1175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        c |= (*string)[i] >> 8;
1185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return !c;
1195267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
1205267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
1215267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)class PerStringStats : public RefCounted<PerStringStats> {
1225267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)public:
1235267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    static PassRefPtr<PerStringStats> create()
12493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    {
1255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return adoptRef(new PerStringStats);
12693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
12793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
12893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    void add(const StringImpl* string)
12993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    {
13093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        ++m_numberOfCopies;
13193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (!m_length) {
13293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            m_length = string->length();
13393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            fillWithSnippet(string, m_snippet);
13493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        }
13593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (string->isAtomic())
13693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            ++m_numberOfAtomicCopies;
1375267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        if (isUnnecessarilyWide(string))
1385267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            m_unnecessarilyWide = true;
13993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
14093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
1415267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    size_t totalCharacters() const
14293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    {
1435267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return m_numberOfCopies * m_length;
14493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
14593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
14693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    void print()
14793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    {
1485267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        const char* status = "ok";
1497757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        if (m_unnecessarilyWide)
1505267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            status = "16";
1515267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        dataLogF("%8u copies (%s) of length %8u %s\n", m_numberOfCopies, status, m_length, m_snippet.data());
15293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
15393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
1545267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    bool m_unnecessarilyWide;
15593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    unsigned m_numberOfCopies;
15693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    unsigned m_length;
15793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    unsigned m_numberOfAtomicCopies;
15893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    Vector<char> m_snippet;
1595267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
1605267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)private:
1615267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    PerStringStats()
1627757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        : m_unnecessarilyWide(false)
1635267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        , m_numberOfCopies(0)
1645267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        , m_length(0)
1655267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        , m_numberOfAtomicCopies(0)
1665267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    {
1675267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    }
16893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)};
16993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
1705267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)bool operator<(const RefPtr<PerStringStats>& a, const RefPtr<PerStringStats>& b)
17193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
1725267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (a->m_unnecessarilyWide != b->m_unnecessarilyWide)
1735267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return !a->m_unnecessarilyWide && b->m_unnecessarilyWide;
1745267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (a->totalCharacters() != b->totalCharacters())
1755267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return a->totalCharacters() < b->totalCharacters();
1765267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (a->m_numberOfCopies != b->m_numberOfCopies)
1775267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return a->m_numberOfCopies < b->m_numberOfCopies;
1785267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (a->m_length != b->m_length)
1795267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return a->m_length < b->m_length;
1805267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return a->m_numberOfAtomicCopies < b->m_numberOfAtomicCopies;
18193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
18293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
18393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)static void printLiveStringStats(void*)
18493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
18593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    MutexLocker locker(statsMutex());
18693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    HashSet<void*>& strings = liveStrings();
18793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
1885267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    HashMap<StringImpl*, RefPtr<PerStringStats> > stats;
18993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    for (HashSet<void*>::iterator iter = strings.begin(); iter != strings.end(); ++iter) {
19093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        StringImpl* string = static_cast<StringImpl*>(*iter);
1915267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        HashMap<StringImpl*, RefPtr<PerStringStats> >::iterator entry = stats.find(string);
1925267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        RefPtr<PerStringStats> value = entry == stats.end() ? RefPtr<PerStringStats>(PerStringStats::create()) : entry->value;
1935267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        value->add(string);
1945267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        stats.set(string, value.release());
19593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
19693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
1975267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    Vector<RefPtr<PerStringStats> > all;
1985267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    for (HashMap<StringImpl*, RefPtr<PerStringStats> >::iterator iter = stats.begin(); iter != stats.end(); ++iter)
19993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        all.append(iter->value);
2005267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
20193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    std::sort(all.begin(), all.end());
20293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    std::reverse(all.begin(), all.end());
20393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    for (size_t i = 0; i < 20 && i < all.size(); ++i)
2045267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        all[i]->print();
20593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
20693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)StringStats StringImpl::m_stringStats;
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)unsigned StringStats::s_stringRemovesTillPrintStats = StringStats::s_printStringStatsFrequency;
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void StringStats::removeString(StringImpl* string)
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned length = string->length();
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    --m_totalNumberStrings;
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (string->is8Bit()) {
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        --m_number8BitStrings;
2187757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        m_total8BitData -= length;
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        --m_number16BitStrings;
2217757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        m_total16BitData -= length;
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!--s_stringRemovesTillPrintStats) {
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        s_stringRemovesTillPrintStats = s_printStringStatsFrequency;
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        printStats();
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void StringStats::printStats()
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
23253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    dataLogF("String stats for process id %d:\n", getCurrentProcessID());
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned long long totalNumberCharacters = m_total8BitData + m_total16BitData;
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double percent8Bit = m_totalNumberStrings ? ((double)m_number8BitStrings * 100) / (double)m_totalNumberStrings : 0.0;
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double average8bitLength = m_number8BitStrings ? (double)m_total8BitData / (double)m_number8BitStrings : 0.0;
237926b001d589ce2f10facb93dd4b87578ea35a855Torne (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);
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double percent16Bit = m_totalNumberStrings ? ((double)m_number16BitStrings * 100) / (double)m_totalNumberStrings : 0.0;
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double average16bitLength = m_number16BitStrings ? (double)m_total16BitData / (double)m_number16BitStrings : 0.0;
241926b001d589ce2f10facb93dd4b87578ea35a855Torne (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);
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double averageLength = m_totalNumberStrings ? (double)totalNumberCharacters / (double)m_totalNumberStrings : 0.0;
2447757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    unsigned long long totalDataBytes = m_total8BitData + m_total16BitData * 2;
245926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    dataLogF("%8u Total                 %12llu chars  %12llu bytes  avg length %6.1f\n", m_totalNumberStrings, totalNumberCharacters, totalDataBytes, averageLength);
2467757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    unsigned long long totalSavedBytes = m_total8BitData;
247926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    double percentSavings = totalSavedBytes ? ((double)totalSavedBytes * 100) / (double)(totalDataBytes + totalSavedBytes) : 0.0;
248926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    dataLogF("         Total savings %12llu bytes (%5.2f%%)\n", totalSavedBytes, percentSavings);
24993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
2507757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    unsigned totalOverhead = m_totalNumberStrings * sizeof(StringImpl);
2517757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    double overheadPercent = (double)totalOverhead / (double)totalDataBytes * 100;
2527757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    dataLogF("         StringImpl overheader: %8u (%5.2f%%)\n", totalOverhead, overheadPercent);
2537757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
25493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    callOnMainThread(printLiveStringStats, 0);
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
258bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)void* StringImpl::operator new(size_t size)
259bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles){
260bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    ASSERT(size == sizeof(StringImpl));
261bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return partitionAllocGeneric(Partitions::getBufferPartition(), size);
262bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)}
263bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
264bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)void StringImpl::operator delete(void* ptr)
265bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles){
266bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    partitionFreeGeneric(Partitions::getBufferPartition(), ptr);
267bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)}
268bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
2698abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)inline StringImpl::~StringImpl()
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!isStatic());
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    STRING_STATS_REMOVE_STRING(this);
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isAtomic())
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        AtomicString::remove(this);
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2798abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)void StringImpl::destroyIfNotStatic()
2808abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles){
2818abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    if (!isStatic())
2828abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        delete this;
2838abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)}
2848abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, LChar*& data)
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!length) {
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        data = 0;
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return empty();
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Allocate a single buffer large enough to contain the StringImpl
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // struct as well as the data which it contains. This removes one
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // heap allocation from this call.
29553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(length <= ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(LChar)));
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t size = sizeof(StringImpl) + length * sizeof(LChar);
297bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    StringImpl* string = static_cast<StringImpl*>(partitionAllocGeneric(Partitions::getBufferPartition(), size));
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    data = reinterpret_cast<LChar*>(string + 1);
300bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return adoptRef(new (string) StringImpl(length, Force8BitConstructor));
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, UChar*& data)
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!length) {
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        data = 0;
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return empty();
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Allocate a single buffer large enough to contain the StringImpl
311591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // struct as well as the data which it contains. This removes one
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // heap allocation from this call.
31353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(length <= ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(UChar)));
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t size = sizeof(StringImpl) + length * sizeof(UChar);
315bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    StringImpl* string = static_cast<StringImpl*>(partitionAllocGeneric(Partitions::getBufferPartition(), size));
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)
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::reallocate(PassRefPtr<StringImpl> originalString, unsigned length, LChar*& data)
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(originalString->is8Bit());
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(originalString->hasOneRef());
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!length) {
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        data = 0;
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return empty();
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
331bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    // Same as createUninitialized() except here we use realloc.
33253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(length <= ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(LChar)));
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t size = sizeof(StringImpl) + length * sizeof(LChar);
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    originalString->~StringImpl();
335bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    StringImpl* string = static_cast<StringImpl*>(partitionReallocGeneric(Partitions::getBufferPartition(), originalString.leakRef(), size));
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    data = reinterpret_cast<LChar*>(string + 1);
338bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return adoptRef(new (string) StringImpl(length, Force8BitConstructor));
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::reallocate(PassRefPtr<StringImpl> originalString, unsigned length, UChar*& data)
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!originalString->is8Bit());
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(originalString->hasOneRef());
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!length) {
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        data = 0;
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return empty();
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
351bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    // Same as createUninitialized() except here we use realloc.
35253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(length <= ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(UChar)));
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t size = sizeof(StringImpl) + length * sizeof(UChar);
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    originalString->~StringImpl();
355bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    StringImpl* string = static_cast<StringImpl*>(partitionReallocGeneric(Partitions::getBufferPartition(), originalString.leakRef(), size));
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    data = reinterpret_cast<UChar*>(string + 1);
358bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return adoptRef(new (string) StringImpl(length));
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
361e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)static StaticStringsTable& staticStrings()
3621e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles){
363e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    DEFINE_STATIC_LOCAL(StaticStringsTable, staticStrings, ());
3641e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    return staticStrings;
3651e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)}
3661e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
3671e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#ifndef NDEBUG
3681e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)static bool s_allowCreationOfStaticStrings = true;
3691e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#endif
3701e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
371e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)const StaticStringsTable& StringImpl::allStaticStrings()
3721e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles){
3731e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    return staticStrings();
3741e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)}
3751e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
3761e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)void StringImpl::freezeStaticStrings()
3771e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles){
3781e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    ASSERT(isMainThread());
3791e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
3801e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#ifndef NDEBUG
3811e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    s_allowCreationOfStaticStrings = false;
3821e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#endif
3831e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)}
3841e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
385e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)unsigned StringImpl::m_highestStaticStringLength = 0;
386e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)
387f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)StringImpl* StringImpl::createStatic(const char* string, unsigned length, unsigned hash)
388f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles){
3891e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    ASSERT(s_allowCreationOfStaticStrings);
390f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    ASSERT(string);
391f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    ASSERT(length);
392f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
393e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    StaticStringsTable::const_iterator it = staticStrings().find(hash);
394e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    if (it != staticStrings().end()) {
395e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)        ASSERT(!memcmp(string, it->value + 1, length * sizeof(LChar)));
396e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)        return it->value;
397e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    }
398e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)
399f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    // Allocate a single buffer large enough to contain the StringImpl
400f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    // struct as well as the data which it contains. This removes one
401f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    // heap allocation from this call.
402f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    RELEASE_ASSERT(length <= ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(LChar)));
403f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    size_t size = sizeof(StringImpl) + length * sizeof(LChar);
404e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)
4058abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    WTF_ANNOTATE_SCOPED_MEMORY_LEAK;
406bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    StringImpl* impl = static_cast<StringImpl*>(partitionAllocGeneric(Partitions::getBufferPartition(), size));
407f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
408f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    LChar* data = reinterpret_cast<LChar*>(impl + 1);
409bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    impl = new (impl) StringImpl(length, hash, StaticString);
410f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    memcpy(data, string, length * sizeof(LChar));
411f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#ifndef NDEBUG
412f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    impl->assertHashIsCorrect();
413f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#endif
4141e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
4151e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    ASSERT(isMainThread());
416e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    m_highestStaticStringLength = std::max(m_highestStaticStringLength, length);
417e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    staticStrings().add(hash, impl);
418f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    WTF_ANNOTATE_BENIGN_RACE(impl,
419f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        "Benign race on the reference counter of a static string created by StringImpl::createStatic");
4201e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
421f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    return impl;
422f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)}
423f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::create(const UChar* characters, unsigned length)
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!characters || !length)
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return empty();
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar* data;
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> string = createUninitialized(length, data);
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    memcpy(data, characters, length * sizeof(UChar));
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return string.release();
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::create(const LChar* characters, unsigned length)
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!characters || !length)
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return empty();
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LChar* data;
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> string = createUninitialized(length, data);
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    memcpy(data, characters, length * sizeof(LChar));
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return string.release();
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::create8BitIfPossible(const UChar* characters, unsigned length)
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!characters || !length)
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return empty();
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LChar* data;
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> string = createUninitialized(length, data);
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < length; ++i) {
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (characters[i] & 0xff00)
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return create(characters, length);
4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        data[i] = static_cast<LChar>(characters[i]);
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return string.release();
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::create(const LChar* string)
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!string)
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return empty();
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t length = strlen(reinterpret_cast<const char*>(string));
46853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(length <= numeric_limits<unsigned>::max());
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return create(string, length);
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool StringImpl::containsOnlyWhitespace()
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: The definition of whitespace here includes a number of characters
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // that are not whitespace from the point of view of RenderText; I wonder if
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // that's a problem in practice.
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
478926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (unsigned i = 0; i < m_length; ++i) {
479f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            UChar c = characters8()[i];
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!isASCIISpace(c))
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
487926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (unsigned i = 0; i < m_length; ++i) {
488f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        UChar c = characters16()[i];
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!isASCIISpace(c))
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::substring(unsigned start, unsigned length)
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (start >= m_length)
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return empty();
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned maxLength = m_length - start;
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (length >= maxLength) {
5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!start)
5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return this;
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        length = maxLength;
5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
506f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        return create(characters8() + start, length);
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
508f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    return create(characters16() + start, length);
5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)UChar32 StringImpl::characterStartingAt(unsigned i)
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
514f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        return characters8()[i];
515f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    if (U16_IS_SINGLE(characters16()[i]))
516f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        return characters16()[i];
517f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    if (i + 1 < m_length && U16_IS_LEAD(characters16()[i]) && U16_IS_TRAIL(characters16()[i + 1]))
518f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        return U16_GET_SUPPLEMENTARY(characters16()[i], characters16()[i + 1]);
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::lower()
5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Note: This is a hot function in the Dromaeo benchmark, specifically the
5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // no-op code path up through the first 'return' statement.
526591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // First scan the string for uppercase and non-ASCII characters:
5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool noUpper = true;
5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar ored = 0;
5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
531f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        const LChar* end = characters8() + m_length;
532f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        for (const LChar* chp = characters8(); chp != end; ++chp) {
5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (UNLIKELY(isASCIIUpper(*chp)))
5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                noUpper = false;
5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ored |= *chp;
5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Nothing to do if the string is all ASCII with no uppercase.
5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (noUpper && !(ored & ~0x7F))
5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return this;
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
54153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        RELEASE_ASSERT(m_length <= static_cast<unsigned>(numeric_limits<int32_t>::max()));
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int32_t length = m_length;
5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar* data8;
5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<StringImpl> newImpl = createUninitialized(length, data8);
5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!(ored & ~0x7F)) {
548926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            for (int32_t i = 0; i < length; ++i)
549f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)                data8[i] = toASCIILower(characters8()[i]);
5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return newImpl.release();
5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Do a slower implementation for cases that include non-ASCII Latin-1 characters.
555926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (int32_t i = 0; i < length; ++i)
556f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            data8[i] = static_cast<LChar>(Unicode::toLower(characters8()[i]));
5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
561f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    const UChar* end = characters16() + m_length;
562f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    for (const UChar* chp = characters16(); chp != end; ++chp) {
5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (UNLIKELY(isASCIIUpper(*chp)))
5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            noUpper = false;
5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ored |= *chp;
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Nothing to do if the string is all ASCII with no uppercase.
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (noUpper && !(ored & ~0x7F))
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
57153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(m_length <= static_cast<unsigned>(numeric_limits<int32_t>::max()));
5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int32_t length = m_length;
5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!(ored & ~0x7F)) {
5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        UChar* data16;
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<StringImpl> newImpl = createUninitialized(m_length, data16);
577591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
578926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (int32_t i = 0; i < length; ++i) {
579f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            UChar c = characters16()[i];
5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            data16[i] = toASCIILower(c);
5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
584591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Do a slower implementation for cases that include non-ASCII characters.
5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar* data16;
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data16);
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool error;
590f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    int32_t realLength = Unicode::toLower(data16, length, characters16(), m_length, &error);
5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!error && realLength == length)
5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newImpl = createUninitialized(realLength, data16);
595f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    Unicode::toLower(data16, realLength, characters16(), m_length, &error);
5965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (error)
5975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newImpl.release();
5995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::upper()
6025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // This function could be optimized for no-op cases the way lower() is,
6045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // but in empirical testing, few actual calls to upper() are no-ops, so
6055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // it wouldn't be worth the extra time for pre-scanning.
6065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
60753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(m_length <= static_cast<unsigned>(numeric_limits<int32_t>::max()));
6085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int32_t length = m_length;
6095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
6115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar* data8;
6125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<StringImpl> newImpl = createUninitialized(m_length, data8);
613591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
6145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Do a faster loop for the case where all the characters are ASCII.
6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar ored = 0;
616926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (int i = 0; i < length; ++i) {
617f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            LChar c = characters8()[i];
6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ored |= c;
6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            data8[i] = toASCIIUpper(c);
6205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!(ored & ~0x7F))
6225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return newImpl.release();
6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Do a slower implementation for cases that include non-ASCII Latin-1 characters.
6255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int numberSharpSCharacters = 0;
6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // There are two special cases.
6285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        //  1. latin-1 characters when converted to upper case are 16 bit characters.
6295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        //  2. Lower case sharp-S converts to "SS" (two characters)
630926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (int32_t i = 0; i < length; ++i) {
631f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            LChar c = characters8()[i];
6325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (UNLIKELY(c == smallLetterSharpS))
633926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                ++numberSharpSCharacters;
6345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            UChar upper = Unicode::toUpper(c);
6355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (UNLIKELY(upper > 0xff)) {
6365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // Since this upper-cased character does not fit in an 8-bit string, we need to take the 16-bit path.
6375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                goto upconvert;
6385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
6395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            data8[i] = static_cast<LChar>(upper);
6405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
6415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!numberSharpSCharacters)
6435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return newImpl.release();
6445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // We have numberSSCharacters sharp-s characters, but none of the other special characters.
6465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        newImpl = createUninitialized(m_length + numberSharpSCharacters, data8);
6475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar* dest = data8;
6495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
650926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (int32_t i = 0; i < length; ++i) {
651f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            LChar c = characters8()[i];
6525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (c == smallLetterSharpS) {
6535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                *dest++ = 'S';
6545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                *dest++ = 'S';
6555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            } else
6565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                *dest++ = static_cast<LChar>(Unicode::toUpper(c));
6575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
6585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
6605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)upconvert:
6631e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    RefPtr<StringImpl> upconverted = upconvertedString();
6641e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    const UChar* source16 = upconverted->characters16();
6655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar* data16;
6675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data16);
668591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
6695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Do a faster loop for the case where all the characters are ASCII.
6705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar ored = 0;
671926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (int i = 0; i < length; ++i) {
6725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        UChar c = source16[i];
6735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ored |= c;
6745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        data16[i] = toASCIIUpper(c);
6755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!(ored & ~0x7F))
6775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
6785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Do a slower implementation for cases that include non-ASCII characters.
6805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool error;
6815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int32_t realLength = Unicode::toUpper(data16, length, source16, m_length, &error);
6825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!error && realLength == length)
6835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl;
6845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newImpl = createUninitialized(realLength, data16);
6855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Unicode::toUpper(data16, realLength, source16, m_length, &error);
6865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (error)
6875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
6885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newImpl.release();
6895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6911e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)PassRefPtr<StringImpl> StringImpl::lower(const AtomicString& localeIdentifier)
6925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6931e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // Use the more-optimized code path most of the time.
6941e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // Note the assumption here that the only locale-specific lowercasing is
6951e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // in the "tr" and "az" locales.
6961e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // FIXME: Could possibly optimize further by looking for the specific sequences
6971e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // that have locale-specific lowercasing. There are only three of them.
6981e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    if (!(localeIdentifier == "tr" || localeIdentifier == "az"))
6991e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        return lower();
7001e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
7011e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    if (m_length > static_cast<unsigned>(numeric_limits<int32_t>::max()))
7021e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        CRASH();
7031e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    int length = m_length;
7045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7051e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // Below, we pass in the hardcoded locale "tr". Passing that is more efficient than
7061e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // allocating memory just to turn localeIdentifier into a C string, and there is no
7071e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // difference between the uppercasing for "tr" and "az" locales.
7081e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    RefPtr<StringImpl> upconverted = upconvertedString();
7091e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    const UChar* source16 = upconverted->characters16();
7101e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    UChar* data16;
7111e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    RefPtr<StringImpl> newString = createUninitialized(length, data16);
7121e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    do {
7131e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        UErrorCode status = U_ZERO_ERROR;
7141e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        int realLength = u_strToLower(data16, length, source16, length, "tr", &status);
7151e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        if (U_SUCCESS(status)) {
7161e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            newString->truncateAssumingIsolated(realLength);
7171e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            return newString.release();
7181e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        }
7191e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        if (status != U_BUFFER_OVERFLOW_ERROR)
7201e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            return this;
7211e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        // Expand the buffer.
7221e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        newString = createUninitialized(realLength, data16);
7231e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    } while (true);
7241e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)}
7251e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
7261e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)PassRefPtr<StringImpl> StringImpl::upper(const AtomicString& localeIdentifier)
7271e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles){
7281e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // Use the more-optimized code path most of the time.
7291e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // Note the assumption here that the only locale-specific uppercasing is of the
7301e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // letter "i" in the "tr" and "az" locales.
7311e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    if (!(localeIdentifier == "tr" || localeIdentifier == "az") || find('i') == kNotFound)
7321e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        return upper();
7331e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
7341e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    if (m_length > static_cast<unsigned>(numeric_limits<int32_t>::max()))
7351e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        CRASH();
7361e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    int length = m_length;
7371e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
7381e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // Below, we pass in the hardcoded locale "tr". Passing that is more efficient than
7391e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // allocating memory just to turn localeIdentifier into a C string, and there is no
7401e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // difference between the uppercasing for "tr" and "az" locales.
7411e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    RefPtr<StringImpl> upconverted = upconvertedString();
7421e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    const UChar* source16 = upconverted->characters16();
7431e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    UChar* data16;
7441e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    RefPtr<StringImpl> newString = createUninitialized(length, data16);
7451e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    do {
7461e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        UErrorCode status = U_ZERO_ERROR;
7471e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        int realLength = u_strToUpper(data16, length, source16, length, "tr", &status);
7481e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        if (U_SUCCESS(status)) {
7491e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            newString->truncateAssumingIsolated(realLength);
7501e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            return newString.release();
7511e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        }
7521e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        if (status != U_BUFFER_OVERFLOW_ERROR)
7531e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            return this;
7541e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        // Expand the buffer.
7551e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        newString = createUninitialized(realLength, data16);
7561e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    } while (true);
7571e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)}
7581e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
7591e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)PassRefPtr<StringImpl> StringImpl::fill(UChar character)
7601e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles){
7615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!(character & ~0x7F)) {
7625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar* data;
7635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
7645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0; i < m_length; ++i)
7655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            data[i] = character;
7665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
7675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
7685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar* data;
7695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
7705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i < m_length; ++i)
7715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        data[i] = character;
7725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newImpl.release();
7735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::foldCase()
7765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
77753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(m_length <= static_cast<unsigned>(numeric_limits<int32_t>::max()));
7785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int32_t length = m_length;
7795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
7815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Do a faster loop for the case where all the characters are ASCII.
7825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar* data;
7835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr <StringImpl>newImpl = createUninitialized(m_length, data);
7845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar ored = 0;
7855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
786926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (int32_t i = 0; i < length; ++i) {
787f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            LChar c = characters8()[i];
7885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            data[i] = toASCIILower(c);
7895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ored |= c;
7905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
7915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!(ored & ~0x7F))
7935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return newImpl.release();
7945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Do a slower implementation for cases that include non-ASCII Latin-1 characters.
796926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (int32_t i = 0; i < length; ++i)
797f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            data[i] = static_cast<LChar>(Unicode::toLower(characters8()[i]));
7985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
8005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Do a faster loop for the case where all the characters are ASCII.
8035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar* data;
8045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
8055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar ored = 0;
806926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (int32_t i = 0; i < length; ++i) {
807f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        UChar c = characters16()[i];
8085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ored |= c;
8095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        data[i] = toASCIILower(c);
8105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!(ored & ~0x7F))
8125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
8135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Do a slower implementation for cases that include non-ASCII characters.
8155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool error;
816f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    int32_t realLength = Unicode::foldCase(data, length, characters16(), m_length, &error);
8175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!error && realLength == length)
8185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
8195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newImpl = createUninitialized(realLength, data);
820f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    Unicode::foldCase(data, realLength, characters16(), m_length, &error);
8215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (error)
8225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
8235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newImpl.release();
8245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template <class UCharPredicate>
8275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline PassRefPtr<StringImpl> StringImpl::stripMatchedCharacters(UCharPredicate predicate)
8285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_length)
8305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return empty();
8315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned start = 0;
8335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned end = m_length - 1;
834591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
8355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // skip white space from start
836f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    while (start <= end && predicate(is8Bit() ? characters8()[start] : characters16()[start]))
837926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ++start;
838591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
8395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // only white space
840591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (start > end)
8415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return empty();
8425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // skip white space from end
844f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    while (end && predicate(is8Bit() ? characters8()[end] : characters16()[end]))
845926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        --end;
8465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!start && end == m_length - 1)
8485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
8495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
850f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        return create(characters8() + start, end + 1 - start);
851f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    return create(characters16() + start, end + 1 - start);
8525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class UCharPredicate {
8555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
8565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    inline UCharPredicate(CharacterMatchFunctionPtr function): m_function(function) { }
8575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    inline bool operator()(UChar ch) const
8595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return m_function(ch);
8615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private:
8645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const CharacterMatchFunctionPtr m_function;
8655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
8665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class SpaceOrNewlinePredicate {
8685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
8695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    inline bool operator()(UChar ch) const
8705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return isSpaceOrNewline(ch);
8725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
8745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::stripWhiteSpace()
8765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return stripMatchedCharacters(SpaceOrNewlinePredicate());
8785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::stripWhiteSpace(IsWhiteSpaceFunctionPtr isWhiteSpace)
8815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return stripMatchedCharacters(UCharPredicate(isWhiteSpace));
8835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template <typename CharType>
8865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ALWAYS_INLINE PassRefPtr<StringImpl> StringImpl::removeCharacters(const CharType* characters, CharacterMatchFunctionPtr findMatch)
8875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const CharType* from = characters;
8895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const CharType* fromend = from + m_length;
890591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
8915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Assume the common case will not remove any characters
8925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (from != fromend && !findMatch(*from))
893926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ++from;
8945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (from == fromend)
8955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
896591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
8975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StringBuffer<CharType> data(m_length);
8985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CharType* to = data.characters();
8995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned outc = from - characters;
900591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
9015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (outc)
9025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        memcpy(to, characters, outc * sizeof(CharType));
9035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (true) {
9055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (from != fromend && findMatch(*from))
906926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            ++from;
9075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (from != fromend && !findMatch(*from))
9085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            to[outc++] = *from++;
9095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (from == fromend)
9105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
9115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
9125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    data.shrink(outc);
9145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
91583750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch    return data.release();
9165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::removeCharacters(CharacterMatchFunctionPtr findMatch)
9195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
9215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return removeCharacters(characters8(), findMatch);
9225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return removeCharacters(characters16(), findMatch);
9235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template <typename CharType, class UCharPredicate>
92619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)inline PassRefPtr<StringImpl> StringImpl::simplifyMatchedCharactersToSpace(UCharPredicate predicate, StripBehavior stripBehavior)
9275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StringBuffer<CharType> data(m_length);
9295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const CharType* from = getCharacters<CharType>();
9315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const CharType* fromend = from + m_length;
9325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int outc = 0;
9335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool changedToSpace = false;
934591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
9355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CharType* to = data.characters();
936591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
93719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)    if (stripBehavior == StripExtraWhiteSpace) {
93819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)        while (true) {
93919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)            while (from != fromend && predicate(*from)) {
94019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)                if (*from != ' ')
94119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)                    changedToSpace = true;
94219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)                ++from;
94319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)            }
94419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)            while (from != fromend && !predicate(*from))
94519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)                to[outc++] = *from++;
94619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)            if (from != fromend)
94719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)                to[outc++] = ' ';
94819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)            else
94919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)                break;
9505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
951591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
95219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)        if (outc > 0 && to[outc - 1] == ' ')
95319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)            --outc;
95419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)    } else {
95519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)        for (; from != fromend; ++from) {
95619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)            if (predicate(*from)) {
95719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)                if (*from != ' ')
95819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)                    changedToSpace = true;
95919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)                to[outc++] = ' ';
96019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)            } else {
96119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)                to[outc++] = *from;
96219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)            }
96319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)        }
96419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)    }
965591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
9665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (static_cast<unsigned>(outc) == m_length && !changedToSpace)
9675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
968591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
9695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    data.shrink(outc);
970591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
97183750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch    return data.release();
9725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
97419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)PassRefPtr<StringImpl> StringImpl::simplifyWhiteSpace(StripBehavior stripBehavior)
9755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
97719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)        return StringImpl::simplifyMatchedCharactersToSpace<LChar>(SpaceOrNewlinePredicate(), stripBehavior);
97819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)    return StringImpl::simplifyMatchedCharactersToSpace<UChar>(SpaceOrNewlinePredicate(), stripBehavior);
9795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
98119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)PassRefPtr<StringImpl> StringImpl::simplifyWhiteSpace(IsWhiteSpaceFunctionPtr isWhiteSpace, StripBehavior stripBehavior)
9825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
98419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)        return StringImpl::simplifyMatchedCharactersToSpace<LChar>(UCharPredicate(isWhiteSpace), stripBehavior);
98519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)    return StringImpl::simplifyMatchedCharactersToSpace<UChar>(UCharPredicate(isWhiteSpace), stripBehavior);
9865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)int StringImpl::toIntStrict(bool* ok, int base)
9895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
9915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToIntStrict(characters8(), m_length, ok, base);
9925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToIntStrict(characters16(), m_length, ok, base);
9935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)unsigned StringImpl::toUIntStrict(bool* ok, int base)
9965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
9985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToUIntStrict(characters8(), m_length, ok, base);
9995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToUIntStrict(characters16(), m_length, ok, base);
10005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)int64_t StringImpl::toInt64Strict(bool* ok, int base)
10035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToInt64Strict(characters8(), m_length, ok, base);
10065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToInt64Strict(characters16(), m_length, ok, base);
10075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)uint64_t StringImpl::toUInt64Strict(bool* ok, int base)
10105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToUInt64Strict(characters8(), m_length, ok, base);
10135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToUInt64Strict(characters16(), m_length, ok, base);
10145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)intptr_t StringImpl::toIntPtrStrict(bool* ok, int base)
10175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToIntPtrStrict(characters8(), m_length, ok, base);
10205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToIntPtrStrict(characters16(), m_length, ok, base);
10215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)int StringImpl::toInt(bool* ok)
10245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToInt(characters8(), m_length, ok);
10275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToInt(characters16(), m_length, ok);
10285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)unsigned StringImpl::toUInt(bool* ok)
10315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToUInt(characters8(), m_length, ok);
10345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToUInt(characters16(), m_length, ok);
10355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)int64_t StringImpl::toInt64(bool* ok)
10385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToInt64(characters8(), m_length, ok);
10415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToInt64(characters16(), m_length, ok);
10425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)uint64_t StringImpl::toUInt64(bool* ok)
10455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToUInt64(characters8(), m_length, ok);
10485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToUInt64(characters16(), m_length, ok);
10495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)intptr_t StringImpl::toIntPtr(bool* ok)
10525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToIntPtr(characters8(), m_length, ok);
10555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToIntPtr(characters16(), m_length, ok);
10565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)double StringImpl::toDouble(bool* ok)
10595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToDouble(characters8(), m_length, ok);
10625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToDouble(characters16(), m_length, ok);
10635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float StringImpl::toFloat(bool* ok)
10665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return charactersToFloat(characters8(), m_length, ok);
10695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return charactersToFloat(characters16(), m_length, ok);
10705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool equalIgnoringCase(const LChar* a, const LChar* b, unsigned length)
10735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (length--) {
10755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar bc = *b++;
10765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (foldCase(*a++) != foldCase(bc))
10775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
10785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
10795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
10805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool equalIgnoringCase(const UChar* a, const LChar* b, unsigned length)
10835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (length--) {
10855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar bc = *b++;
10865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (foldCase(*a++) != foldCase(bc))
10875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
10885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
10895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
10905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)size_t StringImpl::find(CharacterMatchFunctionPtr matchFunction, unsigned start)
10935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
10955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return WTF::find(characters8(), m_length, matchFunction, start);
10965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return WTF::find(characters16(), m_length, matchFunction, start);
10975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)size_t StringImpl::find(const LChar* matchString, unsigned index)
11005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
11015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check for null or empty string to match against
11025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchString)
110306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
11045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t matchStringLength = strlen(reinterpret_cast<const char*>(matchString));
110553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(matchStringLength <= numeric_limits<unsigned>::max());
11065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchLength = matchStringLength;
11075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchLength)
11085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return min(index, length());
11095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Optimization 1: fast case for strings of length 1.
11115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength == 1)
11125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return WTF::find(characters16(), length(), *matchString, index);
11135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check index & matchLength are in range.
11155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (index > length())
111606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
11175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned searchLength = length() - index;
11185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength > searchLength)
111906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
11205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // delta is the number of additional times to test; delta == 0 means test only once.
11215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned delta = searchLength - matchLength;
11225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11237757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    const UChar* searchCharacters = characters16() + index;
11245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Optimization 2: keep a running hash of the strings,
11265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // only call equal if the hashes match.
11275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned searchHash = 0;
11285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchHash = 0;
11295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i < matchLength; ++i) {
11305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        searchHash += searchCharacters[i];
11315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        matchHash += matchString[i];
11325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
11335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned i = 0;
11355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // keep looping until we match
11365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (searchHash != matchHash || !equal(searchCharacters + i, matchString, matchLength)) {
11375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (i == delta)
113806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)            return kNotFound;
11395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        searchHash += searchCharacters[i + matchLength];
11405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        searchHash -= searchCharacters[i];
11415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++i;
11425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
11435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return index + i;
11445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
11455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11467757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochtemplate<typename CharType>
11477757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochALWAYS_INLINE size_t findIgnoringCaseInternal(const CharType* searchCharacters, const LChar* matchString, unsigned index, unsigned searchLength, unsigned matchLength)
11487757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch{
11497757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    // delta is the number of additional times to test; delta == 0 means test only once.
11507757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    unsigned delta = searchLength - matchLength;
11517757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
11527757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    unsigned i = 0;
11537757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    while (!equalIgnoringCase(searchCharacters + i, matchString, matchLength)) {
11547757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        if (i == delta)
115506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)            return kNotFound;
11567757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        ++i;
11577757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    }
11587757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    return index + i;
11597757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch}
11607757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
11615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)size_t StringImpl::findIgnoringCase(const LChar* matchString, unsigned index)
11625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
11635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check for null or empty string to match against
11645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchString)
116506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
11665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t matchStringLength = strlen(reinterpret_cast<const char*>(matchString));
116753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(matchStringLength <= numeric_limits<unsigned>::max());
11685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchLength = matchStringLength;
11695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchLength)
11705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return min(index, length());
11715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check index & matchLength are in range.
11735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (index > length())
117406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
11755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned searchLength = length() - index;
11765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength > searchLength)
117706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
11785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11797757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    if (is8Bit())
11807757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return findIgnoringCaseInternal(characters8() + index, matchString, index, searchLength, matchLength);
11817757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    return findIgnoringCaseInternal(characters16() + index, matchString, index, searchLength, matchLength);
11825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
11835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template <typename SearchCharacterType, typename MatchCharacterType>
11857757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochALWAYS_INLINE static size_t findInternal(const SearchCharacterType* searchCharacters, const MatchCharacterType* matchCharacters, unsigned index, unsigned searchLength, unsigned matchLength)
11865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
11875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Optimization: keep a running hash of the strings,
11885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // only call equal() if the hashes match.
11895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // delta is the number of additional times to test; delta == 0 means test only once.
11915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned delta = searchLength - matchLength;
11925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned searchHash = 0;
11945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchHash = 0;
11955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i < matchLength; ++i) {
11975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        searchHash += searchCharacters[i];
11985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        matchHash += matchCharacters[i];
11995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned i = 0;
12025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // keep looping until we match
12035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (searchHash != matchHash || !equal(searchCharacters + i, matchCharacters, matchLength)) {
12045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (i == delta)
120506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)            return kNotFound;
12065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        searchHash += searchCharacters[i + matchLength];
12075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        searchHash -= searchCharacters[i];
12085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++i;
12095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1210591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return index + i;
12115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
12125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)size_t StringImpl::find(StringImpl* matchString)
12145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
12155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check for null string to match against
12165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (UNLIKELY(!matchString))
121706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
12185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchLength = matchString->length();
12195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Optimization 1: fast case for strings of length 1.
12215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength == 1) {
12225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (is8Bit()) {
12235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (matchString->is8Bit())
12245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return WTF::find(characters8(), length(), matchString->characters8()[0]);
12255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return WTF::find(characters8(), length(), matchString->characters16()[0]);
12265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
12275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (matchString->is8Bit())
12285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return WTF::find(characters16(), length(), matchString->characters8()[0]);
12295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return WTF::find(characters16(), length(), matchString->characters16()[0]);
12305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check matchLength is in range.
12335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength > length())
123406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
12355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check for empty string to match against
12375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (UNLIKELY(!matchLength))
12385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
12395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
12415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (matchString->is8Bit())
12427757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            return findInternal(characters8(), matchString->characters8(), 0, length(), matchLength);
12437757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return findInternal(characters8(), matchString->characters16(), 0, length(), matchLength);
12445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchString->is8Bit())
12477757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return findInternal(characters16(), matchString->characters8(), 0, length(), matchLength);
12485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12497757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    return findInternal(characters16(), matchString->characters16(), 0, length(), matchLength);
12505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
12515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)size_t StringImpl::find(StringImpl* matchString, unsigned index)
12535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
12545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check for null or empty string to match against
12555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (UNLIKELY(!matchString))
125606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
12575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchLength = matchString->length();
12595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Optimization 1: fast case for strings of length 1.
12615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength == 1) {
12625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (is8Bit())
12635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return WTF::find(characters8(), length(), (*matchString)[0], index);
12645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return WTF::find(characters16(), length(), (*matchString)[0], index);
12655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (UNLIKELY(!matchLength))
12685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return min(index, length());
12695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check index & matchLength are in range.
12715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (index > length())
127206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
12735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned searchLength = length() - index;
12745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength > searchLength)
127506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
12765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
12785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (matchString->is8Bit())
12797757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            return findInternal(characters8() + index, matchString->characters8(), index, searchLength, matchLength);
12807757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return findInternal(characters8() + index, matchString->characters16(), index, searchLength, matchLength);
12815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchString->is8Bit())
12847757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return findInternal(characters16() + index, matchString->characters8(), index, searchLength, matchLength);
12855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12867757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    return findInternal(characters16() + index, matchString->characters16(), index, searchLength, matchLength);
12875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
12885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template <typename SearchCharacterType, typename MatchCharacterType>
12905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ALWAYS_INLINE static size_t findIgnoringCaseInner(const SearchCharacterType* searchCharacters, const MatchCharacterType* matchCharacters, unsigned index, unsigned searchLength, unsigned matchLength)
12915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
12925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // delta is the number of additional times to test; delta == 0 means test only once.
12935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned delta = searchLength - matchLength;
12945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned i = 0;
12965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // keep looping until we match
12975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (!equalIgnoringCase(searchCharacters + i, matchCharacters, matchLength)) {
12985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (i == delta)
129906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)            return kNotFound;
13005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++i;
13015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
13025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return index + i;
13035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
13045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)size_t StringImpl::findIgnoringCase(StringImpl* matchString, unsigned index)
13065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
13075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check for null or empty string to match against
13085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchString)
130906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
13105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchLength = matchString->length();
13115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchLength)
13125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return min(index, length());
13135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check index & matchLength are in range.
13155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (index > length())
131606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
13175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned searchLength = length() - index;
13185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength > searchLength)
131906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
13205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
13225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (matchString->is8Bit())
13235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return findIgnoringCaseInner(characters8() + index, matchString->characters8(), index, searchLength, matchLength);
13245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return findIgnoringCaseInner(characters8() + index, matchString->characters16(), index, searchLength, matchLength);
13255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
13265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchString->is8Bit())
13285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return findIgnoringCaseInner(characters16() + index, matchString->characters8(), index, searchLength, matchLength);
13295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return findIgnoringCaseInner(characters16() + index, matchString->characters16(), index, searchLength, matchLength);
13315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
13325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1333926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)size_t StringImpl::findNextLineStart(unsigned index)
1334926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
1335926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (is8Bit())
1336926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return WTF::findNextLineStart(characters8(), m_length, index);
1337926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return WTF::findNextLineStart(characters16(), m_length, index);
1338926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
1339926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1340591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochsize_t StringImpl::count(LChar c) const
1341591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
1342591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    int count = 0;
1343591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (is8Bit()) {
1344591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        for (size_t i = 0; i < m_length; ++i)
1345591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            count += characters8()[i] == c;
1346591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    } else {
1347591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        for (size_t i = 0; i < m_length; ++i)
1348591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            count += characters16()[i] == c;
1349591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
1350591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return count;
1351591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
1352591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
13531e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)size_t StringImpl::reverseFind(UChar c, unsigned index)
13545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
13555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
13561e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        return WTF::reverseFind(characters8(), m_length, c, index);
13571e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    return WTF::reverseFind(characters16(), m_length, c, index);
13585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
13595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template <typename SearchCharacterType, typename MatchCharacterType>
13611e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)ALWAYS_INLINE static size_t reverseFindInner(const SearchCharacterType* searchCharacters, const MatchCharacterType* matchCharacters, unsigned index, unsigned length, unsigned matchLength)
13625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
13635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Optimization: keep a running hash of the strings,
13645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // only call equal if the hashes match.
13655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // delta is the number of additional times to test; delta == 0 means test only once.
13675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned delta = min(index, length - matchLength);
1368591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
13695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned searchHash = 0;
13705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchHash = 0;
13715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i < matchLength; ++i) {
13725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        searchHash += searchCharacters[delta + i];
13735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        matchHash += matchCharacters[i];
13745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
13755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // keep looping until we match
13775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (searchHash != matchHash || !equal(searchCharacters + delta, matchCharacters, matchLength)) {
13785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!delta)
137906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)            return kNotFound;
1380926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        --delta;
13815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        searchHash -= searchCharacters[delta + matchLength];
13825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        searchHash += searchCharacters[delta];
13835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
13841e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    return delta;
13855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
13865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13871e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)size_t StringImpl::reverseFind(StringImpl* matchString, unsigned index)
13885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
13895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check for null or empty string to match against
13905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchString)
139106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
13925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchLength = matchString->length();
13935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned ourLength = length();
13945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchLength)
13955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return min(index, ourLength);
13965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Optimization 1: fast case for strings of length 1.
13985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength == 1) {
13995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (is8Bit())
14001e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            return WTF::reverseFind(characters8(), ourLength, (*matchString)[0], index);
14011e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        return WTF::reverseFind(characters16(), ourLength, (*matchString)[0], index);
14025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
14035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check index & matchLength are in range.
14051e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    if (matchLength > ourLength)
140606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
14075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
14095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (matchString->is8Bit())
14101e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            return reverseFindInner(characters8(), matchString->characters8(), index, ourLength, matchLength);
14111e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        return reverseFindInner(characters8(), matchString->characters16(), index, ourLength, matchLength);
14125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1413591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
14145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchString->is8Bit())
14151e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        return reverseFindInner(characters16(), matchString->characters8(), index, ourLength, matchLength);
14165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14171e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    return reverseFindInner(characters16(), matchString->characters16(), index, ourLength, matchLength);
14185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
14195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template <typename SearchCharacterType, typename MatchCharacterType>
14215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ALWAYS_INLINE static size_t reverseFindIgnoringCaseInner(const SearchCharacterType* searchCharacters, const MatchCharacterType* matchCharacters, unsigned index, unsigned length, unsigned matchLength)
14225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
14235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // delta is the number of additional times to test; delta == 0 means test only once.
14245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned delta = min(index, length - matchLength);
14255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // keep looping until we match
14275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (!equalIgnoringCase(searchCharacters + delta, matchCharacters, matchLength)) {
14285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!delta)
142906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)            return kNotFound;
1430926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        --delta;
14315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
14325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return delta;
14335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
14345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)size_t StringImpl::reverseFindIgnoringCase(StringImpl* matchString, unsigned index)
14365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
14375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check for null or empty string to match against
14385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchString)
143906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
14405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchLength = matchString->length();
14415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned ourLength = length();
14425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchLength)
14435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return min(index, ourLength);
14445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check index & matchLength are in range.
14465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength > ourLength)
144706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return kNotFound;
14485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
14505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (matchString->is8Bit())
14515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return reverseFindIgnoringCaseInner(characters8(), matchString->characters8(), index, ourLength, matchLength);
14525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return reverseFindIgnoringCaseInner(characters8(), matchString->characters16(), index, ourLength, matchLength);
14535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
14545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchString->is8Bit())
14565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return reverseFindIgnoringCaseInner(characters16(), matchString->characters8(), index, ourLength, matchLength);
14575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return reverseFindIgnoringCaseInner(characters16(), matchString->characters16(), index, ourLength, matchLength);
14595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
14605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ALWAYS_INLINE static bool equalInner(const StringImpl* stringImpl, unsigned startOffset, const char* matchString, unsigned matchLength, bool caseSensitive)
14625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
14635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(stringImpl);
14645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(matchLength <= stringImpl->length());
14655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(startOffset + matchLength <= stringImpl->length());
14665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (caseSensitive) {
14685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (stringImpl->is8Bit())
14695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return equal(stringImpl->characters8() + startOffset, reinterpret_cast<const LChar*>(matchString), matchLength);
14705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return equal(stringImpl->characters16() + startOffset, reinterpret_cast<const LChar*>(matchString), matchLength);
14715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
14725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (stringImpl->is8Bit())
14735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return equalIgnoringCase(stringImpl->characters8() + startOffset, reinterpret_cast<const LChar*>(matchString), matchLength);
14745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return equalIgnoringCase(stringImpl->characters16() + startOffset, reinterpret_cast<const LChar*>(matchString), matchLength);
14755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
14765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool StringImpl::startsWith(UChar character) const
14785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
14795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_length && (*this)[0] == character;
14805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
14815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool StringImpl::startsWith(const char* matchString, unsigned matchLength, bool caseSensitive) const
14835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
14845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(matchLength);
14855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength > length())
14865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
14875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return equalInner(this, 0, matchString, matchLength, caseSensitive);
14885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
14895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool StringImpl::endsWith(StringImpl* matchString, bool caseSensitive)
14915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
14925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(matchString);
14935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_length >= matchString->m_length) {
14945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unsigned start = m_length - matchString->m_length;
14955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return (caseSensitive ? find(matchString, start) : findIgnoringCase(matchString, start)) == start;
14965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
14975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
14985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
14995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool StringImpl::endsWith(UChar character) const
15015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
15025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_length && (*this)[m_length - 1] == character;
15035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
15045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool StringImpl::endsWith(const char* matchString, unsigned matchLength, bool caseSensitive) const
15065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
15075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(matchLength);
15085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (matchLength > length())
15095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
15105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned startOffset = length() - matchLength;
15115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return equalInner(this, startOffset, matchString, matchLength, caseSensitive);
15125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
15135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::replace(UChar oldC, UChar newC)
15155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
15165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (oldC == newC)
15175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
15185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned i;
15195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (i = 0; i != m_length; ++i) {
1520f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        UChar c = is8Bit() ? characters8()[i] : characters16()[i];
15215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (c == oldC)
15225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
15235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
15245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (i == m_length)
15255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
15265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
15285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (oldC > 0xff)
15295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Looking for a 16 bit char in an 8 bit string, we're done.
15305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return this;
15315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (newC <= 0xff) {
15335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            LChar* data;
15345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            LChar oldChar = static_cast<LChar>(oldC);
15355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            LChar newChar = static_cast<LChar>(newC);
15365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
15385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for (i = 0; i != m_length; ++i) {
1540f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)                LChar ch = characters8()[i];
15415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (ch == oldChar)
15425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    ch = newChar;
15435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                data[i] = ch;
15445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
15455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return newImpl.release();
15465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
15475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // There is the possibility we need to up convert from 8 to 16 bit,
15495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // create a 16 bit string for the result.
15505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        UChar* data;
15515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
15525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (i = 0; i != m_length; ++i) {
1554f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            UChar ch = characters8()[i];
15555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (ch == oldC)
15565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ch = newC;
15575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            data[i] = ch;
15585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
15595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
15615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
15625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar* data;
15645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
15655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (i = 0; i != m_length; ++i) {
1567f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        UChar ch = characters16()[i];
15685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (ch == oldC)
15695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ch = newC;
15705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        data[i] = ch;
15715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
15725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newImpl.release();
15735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
15745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::replace(unsigned position, unsigned lengthToReplace, StringImpl* str)
15765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
15775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    position = min(position, length());
15785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    lengthToReplace = min(lengthToReplace, length() - position);
15795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned lengthToInsert = str ? str->length() : 0;
15805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!lengthToReplace && !lengthToInsert)
15815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
15825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
158353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT((length() - lengthToReplace) < (numeric_limits<unsigned>::max() - lengthToInsert));
15845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit() && (!str || str->is8Bit())) {
15865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar* data;
15875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<StringImpl> newImpl =
15885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        createUninitialized(length() - lengthToReplace + lengthToInsert, data);
1589f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        memcpy(data, characters8(), position * sizeof(LChar));
15905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (str)
1591f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            memcpy(data + position, str->characters8(), lengthToInsert * sizeof(LChar));
1592f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        memcpy(data + position + lengthToInsert, characters8() + position + lengthToReplace,
15935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)               (length() - position - lengthToReplace) * sizeof(LChar));
15945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
15955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
15965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar* data;
15975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> newImpl =
15985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        createUninitialized(length() - lengthToReplace + lengthToInsert, data);
15995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit())
1600926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (unsigned i = 0; i < position; ++i)
1601f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            data[i] = characters8()[i];
16025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
1603f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        memcpy(data, characters16(), position * sizeof(UChar));
16045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (str) {
16055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (str->is8Bit())
1606926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            for (unsigned i = 0; i < lengthToInsert; ++i)
1607f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)                data[i + position] = str->characters8()[i];
16085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else
1609f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            memcpy(data + position, str->characters16(), lengthToInsert * sizeof(UChar));
16105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
16115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
1612926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (unsigned i = 0; i < length() - position - lengthToReplace; ++i)
1613f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            data[i + position + lengthToInsert] = characters8()[i + position + lengthToReplace];
16145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
16157757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        memcpy(data + position + lengthToInsert, characters16() + position + lengthToReplace,
16165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            (length() - position - lengthToReplace) * sizeof(UChar));
16175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
16185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newImpl.release();
16195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
16205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::replace(UChar pattern, StringImpl* replacement)
16225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
16235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!replacement)
16245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
16255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (replacement->is8Bit())
1627f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        return replace(pattern, replacement->characters8(), replacement->length());
16285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1629f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    return replace(pattern, replacement->characters16(), replacement->length());
16305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
16315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::replace(UChar pattern, const LChar* replacement, unsigned repStrLength)
16335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
16345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(replacement);
16355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t srcSegmentStart = 0;
16375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchCount = 0;
16385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Count the matches.
164006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    while ((srcSegmentStart = find(pattern, srcSegmentStart)) != kNotFound) {
16415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++matchCount;
16425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++srcSegmentStart;
16435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
16445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If we have 0 matches then we don't have to do any more work.
16465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchCount)
16475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
16485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
164953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(!repStrLength || matchCount <= numeric_limits<unsigned>::max() / repStrLength);
16505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned replaceSize = matchCount * repStrLength;
16525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned newSize = m_length - matchCount;
165353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(newSize < (numeric_limits<unsigned>::max() - replaceSize));
16545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newSize += replaceSize;
16565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Construct the new data.
16585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t srcSegmentEnd;
16595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned srcSegmentLength;
16605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    srcSegmentStart = 0;
16615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned dstOffset = 0;
16625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
16645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar* data;
16655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
16665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
166706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != kNotFound) {
16685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            srcSegmentLength = srcSegmentEnd - srcSegmentStart;
1669f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            memcpy(data + dstOffset, characters8() + srcSegmentStart, srcSegmentLength * sizeof(LChar));
16705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            dstOffset += srcSegmentLength;
16715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            memcpy(data + dstOffset, replacement, repStrLength * sizeof(LChar));
16725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            dstOffset += repStrLength;
16735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            srcSegmentStart = srcSegmentEnd + 1;
16745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
16755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        srcSegmentLength = m_length - srcSegmentStart;
1677f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        memcpy(data + dstOffset, characters8() + srcSegmentStart, srcSegmentLength * sizeof(LChar));
16785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(dstOffset + srcSegmentLength == newImpl->length());
16805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
16825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
16835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar* data;
16855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
16865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
168706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != kNotFound) {
16885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        srcSegmentLength = srcSegmentEnd - srcSegmentStart;
1689f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        memcpy(data + dstOffset, characters16() + srcSegmentStart, srcSegmentLength * sizeof(UChar));
16905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        dstOffset += srcSegmentLength;
16925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0; i < repStrLength; ++i)
16935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            data[i + dstOffset] = replacement[i];
16945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        dstOffset += repStrLength;
16965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        srcSegmentStart = srcSegmentEnd + 1;
16975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
16985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    srcSegmentLength = m_length - srcSegmentStart;
1700f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    memcpy(data + dstOffset, characters16() + srcSegmentStart, srcSegmentLength * sizeof(UChar));
17015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(dstOffset + srcSegmentLength == newImpl->length());
17035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newImpl.release();
17055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
17065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::replace(UChar pattern, const UChar* replacement, unsigned repStrLength)
17085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
17095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(replacement);
17105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t srcSegmentStart = 0;
17125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchCount = 0;
17135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Count the matches.
171506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    while ((srcSegmentStart = find(pattern, srcSegmentStart)) != kNotFound) {
17165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++matchCount;
17175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++srcSegmentStart;
17185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
17195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If we have 0 matches then we don't have to do any more work.
17215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchCount)
17225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
17235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
172453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(!repStrLength || matchCount <= numeric_limits<unsigned>::max() / repStrLength);
17255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned replaceSize = matchCount * repStrLength;
17275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned newSize = m_length - matchCount;
172853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(newSize < (numeric_limits<unsigned>::max() - replaceSize));
17295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newSize += replaceSize;
17315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Construct the new data.
17335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t srcSegmentEnd;
17345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned srcSegmentLength;
17355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    srcSegmentStart = 0;
17365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned dstOffset = 0;
17375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (is8Bit()) {
17395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        UChar* data;
17405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
17415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
174206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != kNotFound) {
17435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            srcSegmentLength = srcSegmentEnd - srcSegmentStart;
17445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for (unsigned i = 0; i < srcSegmentLength; ++i)
1745f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)                data[i + dstOffset] = characters8()[i + srcSegmentStart];
17465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            dstOffset += srcSegmentLength;
17485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            memcpy(data + dstOffset, replacement, repStrLength * sizeof(UChar));
17495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            dstOffset += repStrLength;
17515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            srcSegmentStart = srcSegmentEnd + 1;
17525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
17535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        srcSegmentLength = m_length - srcSegmentStart;
17555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0; i < srcSegmentLength; ++i)
1756f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            data[i + dstOffset] = characters8()[i + srcSegmentStart];
17575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(dstOffset + srcSegmentLength == newImpl->length());
17595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
17615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
17625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar* data;
17645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
17655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
176606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != kNotFound) {
17675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        srcSegmentLength = srcSegmentEnd - srcSegmentStart;
1768f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        memcpy(data + dstOffset, characters16() + srcSegmentStart, srcSegmentLength * sizeof(UChar));
17695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        dstOffset += srcSegmentLength;
17715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        memcpy(data + dstOffset, replacement, repStrLength * sizeof(UChar));
17725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        dstOffset += repStrLength;
17745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        srcSegmentStart = srcSegmentEnd + 1;
17755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
17765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    srcSegmentLength = m_length - srcSegmentStart;
1778f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    memcpy(data + dstOffset, characters16() + srcSegmentStart, srcSegmentLength * sizeof(UChar));
17795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(dstOffset + srcSegmentLength == newImpl->length());
17815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newImpl.release();
17835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
17845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> StringImpl::replace(StringImpl* pattern, StringImpl* replacement)
17865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
17875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!pattern || !replacement)
17885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
17895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned patternLength = pattern->length();
17915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!patternLength)
17925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
1793591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
17945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned repStrLength = replacement->length();
17955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t srcSegmentStart = 0;
17965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned matchCount = 0;
1797591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
17985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Count the matches.
179906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    while ((srcSegmentStart = find(pattern, srcSegmentStart)) != kNotFound) {
18005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++matchCount;
18015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        srcSegmentStart += patternLength;
18025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1803591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
18045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If we have 0 matches, we don't have to do any more work
18055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!matchCount)
18065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
1807591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
18085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned newSize = m_length - matchCount * patternLength;
180953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(!repStrLength || matchCount <= numeric_limits<unsigned>::max() / repStrLength);
18105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
181153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RELEASE_ASSERT(newSize <= (numeric_limits<unsigned>::max() - matchCount * repStrLength));
18125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newSize += matchCount * repStrLength;
18145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1815591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
18165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Construct the new data
18175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t srcSegmentEnd;
18185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned srcSegmentLength;
18195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    srcSegmentStart = 0;
18205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned dstOffset = 0;
18215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool srcIs8Bit = is8Bit();
18225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool replacementIs8Bit = replacement->is8Bit();
1823591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
18245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // There are 4 cases:
18255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // 1. This and replacement are both 8 bit.
18265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // 2. This and replacement are both 16 bit.
18275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // 3. This is 8 bit and replacement is 16 bit.
18285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // 4. This is 16 bit and replacement is 8 bit.
18295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (srcIs8Bit && replacementIs8Bit) {
18305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Case 1
18315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar* data;
18325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
183306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != kNotFound) {
18345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            srcSegmentLength = srcSegmentEnd - srcSegmentStart;
1835f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            memcpy(data + dstOffset, characters8() + srcSegmentStart, srcSegmentLength * sizeof(LChar));
18365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            dstOffset += srcSegmentLength;
1837f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            memcpy(data + dstOffset, replacement->characters8(), repStrLength * sizeof(LChar));
18385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            dstOffset += repStrLength;
18395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            srcSegmentStart = srcSegmentEnd + patternLength;
18405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
18415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        srcSegmentLength = m_length - srcSegmentStart;
1843f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        memcpy(data + dstOffset, characters8() + srcSegmentStart, srcSegmentLength * sizeof(LChar));
18445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(dstOffset + srcSegmentLength == newImpl->length());
18465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newImpl.release();
18485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
18495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar* data;
18515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
185206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != kNotFound) {
18535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        srcSegmentLength = srcSegmentEnd - srcSegmentStart;
18545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (srcIs8Bit) {
18555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Case 3.
1856926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            for (unsigned i = 0; i < srcSegmentLength; ++i)
1857f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)                data[i + dstOffset] = characters8()[i + srcSegmentStart];
18585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
18595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Case 2 & 4.
1860f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            memcpy(data + dstOffset, characters16() + srcSegmentStart, srcSegmentLength * sizeof(UChar));
18615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
18625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        dstOffset += srcSegmentLength;
18635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (replacementIs8Bit) {
18645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Cases 2 & 3.
1865926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            for (unsigned i = 0; i < repStrLength; ++i)
1866f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)                data[i + dstOffset] = replacement->characters8()[i];
18675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
18685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Case 4
1869f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            memcpy(data + dstOffset, replacement->characters16(), repStrLength * sizeof(UChar));
18705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
18715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        dstOffset += repStrLength;
18725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        srcSegmentStart = srcSegmentEnd + patternLength;
18735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
18745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    srcSegmentLength = m_length - srcSegmentStart;
18765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (srcIs8Bit) {
18775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Case 3.
1878926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (unsigned i = 0; i < srcSegmentLength; ++i)
1879f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            data[i + dstOffset] = characters8()[i + srcSegmentStart];
18805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
18815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Cases 2 & 4.
1882f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        memcpy(data + dstOffset, characters16() + srcSegmentStart, srcSegmentLength * sizeof(UChar));
18835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
18845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(dstOffset + srcSegmentLength == newImpl->length());
18865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newImpl.release();
18885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
18895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18901e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)PassRefPtr<StringImpl> StringImpl::upconvertedString()
18911e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles){
18921e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    if (is8Bit())
18931e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        return String::make16BitFrom8BitSource(characters8(), m_length).releaseImpl();
18941e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    return this;
18951e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)}
18961e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
1897926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)static inline bool stringImplContentEqual(const StringImpl* a, const StringImpl* b)
1898926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
1899926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    unsigned aLength = a->length();
1900926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    unsigned bLength = b->length();
1901926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (aLength != bLength)
1902926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return false;
1903926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1904926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (a->is8Bit()) {
1905926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (b->is8Bit())
1906926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return equal(a->characters8(), b->characters8(), aLength);
1907926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1908926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return equal(a->characters8(), b->characters16(), aLength);
1909926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
1910926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1911926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (b->is8Bit())
1912926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return equal(a->characters16(), b->characters8(), aLength);
1913926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1914926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return equal(a->characters16(), b->characters16(), aLength);
1915926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
1916926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
19175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool equal(const StringImpl* a, const StringImpl* b)
19185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1919926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (a == b)
1920926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return true;
1921926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!a || !b)
1922926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return false;
1923926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1924926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return stringImplContentEqual(a, b);
19255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
19265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1927e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochtemplate <typename CharType>
1928e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochinline bool equalInternal(const StringImpl* a, const CharType* b, unsigned length)
19295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
19305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!a)
19315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return !b;
19325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!b)
19335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
19345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1935e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (a->length() != length)
1936e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        return false;
19375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (a->is8Bit())
19385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return equal(a->characters8(), b, length);
19395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return equal(a->characters16(), b, length);
19405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
19415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1942e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochbool equal(const StringImpl* a, const LChar* b, unsigned length)
1943e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch{
1944e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    return equalInternal(a, b, length);
1945e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch}
1946e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
1947e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochbool equal(const StringImpl* a, const UChar* b, unsigned length)
1948e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch{
1949e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    return equalInternal(a, b, length);
1950e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch}
1951e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
19525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool equal(const StringImpl* a, const LChar* b)
19535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
19545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!a)
19555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return !b;
19565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!b)
19575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return !a;
19585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned length = a->length();
19605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (a->is8Bit()) {
19625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const LChar* aPtr = a->characters8();
19635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0; i != length; ++i) {
19645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            LChar bc = b[i];
19655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            LChar ac = aPtr[i];
19665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!bc)
19675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
19685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (ac != bc)
19695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
19705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
19715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return !b[length];
19735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
19745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const UChar* aPtr = a->characters16();
19765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i != length; ++i) {
19775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar bc = b[i];
19785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!bc)
19795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
19805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (aPtr[i] != bc)
19815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
19825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
19835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return !b[length];
19855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
19865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1987926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool equalNonNull(const StringImpl* a, const StringImpl* b)
1988926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
1989926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(a && b);
1990926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (a == b)
1991926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return true;
1992926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1993926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return stringImplContentEqual(a, b);
1994926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
1995926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1996926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool equalIgnoringCase(const StringImpl* a, const StringImpl* b)
19975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1998926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (a == b)
1999926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return true;
2000926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!a || !b)
2001926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return false;
2002926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
20035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return CaseFoldingHash::equal(a, b);
20045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
20055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2006926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool equalIgnoringCase(const StringImpl* a, const LChar* b)
20075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
20085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!a)
20095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return !b;
20105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!b)
20115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return !a;
20125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned length = a->length();
20145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Do a faster loop for the case where all the characters are ASCII.
20165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UChar ored = 0;
20175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool equal = true;
20185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (a->is8Bit()) {
20195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const LChar* as = a->characters8();
20205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0; i != length; ++i) {
20215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            LChar bc = b[i];
20225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!bc)
20235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
20245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            UChar ac = as[i];
20255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ored |= ac;
20265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            equal = equal && (toASCIILower(ac) == toASCIILower(bc));
20275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2028591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
20295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Do a slower implementation for cases that include non-ASCII characters.
20305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (ored & ~0x7F) {
20315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            equal = true;
20325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for (unsigned i = 0; i != length; ++i)
20335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                equal = equal && (foldCase(as[i]) == foldCase(b[i]));
20345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2035591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
2036591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return equal && !b[length];
20375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
20385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const UChar* as = a->characters16();
20405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i != length; ++i) {
20415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LChar bc = b[i];
20425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!bc)
20435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
20445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        UChar ac = as[i];
20455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ored |= ac;
20465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        equal = equal && (toASCIILower(ac) == toASCIILower(bc));
20475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
20485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Do a slower implementation for cases that include non-ASCII characters.
20505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (ored & ~0x7F) {
20515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        equal = true;
20525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0; i != length; ++i) {
20535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            equal = equal && (foldCase(as[i]) == foldCase(b[i]));
20545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
20555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
20565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return equal && !b[length];
20585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
20595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2060926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool equalIgnoringCaseNonNull(const StringImpl* a, const StringImpl* b)
20615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2062926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(a && b);
2063926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (a == b)
20645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
2065926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2066926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    unsigned length = a->length();
2067926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (length != b->length())
2068926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return false;
2069926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2070926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (a->is8Bit()) {
2071926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (b->is8Bit())
2072926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return equalIgnoringCase(a->characters8(), b->characters8(), length);
2073926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2074926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return equalIgnoringCase(b->characters16(), a->characters8(), length);
2075926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2076926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2077926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (b->is8Bit())
2078926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return equalIgnoringCase(a->characters16(), b->characters8(), length);
2079926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2080926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return equalIgnoringCase(a->characters16(), b->characters16(), length);
2081926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
2082926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2083926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool equalIgnoringNullity(StringImpl* a, StringImpl* b)
2084926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
20855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!a && b && !b->length())
20865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
20875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!b && a && !a->length())
20885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
2089926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return equal(a, b);
20905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
20915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)size_t StringImpl::sizeInBytes() const
20935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
20945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t size = length();
20957757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    if (!is8Bit())
20965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        size *= 2;
20975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return size + sizeof(*this);
20985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
20995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
21005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WTF
2101