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