diff options
Diffstat (limited to 'WebCore/platform/text')
22 files changed, 401 insertions, 219 deletions
diff --git a/WebCore/platform/text/AtomicString.cpp b/WebCore/platform/text/AtomicString.cpp index dc573e1..5f9abfd 100644 --- a/WebCore/platform/text/AtomicString.cpp +++ b/WebCore/platform/text/AtomicString.cpp @@ -28,35 +28,21 @@ #include "StaticConstructors.h" #include "StringHash.h" -#include <kjs/identifier.h> +#include "ThreadGlobalData.h" #include <wtf/Threading.h> #include <wtf/HashSet.h> -#if ENABLE(WORKERS) -#include <wtf/ThreadSpecific.h> -using namespace WTF; -#endif - #if USE(JSC) +#include <runtime/Identifier.h> using JSC::Identifier; using JSC::UString; #endif namespace WebCore { -#if ENABLE(WORKERS) -static ThreadSpecific<HashSet<StringImpl*> >* staticStringTable; -#else -static HashSet<StringImpl*>* staticStringTable; -#endif - -static inline HashSet<StringImpl*>* stringTable() +static inline HashSet<StringImpl*>& stringTable() { -#if ENABLE(WORKERS) - return *staticStringTable; -#else - return staticStringTable; -#endif + return threadGlobalData().atomicStringTable(); } struct CStringTranslator { @@ -99,7 +85,7 @@ PassRefPtr<StringImpl> AtomicString::add(const char* c) return 0; if (!*c) return StringImpl::empty(); - pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable()->add<const char*, CStringTranslator>(c); + pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<const char*, CStringTranslator>(c); if (!addResult.second) return *addResult.first; return adoptRef(*addResult.first); @@ -191,10 +177,11 @@ PassRefPtr<StringImpl> AtomicString::add(const UChar* s, int length) return StringImpl::empty(); UCharBuffer buf = { s, length }; - pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable()->add<UCharBuffer, UCharBufferTranslator>(buf); - if (!addResult.second) - return *addResult.first; - return adoptRef(*addResult.first); + pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<UCharBuffer, UCharBufferTranslator>(buf); + + // If the string is newly-translated, then we need to adopt it. + // The boolean in the pair tells us if that is so. + return addResult.second ? adoptRef(*addResult.first) : *addResult.first; } PassRefPtr<StringImpl> AtomicString::add(const UChar* s) @@ -210,10 +197,11 @@ PassRefPtr<StringImpl> AtomicString::add(const UChar* s) return StringImpl::empty(); UCharBuffer buf = {s, length}; - pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable()->add<UCharBuffer, UCharBufferTranslator>(buf); - if (!addResult.second) - return *addResult.first; - return adoptRef(*addResult.first); + pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<UCharBuffer, UCharBufferTranslator>(buf); + + // If the string is newly-translated, then we need to adopt it. + // The boolean in the pair tells us if that is so. + return addResult.second ? adoptRef(*addResult.first) : *addResult.first; } PassRefPtr<StringImpl> AtomicString::add(StringImpl* r) @@ -224,7 +212,7 @@ PassRefPtr<StringImpl> AtomicString::add(StringImpl* r) if (r->length() == 0) return StringImpl::empty(); - StringImpl* result = *stringTable()->add(r).first; + StringImpl* result = *stringTable().add(r).first; if (result == r) r->m_inTable = true; return result; @@ -232,7 +220,7 @@ PassRefPtr<StringImpl> AtomicString::add(StringImpl* r) void AtomicString::remove(StringImpl* r) { - stringTable()->remove(r); + stringTable().remove(r); } #if USE(JSC) @@ -247,7 +235,7 @@ PassRefPtr<StringImpl> AtomicString::add(const JSC::Identifier& identifier) return StringImpl::empty(); HashAndCharacters buffer = { string->computedHash(), string->data(), length }; - pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable()->add<HashAndCharacters, HashAndCharactersTranslator>(buffer); + pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<HashAndCharacters, HashAndCharactersTranslator>(buffer); if (!addResult.second) return *addResult.first; return adoptRef(*addResult.first); @@ -264,12 +252,11 @@ PassRefPtr<StringImpl> AtomicString::add(const JSC::UString& ustring) return StringImpl::empty(); HashAndCharacters buffer = { string->hash(), string->data(), length }; - pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable()->add<HashAndCharacters, HashAndCharactersTranslator>(buffer); + pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<HashAndCharacters, HashAndCharactersTranslator>(buffer); if (!addResult.second) return *addResult.first; return adoptRef(*addResult.first); } -#endif AtomicStringImpl* AtomicString::find(const JSC::Identifier& identifier) { @@ -282,8 +269,8 @@ AtomicStringImpl* AtomicString::find(const JSC::Identifier& identifier) return static_cast<AtomicStringImpl*>(StringImpl::empty()); HashAndCharacters buffer = { string->computedHash(), string->data(), length }; - HashSet<StringImpl*>::iterator iterator = stringTable()->find<HashAndCharacters, HashAndCharactersTranslator>(buffer); - if (iterator == stringTable()->end()) + HashSet<StringImpl*>::iterator iterator = stringTable().find<HashAndCharacters, HashAndCharactersTranslator>(buffer); + if (iterator == stringTable().end()) return 0; return static_cast<AtomicStringImpl*>(*iterator); } @@ -292,6 +279,7 @@ AtomicString::operator UString() const { return m_string; } +#endif DEFINE_GLOBAL(AtomicString, nullAtom) DEFINE_GLOBAL(AtomicString, emptyAtom, "") @@ -306,12 +294,6 @@ void AtomicString::init() // Initialization is not thread safe, so this function must be called from the main thread first. ASSERT(isMainThread()); -#if ENABLE(WORKERS) - staticStringTable = new ThreadSpecific<HashSet<StringImpl*> >; -#else - staticStringTable = new HashSet<StringImpl*>; -#endif - // Use placement new to initialize the globals. new ((void*)&nullAtom) AtomicString; new ((void*)&emptyAtom) AtomicString(""); diff --git a/WebCore/platform/text/AtomicString.h b/WebCore/platform/text/AtomicString.h index ad034d9..f4efab9 100644 --- a/WebCore/platform/text/AtomicString.h +++ b/WebCore/platform/text/AtomicString.h @@ -89,14 +89,14 @@ public: static void remove(StringImpl*); +#if PLATFORM(CF) || (PLATFORM(QT) && PLATFORM(DARWIN)) + AtomicString(CFStringRef s) : m_string(add(String(s).impl())) { } + CFStringRef createCFString() const { return m_string.createCFString(); } +#endif #ifdef __OBJC__ AtomicString(NSString* s) : m_string(add(String(s).impl())) { } operator NSString*() const { return m_string; } #endif -#if PLATFORM(SYMBIAN) - AtomicString(const TDesC& s) : m_string(add(String(s).impl())) { } - operator TPtrC() const { return m_string; } -#endif #if PLATFORM(QT) AtomicString(const QString& s) : m_string(add(String(s).impl())) { } operator QString() const { return m_string; } diff --git a/WebCore/platform/text/PlatformString.h b/WebCore/platform/text/PlatformString.h index 73a44bd..35d3079 100644 --- a/WebCore/platform/text/PlatformString.h +++ b/WebCore/platform/text/PlatformString.h @@ -30,11 +30,12 @@ #include <wtf/PassRefPtr.h> #if USE(JSC) -#include <kjs/identifier.h> +#include <runtime/Identifier.h> #else -// kjs/identifier.h includes HashMap.h. We explicitly include it in the case of -// non-JSC builds to keep things consistent. +// runtime/Identifier.h includes HashMap.h and HashSet.h. We explicitly include +// them in the case of non-JSC builds to keep things consistent. #include <wtf/HashMap.h> +#include <wtf/HashSet.h> #endif #if PLATFORM(CF) || (PLATFORM(QT) && PLATFORM(DARWIN)) @@ -98,6 +99,8 @@ public: int find(UChar c, int start = 0) const { return m_impl ? m_impl->find(c, start) : -1; } + int find(CharacterMatchFunctionPtr matchFunction, int start = 0) const + { return m_impl ? m_impl->find(matchFunction, start) : -1; } int find(const char* str, int start = 0, bool caseSensitive = true) const { return m_impl ? m_impl->find(str, start, caseSensitive) : -1; } int find(const String& str, int start = 0, bool caseSensitive = true) const @@ -138,10 +141,14 @@ public: String stripWhiteSpace() const; String simplifyWhiteSpace() const; - + + String removeCharacters(CharacterMatchFunctionPtr) const; + // Return the string with case folded for case insensitive comparison. String foldCase() const; + static String number(short); + static String number(unsigned short); static String number(int); static String number(unsigned); static String number(long); @@ -176,6 +183,12 @@ public: // to ever prefer copy() over plain old assignment. String copy() const; + // Makes a deep copy like copy() but only for a substring. + // (This ensures that you always get something suitable for a thread while subtring + // may not. For example, in the empty string case, StringImpl::substring returns + // empty() which is not safe for another thread.) + String substringCopy(unsigned pos, unsigned len = UINT_MAX) const; + bool isNull() const { return !m_impl; } bool isEmpty() const; @@ -200,12 +213,6 @@ public: operator QString() const; #endif -#if PLATFORM(SYMBIAN) - String(const TDesC&); - operator TPtrC() const { return des(); } - TPtrC des() const { if (!m_impl) return KNullDesC(); return m_impl->des(); } -#endif - #if PLATFORM(WX) String(const wxString&); operator wxString() const; @@ -296,6 +303,17 @@ inline int find(const UChar* characters, size_t length, UChar character, int sta return -1; } +inline int find(const UChar* characters, size_t length, CharacterMatchFunctionPtr matchFunction, int startPosition) +{ + if (startPosition >= static_cast<int>(length)) + return -1; + for (size_t i = startPosition; i < length; ++i) { + if (matchFunction(characters[i])) + return static_cast<int>(i); + } + return -1; +} + inline int reverseFind(const UChar* characters, size_t length, UChar character, int startPosition) { if (startPosition >= static_cast<int>(length) || !length) diff --git a/WebCore/platform/text/RegularExpression.cpp b/WebCore/platform/text/RegularExpression.cpp index 1b933ff..6329b3b 100644 --- a/WebCore/platform/text/RegularExpression.cpp +++ b/WebCore/platform/text/RegularExpression.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2008 Collabora Ltd. * * Redistribution and use in source and binary forms, with or without @@ -27,86 +27,58 @@ #include "config.h" #include "RegularExpression.h" -#include "PlatformString.h" #include "Logging.h" -#include <wtf/RefCounted.h> #include <pcre/pcre.h> -#include <sys/types.h> namespace WebCore { -const size_t maxSubstrings = 10; -const size_t maxOffsets = 3 * maxSubstrings; - class RegularExpression::Private : public RefCounted<Private> { public: - static PassRefPtr<Private> create() { return adoptRef(new Private); } - static PassRefPtr<Private> create(const String& pattern, bool caseSensitive) { return adoptRef(new Private(pattern, caseSensitive)); } - + static PassRefPtr<Private> create(const String& pattern, TextCaseSensitivity); ~Private(); - void compile(bool caseSensitive); + JSRegExp* regexp() const { return m_regexp; } + int lastMatchLength; - String pattern; - JSRegExp* regex; - - String lastMatchString; - int lastMatchOffsets[maxOffsets]; - int lastMatchCount; - int lastMatchPos; - int lastMatchLength; - private: - Private(); - Private(const String& pattern, bool caseSensitive); -}; - -RegularExpression::Private::Private() - : pattern("") -{ - compile(true); -} + Private(const String& pattern, TextCaseSensitivity); + static JSRegExp* compile(const String& pattern, TextCaseSensitivity); -RegularExpression::Private::Private(const String& p, bool caseSensitive) - : pattern(p) - , lastMatchPos(-1) - , lastMatchLength(-1) -{ - compile(caseSensitive); -} + JSRegExp* m_regexp; +}; -void RegularExpression::Private::compile(bool caseSensitive) +inline JSRegExp* RegularExpression::Private::compile(const String& pattern, TextCaseSensitivity caseSensitivity) { const char* errorMessage; - regex = jsRegExpCompile(pattern.characters(), pattern.length(), - caseSensitive ? JSRegExpDoNotIgnoreCase : JSRegExpIgnoreCase, JSRegExpSingleLine, + JSRegExp* regexp = jsRegExpCompile(pattern.characters(), pattern.length(), + caseSensitivity == TextCaseSensitive ? JSRegExpDoNotIgnoreCase : JSRegExpIgnoreCase, JSRegExpSingleLine, 0, &errorMessage); - if (!regex) + if (!regexp) LOG_ERROR("RegularExpression: pcre_compile failed with '%s'", errorMessage); + return regexp; } -RegularExpression::Private::~Private() +inline RegularExpression::Private::Private(const String& pattern, TextCaseSensitivity caseSensitivity) + : lastMatchLength(-1) + , m_regexp(compile(pattern, caseSensitivity)) { - jsRegExpFree(regex); } - -RegularExpression::RegularExpression() - : d(Private::create()) +inline PassRefPtr<RegularExpression::Private> RegularExpression::Private::create(const String& pattern, TextCaseSensitivity caseSensitivity) { + return adoptRef(new Private(pattern, caseSensitivity)); } -RegularExpression::RegularExpression(const String& pattern, bool caseSensitive) - : d(Private::create(pattern, caseSensitive)) +RegularExpression::Private::~Private() { + jsRegExpFree(m_regexp); } -RegularExpression::RegularExpression(const char* pattern) - : d(Private::create(pattern, true)) +RegularExpression::RegularExpression(const String& pattern, TextCaseSensitivity caseSensitivity) + : d(Private::create(pattern, caseSensitivity)) { } - RegularExpression::RegularExpression(const RegularExpression& re) : d(re.d) { @@ -118,52 +90,41 @@ RegularExpression::~RegularExpression() RegularExpression& RegularExpression::operator=(const RegularExpression& re) { - RegularExpression tmp(re); - tmp.d.swap(d); + d = re.d; return *this; } -String RegularExpression::pattern() const -{ - return d->pattern; -} - int RegularExpression::match(const String& str, int startFrom, int* matchLength) const { + if (!d->regexp()) + return -1; + if (str.isNull()) return -1; - d->lastMatchString = str; // First 2 offsets are start and end offsets; 3rd entry is used internally by pcre - d->lastMatchCount = jsRegExpExecute(d->regex, d->lastMatchString.characters(), - d->lastMatchString.length(), startFrom, d->lastMatchOffsets, maxOffsets); - if (d->lastMatchCount < 0) { - if (d->lastMatchCount != JSRegExpErrorNoMatch) - LOG_ERROR("RegularExpression: pcre_exec() failed with result %d", d->lastMatchCount); - d->lastMatchPos = -1; + static const size_t maxOffsets = 3; + int offsets[maxOffsets]; + int result = jsRegExpExecute(d->regexp(), str.characters(), str.length(), startFrom, offsets, maxOffsets); + if (result < 0) { + if (result != JSRegExpErrorNoMatch) + LOG_ERROR("RegularExpression: pcre_exec() failed with result %d", result); d->lastMatchLength = -1; - d->lastMatchString = String(); return -1; } - + // 1 means 1 match; 0 means more than one match. First match is recorded in offsets. - d->lastMatchPos = d->lastMatchOffsets[0]; - d->lastMatchLength = d->lastMatchOffsets[1] - d->lastMatchOffsets[0]; + d->lastMatchLength = offsets[1] - offsets[0]; if (matchLength) *matchLength = d->lastMatchLength; - return d->lastMatchPos; -} - -int RegularExpression::search(const String& str, int startFrom) const -{ - if (startFrom < 0) - startFrom = str.length() - startFrom; - return match(str, startFrom, 0); + return offsets[0]; } int RegularExpression::searchRev(const String& str) const { - // FIXME: Total hack for now. Search forward, return the last, greedy match + // FIXME: This could be faster if it actually searched backwards. + // Instead, it just searches forwards, multiple times until it finds the last match. + int start = 0; int pos; int lastPos = -1; @@ -180,17 +141,10 @@ int RegularExpression::searchRev(const String& str) const start = pos + 1; } } while (pos != -1); - d->lastMatchPos = lastPos; d->lastMatchLength = lastMatchLength; return lastPos; } -int RegularExpression::pos(int n) -{ - ASSERT(n == 0); - return d->lastMatchPos; -} - int RegularExpression::matchedLength() const { return d->lastMatchLength; diff --git a/WebCore/platform/text/RegularExpression.h b/WebCore/platform/text/RegularExpression.h index 5d1991e..3254067 100644 --- a/WebCore/platform/text/RegularExpression.h +++ b/WebCore/platform/text/RegularExpression.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,29 +26,21 @@ #ifndef RegularExpression_h #define RegularExpression_h -#include <wtf/RefPtr.h> +#include "PlatformString.h" namespace WebCore { -class String; - class RegularExpression { public: - RegularExpression(); - RegularExpression(const String&, bool caseSensitive = false); - RegularExpression(const char*); + RegularExpression(const String&, TextCaseSensitivity); ~RegularExpression(); RegularExpression(const RegularExpression&); RegularExpression& operator=(const RegularExpression&); - String pattern() const; int match(const String&, int startFrom = 0, int* matchLength = 0) const; - - int search(const String&, int startFrom = 0) const; int searchRev(const String&) const; - int pos(int n = 0); int matchedLength() const; private: diff --git a/WebCore/platform/text/String.cpp b/WebCore/platform/text/String.cpp index 44500e1..638e45f 100644 --- a/WebCore/platform/text/String.cpp +++ b/WebCore/platform/text/String.cpp @@ -25,7 +25,7 @@ #include "FloatConversion.h" #include "StringBuffer.h" #include "TextEncoding.h" -#include <kjs/dtoa.h> +#include <wtf/dtoa.h> #include <limits> #include <stdarg.h> #include <wtf/ASCIICType.h> @@ -248,6 +248,13 @@ String String::substring(unsigned pos, unsigned len) const return m_impl->substring(pos, len); } +String String::substringCopy(unsigned pos, unsigned len) const +{ + if (!m_impl) + return String(); + return m_impl->substringCopy(pos, len); +} + String String::lower() const { if (!m_impl) @@ -276,6 +283,13 @@ String String::simplifyWhiteSpace() const return m_impl->simplifyWhiteSpace(); } +String String::removeCharacters(CharacterMatchFunctionPtr findMatch) const +{ + if (!m_impl) + return String(); + return m_impl->removeCharacters(findMatch); +} + String String::foldCase() const { if (!m_impl) @@ -364,6 +378,16 @@ String String::format(const char *format, ...) #endif } +String String::number(short n) +{ + return String::format("%hd", n); +} + +String String::number(unsigned short n) +{ + return String::format("%hu", n); +} + String String::number(int n) { return String::format("%d", n); @@ -791,7 +815,7 @@ double charactersToDouble(const UChar* data, size_t length, bool* ok) bytes[i] = data[i] < 0x7F ? data[i] : '?'; bytes[length] = '\0'; char* end; - double val = JSC::strtod(bytes.data(), &end); + double val = WTF::strtod(bytes.data(), &end); if (ok) *ok = (end == 0 || *end == '\0'); return val; @@ -823,7 +847,9 @@ PassRefPtr<SharedBuffer> utf8Buffer(const String& string) } // namespace WebCore #ifndef NDEBUG -// For debugging only -- leaks memory +// For use in the debugger - leaks memory +WebCore::String* string(const char*); + WebCore::String* string(const char* s) { return new WebCore::String(s); diff --git a/WebCore/platform/text/StringHash.h b/WebCore/platform/text/StringHash.h index c6e08a6..336dce3 100644 --- a/WebCore/platform/text/StringHash.h +++ b/WebCore/platform/text/StringHash.h @@ -21,8 +21,9 @@ #ifndef StringHash_h #define StringHash_h -#include "AtomicStringImpl.h" +#include "AtomicString.h" #include "PlatformString.h" +#include <wtf/HashFunctions.h> #include <wtf/HashTraits.h> #include <wtf/unicode/Unicode.h> @@ -76,9 +77,6 @@ namespace WebCore { }; class CaseFoldingHash { - private: - // Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's - static const unsigned PHI = 0x9e3779b9U; public: // Paul Hsieh's SuperFastHash // http://www.azillionmonkeys.com/qed/hash.html @@ -86,7 +84,7 @@ namespace WebCore { { unsigned l = length; const UChar* s = data; - uint32_t hash = PHI; + uint32_t hash = WTF::stringHashingStartValue; uint32_t tmp; int rem = l & 1; @@ -136,7 +134,7 @@ namespace WebCore { unsigned l = length; const char* s = str; - uint32_t hash = PHI; + uint32_t hash = WTF::stringHashingStartValue; uint32_t tmp; int rem = l & 1; @@ -199,10 +197,18 @@ namespace WebCore { { return hash(key.impl()); } + static unsigned hash(const AtomicString& key) + { + return hash(key.impl()); + } static bool equal(const String& a, const String& b) { return equal(a.impl(), b.impl()); } + static bool equal(const AtomicString& a, const AtomicString& b) + { + return (a == b) || equal(a.impl(), b.impl()); + } static const bool safeToCompareToEmptyOrDeleted = false; }; diff --git a/WebCore/platform/text/StringImpl.cpp b/WebCore/platform/text/StringImpl.cpp index 911c0dc..0556f8e 100644 --- a/WebCore/platform/text/StringImpl.cpp +++ b/WebCore/platform/text/StringImpl.cpp @@ -33,8 +33,10 @@ #include "StringHash.h" #include "TextBreakIterator.h" #include "TextEncoding.h" -#include <kjs/dtoa.h> +#include "ThreadGlobalData.h" +#include <wtf/dtoa.h> #include <wtf/Assertions.h> +#include <wtf/Threading.h> #include <wtf/unicode/Unicode.h> using namespace WTF; @@ -164,8 +166,7 @@ StringImpl::~StringImpl() StringImpl* StringImpl::empty() { - static StringImpl* e = new StringImpl; - return e; + return threadGlobalData().emptyString(); } bool StringImpl::containsOnlyWhitespace() @@ -188,6 +189,17 @@ PassRefPtr<StringImpl> StringImpl::substring(unsigned pos, unsigned len) return create(m_data + pos, len); } +PassRefPtr<StringImpl> StringImpl::substringCopy(unsigned pos, unsigned len) +{ + if (pos >= m_length) + pos = m_length; + if (len > m_length - pos) + len = m_length - pos; + if (!len) + return adoptRef(new StringImpl); + return substring(pos, len); +} + UChar32 StringImpl::characterStartingAt(unsigned i) { if (U16_IS_SINGLE(m_data[i])) @@ -334,6 +346,38 @@ PassRefPtr<StringImpl> StringImpl::stripWhiteSpace() return create(m_data + start, end + 1 - start); } +PassRefPtr<StringImpl> StringImpl::removeCharacters(CharacterMatchFunctionPtr findMatch) +{ + const UChar* from = m_data; + const UChar* fromend = from + m_length; + + // Assume the common case will not remove any characters + while (from != fromend && !findMatch(*from)) + from++; + if (from == fromend) + return this; + + StringBuffer data(m_length); + UChar* to = data.characters(); + unsigned outc = from - m_data; + + if (outc) + memcpy(to, m_data, outc * sizeof(UChar)); + + while (true) { + while (from != fromend && findMatch(*from)) + from++; + while (from != fromend && !findMatch(*from)) + to[outc++] = *from++; + if (from == fromend) + break; + } + + data.shrink(outc); + + return adopt(data); +} + PassRefPtr<StringImpl> StringImpl::simplifyWhiteSpace() { StringBuffer data(m_length); @@ -510,6 +554,11 @@ int StringImpl::find(UChar c, int start) return WebCore::find(m_data, m_length, c, start); } +int StringImpl::find(CharacterMatchFunctionPtr matchFunction, int start) +{ + return WebCore::find(m_data, m_length, matchFunction, start); +} + int StringImpl::find(StringImpl* str, int index, bool caseSensitive) { /* diff --git a/WebCore/platform/text/StringImpl.h b/WebCore/platform/text/StringImpl.h index 57f64c8..281aa37 100644 --- a/WebCore/platform/text/StringImpl.h +++ b/WebCore/platform/text/StringImpl.h @@ -47,12 +47,17 @@ struct HashAndCharactersTranslator; struct StringHash; struct UCharBufferTranslator; +enum TextCaseSensitivity { TextCaseSensitive, TextCaseInsensitive }; + +typedef bool (*CharacterMatchFunctionPtr)(UChar); + class StringImpl : public RefCounted<StringImpl> { friend class AtomicString; friend struct CStringTranslator; friend struct HashAndCharactersTranslator; friend struct UCharBufferTranslator; private: + friend class ThreadGlobalData; StringImpl(); StringImpl(const UChar*, unsigned length); StringImpl(const char*, unsigned length); @@ -94,6 +99,12 @@ public: // Since StringImpl objects are immutable, there's no other reason to make a copy. PassRefPtr<StringImpl> copy(); + // Makes a deep copy like copy() but only for a substring. + // (This ensures that you always get something suitable for a thread while subtring + // may not. For example, in the empty string case, substring returns empty() which + // is not safe for another thread.) + PassRefPtr<StringImpl> substringCopy(unsigned pos, unsigned len = UINT_MAX); + PassRefPtr<StringImpl> substring(unsigned pos, unsigned len = UINT_MAX); UChar operator[](unsigned i) { ASSERT(i < m_length); return m_data[i]; } @@ -124,14 +135,17 @@ public: PassRefPtr<StringImpl> stripWhiteSpace(); PassRefPtr<StringImpl> simplifyWhiteSpace(); + PassRefPtr<StringImpl> removeCharacters(CharacterMatchFunctionPtr); + int find(const char*, int index = 0, bool caseSensitive = true); int find(UChar, int index = 0); + int find(CharacterMatchFunctionPtr, int index = 0); int find(StringImpl*, int index, bool caseSensitive = true); int reverseFind(UChar, int index); int reverseFind(StringImpl*, int index, bool caseSensitive = true); - bool startsWith(StringImpl* m_data, bool caseSensitive = true) { return find(m_data, 0, caseSensitive) == 0; } + bool startsWith(StringImpl* m_data, bool caseSensitive = true) { return reverseFind(m_data, 0, caseSensitive) == 0; } bool endsWith(StringImpl*, bool caseSensitive = true); PassRefPtr<StringImpl> replace(UChar, UChar); diff --git a/WebCore/platform/text/TextCodecICU.cpp b/WebCore/platform/text/TextCodecICU.cpp index 0a324a2..72d45ad 100644 --- a/WebCore/platform/text/TextCodecICU.cpp +++ b/WebCore/platform/text/TextCodecICU.cpp @@ -30,10 +30,12 @@ #include "CharacterNames.h" #include "CString.h" #include "PlatformString.h" +#include "ThreadGlobalData.h" #include <unicode/ucnv.h> #include <unicode/ucnv_cb.h> #include <wtf/Assertions.h> #include <wtf/StringExtras.h> +#include <wtf/Threading.h> using std::auto_ptr; using std::min; @@ -42,7 +44,16 @@ namespace WebCore { const size_t ConversionBufferSize = 16384; -static UConverter* cachedConverterICU; +ICUConverterWrapper::~ICUConverterWrapper() +{ + if (converter) + ucnv_close(converter); +} + +static UConverter*& cachedConverterICU() +{ + return threadGlobalData().cachedConverterICU().converter; +} static auto_ptr<TextCodec> newTextCodecICU(const TextEncoding& encoding, const void*) { @@ -95,12 +106,12 @@ void TextCodecICU::registerExtendedEncodingNames(EncodingNameRegistrar registrar standardName = "GBK"; // Similarly, EUC-KR encodings all map to an extended version. else if (strcmp(standardName, "KSC_5601") == 0 || strcmp(standardName, "EUC-KR") == 0 || strcmp(standardName, "cp1363") == 0) - standardName = "windows-949-2000"; + standardName = "windows-949"; // And so on. else if (strcasecmp(standardName, "iso-8859-9") == 0) // This name is returned in different case by ICU 3.2 and 3.6. standardName = "windows-1254"; else if (strcmp(standardName, "TIS-620") == 0) - standardName = "windows-874-2000"; + standardName = "windows-874"; registrar(standardName, standardName); @@ -132,19 +143,23 @@ void TextCodecICU::registerExtendedEncodingNames(EncodingNameRegistrar registrar registrar("xmacukrainian", "x-mac-cyrillic"); #endif registrar("cnbig5", "Big5"); - registrar("cngb", "EUC-CN"); + registrar("xxbig5", "Big5"); + registrar("cngb", "GBK"); + registrar("csgb231280", "GBK"); + registrar("xeuccn", "GBK"); + registrar("xgbk", "GBK"); registrar("csISO88598I", "ISO_8859-8-I"); - registrar("csgb231280", "EUC-CN"); - registrar("dos874", "cp874"); registrar("koi", "KOI8-R"); registrar("logical", "ISO-8859-8-I"); registrar("unicode11utf8", "UTF-8"); registrar("unicode20utf8", "UTF-8"); + registrar("xunicode20utf8", "UTF-8"); registrar("visual", "ISO-8859-8"); registrar("winarabic", "windows-1256"); registrar("winbaltic", "windows-1257"); registrar("wincyrillic", "windows-1251"); - registrar("iso885911", "windows874-2000"); + registrar("iso885911", "windows-874"); + registrar("dos874", "windows-874"); registrar("wingreek", "windows-1253"); registrar("winhebrew", "windows-1255"); registrar("winlatin2", "windows-1250"); @@ -153,15 +168,8 @@ void TextCodecICU::registerExtendedEncodingNames(EncodingNameRegistrar registrar registrar("xcp1250", "windows-1250"); registrar("xcp1251", "windows-1251"); registrar("xeuc", "EUC-JP"); - registrar("xeuccn", "EUC-CN"); - registrar("xgbk", "EUC-CN"); - registrar("xunicode20utf8", "UTF-8"); - registrar("xwindows949", "windows-949-2000"); - registrar("xxbig5", "Big5"); - - // This alias is present in modern versions of ICU, but it has no standard name, - // so we give one to it manually. It is not present in ICU 3.2. - registrar("windows874", "windows874-2000"); + registrar("xwindows949", "windows-949"); + registrar("xuhc", "windows-949"); // These aliases are present in modern versions of ICU, but use different codecs, and have no standard names. // They are not present in ICU 3.2. @@ -205,9 +213,10 @@ TextCodecICU::~TextCodecICU() void TextCodecICU::releaseICUConverter() const { if (m_converterICU) { - if (cachedConverterICU) - ucnv_close(cachedConverterICU); - cachedConverterICU = m_converterICU; + UConverter*& cachedConverter = cachedConverterICU(); + if (cachedConverter) + ucnv_close(cachedConverter); + cachedConverter = m_converterICU; m_converterICU = 0; } } @@ -221,12 +230,13 @@ void TextCodecICU::createICUConverter() const UErrorCode err; - if (cachedConverterICU) { + UConverter*& cachedConverter = cachedConverterICU(); + if (cachedConverter) { err = U_ZERO_ERROR; - const char* cachedName = ucnv_getName(cachedConverterICU, &err); + const char* cachedName = ucnv_getName(cachedConverter, &err); if (U_SUCCESS(err) && m_encoding == cachedName) { - m_converterICU = cachedConverterICU; - cachedConverterICU = 0; + m_converterICU = cachedConverter; + cachedConverter = 0; return; } } @@ -422,7 +432,7 @@ CString TextCodecICU::encode(const UChar* characters, size_t length, Unencodable // until then, we change the backslash into a yen sign. // Encoding will change the yen sign back into a backslash. String copy(characters, length); - copy.replace('\\', m_encoding.backslashAsCurrencySymbol()); + copy = m_encoding.displayString(copy.impl()); const UChar* source = copy.characters(); const UChar* sourceLimit = source + copy.length(); diff --git a/WebCore/platform/text/TextCodecICU.h b/WebCore/platform/text/TextCodecICU.h index 9c9a4a7b..f07758f 100644 --- a/WebCore/platform/text/TextCodecICU.h +++ b/WebCore/platform/text/TextCodecICU.h @@ -64,6 +64,16 @@ namespace WebCore { mutable bool m_needsGBKFallbacks; }; + struct ICUConverterWrapper { + ICUConverterWrapper() + : converter(0) + { + } + ~ICUConverterWrapper(); + + UConverter* converter; + }; + } // namespace WebCore #endif // TextCodecICU_h diff --git a/WebCore/platform/text/TextCodecUTF16.cpp b/WebCore/platform/text/TextCodecUTF16.cpp index 88e4e73..a4d0d28 100644 --- a/WebCore/platform/text/TextCodecUTF16.cpp +++ b/WebCore/platform/text/TextCodecUTF16.cpp @@ -65,7 +65,7 @@ void TextCodecUTF16::registerCodecs(TextCodecRegistrar registrar) registrar("UTF-16BE", newStreamingTextDecoderUTF16BE, 0); } -String TextCodecUTF16::decode(const char* bytes, size_t length, bool, bool stopOnError, bool& sawError) +String TextCodecUTF16::decode(const char* bytes, size_t length, bool, bool, bool&) { if (!length) return String(); @@ -89,18 +89,19 @@ String TextCodecUTF16::decode(const char* bytes, size_t length, bool, bool stopO numChars -= 1; } - if (m_littleEndian) + if (m_littleEndian) { for (size_t i = 0; i < numChars; ++i) { UChar c = p[0] | (p[1] << 8); p += 2; *q++ = c; } - else + } else { for (size_t i = 0; i < numChars; ++i) { UChar c = (p[0] << 8) | p[1]; p += 2; *q++ = c; } + } if (numBytes & 1) { ASSERT(!m_haveBufferedByte); diff --git a/WebCore/platform/text/TextEncoding.cpp b/WebCore/platform/text/TextEncoding.cpp index 9026049..063d96b 100644 --- a/WebCore/platform/text/TextEncoding.cpp +++ b/WebCore/platform/text/TextEncoding.cpp @@ -39,6 +39,7 @@ #endif #include <wtf/HashSet.h> #include <wtf/OwnPtr.h> +#include <wtf/StdLibExtras.h> namespace WebCore { @@ -49,13 +50,21 @@ static void addEncodingName(HashSet<const char*>& set, const char* name) set.add(atomicName); } +static const TextEncoding& UTF7Encoding() +{ + static TextEncoding globalUTF7Encoding("UTF-7"); + return globalUTF7Encoding; +} + TextEncoding::TextEncoding(const char* name) : m_name(atomicCanonicalTextEncodingName(name)) + , m_backslashAsCurrencySymbol(backslashAsCurrencySymbol()) { } TextEncoding::TextEncoding(const String& name) : m_name(atomicCanonicalTextEncodingName(name.characters(), name.length())) + , m_backslashAsCurrencySymbol(backslashAsCurrencySymbol()) { } @@ -122,7 +131,7 @@ bool TextEncoding::isJapanese() const if (noExtendedTextEncodingNameUsed()) return false; - static HashSet<const char*> set; + DEFINE_STATIC_LOCAL(HashSet<const char*>, set, ()); if (set.isEmpty()) { addEncodingName(set, "x-mac-japanese"); addEncodingName(set, "cp932"); @@ -154,9 +163,29 @@ UChar TextEncoding::backslashAsCurrencySymbol() const return (m_name == a || m_name == b) ? 0x00A5 : '\\'; } -const TextEncoding& TextEncoding::closest8BitEquivalent() const +bool TextEncoding::isNonByteBasedEncoding() const +{ + return *this == UTF16LittleEndianEncoding() + || *this == UTF16BigEndianEncoding() + || *this == UTF32BigEndianEncoding() + || *this == UTF32LittleEndianEncoding(); +} + +const TextEncoding& TextEncoding::closestByteBasedEquivalent() const { - if (*this == UTF16BigEndianEncoding() || *this == UTF16LittleEndianEncoding()) + if (isNonByteBasedEncoding()) + return UTF8Encoding(); + return *this; +} + +// HTML5 specifies that UTF-8 be used in form submission when a form is +// is a part of a document in UTF-16 probably because UTF-16 is not a +// byte-based encoding and can contain 0x00. By extension, the same +// should be done for UTF-32. In case of UTF-7, it is a byte-based encoding, +// but it's fraught with problems and we'd rather steer clear of it. +const TextEncoding& TextEncoding::encodingForFormSubmission() const +{ + if (isNonByteBasedEncoding() || *this == UTF7Encoding()) return UTF8Encoding(); return *this; } @@ -197,7 +226,6 @@ const TextEncoding& UTF32LittleEndianEncoding() return globalUTF32LittleEndianEncoding; } - const TextEncoding& UTF8Encoding() { static TextEncoding globalUTF8Encoding("UTF-8"); diff --git a/WebCore/platform/text/TextEncoding.h b/WebCore/platform/text/TextEncoding.h index 0a0ab8c..b2bb816 100644 --- a/WebCore/platform/text/TextEncoding.h +++ b/WebCore/platform/text/TextEncoding.h @@ -44,8 +44,23 @@ namespace WebCore { const char* name() const { return m_name; } bool usesVisualOrdering() const; bool isJapanese() const; - UChar backslashAsCurrencySymbol() const; - const TextEncoding& closest8BitEquivalent() const; + + PassRefPtr<StringImpl> displayString(PassRefPtr<StringImpl> str) const { + if (m_backslashAsCurrencySymbol == '\\' || !str) + return str; + return str->replace('\\', m_backslashAsCurrencySymbol); + } + void displayBuffer(UChar* characters, unsigned len) const { + if (m_backslashAsCurrencySymbol == '\\') + return; + for (unsigned i = 0; i < len; ++i) { + if (characters[i] == '\\') + characters[i] = m_backslashAsCurrencySymbol; + } + } + + const TextEncoding& closestByteBasedEquivalent() const; + const TextEncoding& encodingForFormSubmission() const; String decode(const char* str, size_t length) const { @@ -56,7 +71,11 @@ namespace WebCore { CString encode(const UChar*, size_t length, UnencodableHandling) const; private: + UChar backslashAsCurrencySymbol() const; + const char* m_name; + UChar m_backslashAsCurrencySymbol; + bool isNonByteBasedEncoding() const; }; inline bool operator==(const TextEncoding& a, const TextEncoding& b) { return a.name() == b.name(); } diff --git a/WebCore/platform/text/TextEncodingRegistry.cpp b/WebCore/platform/text/TextEncodingRegistry.cpp index 3f1f078..2d89fac 100644 --- a/WebCore/platform/text/TextEncodingRegistry.cpp +++ b/WebCore/platform/text/TextEncodingRegistry.cpp @@ -32,8 +32,11 @@ #include "TextCodecUTF16.h" #include <wtf/ASCIICType.h> #include <wtf/Assertions.h> +#include <wtf/HashFunctions.h> #include <wtf/HashMap.h> +#include <wtf/StdLibExtras.h> #include <wtf/StringExtras.h> +#include <wtf/Threading.h> #if USE(ICU_UNICODE) #include "TextCodecICU.h" @@ -57,10 +60,6 @@ const size_t maxEncodingNameLength = 63; // it will properly skip those characters too. struct TextEncodingNameHash { - // Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's - // or anything like that. - static const unsigned PHI = 0x9e3779b9U; - static bool equal(const char* s1, const char* s2) { char c1; @@ -83,7 +82,7 @@ struct TextEncodingNameHash { // http://burtleburtle.net/bob/hash/doobs.html static unsigned hash(const char* s) { - unsigned h = PHI; + unsigned h = WTF::stringHashingStartValue; for (;;) { char c; do { @@ -113,6 +112,15 @@ struct TextCodecFactory { typedef HashMap<const char*, const char*, TextEncodingNameHash> TextEncodingNameMap; typedef HashMap<const char*, TextCodecFactory> TextCodecMap; +static Mutex& encodingRegistryMutex() +{ + // We don't have to use AtomicallyInitializedStatic here because + // this function is called on the main thread for any page before + // it is used in worker threads. + DEFINE_STATIC_LOCAL(Mutex, mutex, ()); + return mutex; +} + static TextEncodingNameMap* textEncodingNameMap; static TextCodecMap* textCodecMap; static bool didExtendTextCodecMaps; @@ -154,13 +162,17 @@ static void addToTextEncodingNameMap(const char* alias, const char* name) static void addToTextCodecMap(const char* name, NewTextCodecFunction function, const void* additionalData) { - TextEncoding encoding(name); - ASSERT(encoding.isValid()); - textCodecMap->add(encoding.name(), TextCodecFactory(function, additionalData)); + const char* atomicName = textEncodingNameMap->get(name); + ASSERT(atomicName); + textCodecMap->add(atomicName, TextCodecFactory(function, additionalData)); } static void buildBaseTextCodecMaps() { + ASSERT(isMainThread()); + ASSERT(!textCodecMap); + ASSERT(!textEncodingNameMap); + textCodecMap = new TextCodecMap; textEncodingNameMap = new TextEncodingNameMap; @@ -199,6 +211,8 @@ static void extendTextCodecMaps() std::auto_ptr<TextCodec> newTextCodec(const TextEncoding& encoding) { + MutexLocker lock(encodingRegistryMutex()); + ASSERT(textCodecMap); TextCodecFactory factory = textCodecMap->get(encoding.name()); ASSERT(factory.function); @@ -211,6 +225,9 @@ const char* atomicCanonicalTextEncodingName(const char* name) return 0; if (!textEncodingNameMap) buildBaseTextCodecMaps(); + + MutexLocker lock(encodingRegistryMutex()); + if (const char* atomicName = textEncodingNameMap->get(name)) return atomicName; if (didExtendTextCodecMaps) @@ -238,6 +255,7 @@ const char* atomicCanonicalTextEncodingName(const UChar* characters, size_t leng bool noExtendedTextEncodingNameUsed() { + // If the calling thread did not use extended encoding names, it is fine for it to use a stale false value. return !didExtendTextCodecMaps; } diff --git a/WebCore/platform/text/TextStream.cpp b/WebCore/platform/text/TextStream.cpp index 5b7a0c7..eb4bae7 100644 --- a/WebCore/platform/text/TextStream.cpp +++ b/WebCore/platform/text/TextStream.cpp @@ -33,6 +33,11 @@ namespace WebCore { static const size_t printBufferSize = 100; // large enough for any integer or floating point value in string format, including trailing null character +TextStream& TextStream::operator<<(bool b) +{ + return *this << (b ? "1" : "0"); +} + TextStream& TextStream::operator<<(int i) { char buffer[printBufferSize]; diff --git a/WebCore/platform/text/TextStream.h b/WebCore/platform/text/TextStream.h index 6fb3f4b..71034f3 100644 --- a/WebCore/platform/text/TextStream.h +++ b/WebCore/platform/text/TextStream.h @@ -35,6 +35,7 @@ class String; class TextStream { public: + TextStream& operator<<(bool); TextStream& operator<<(int); TextStream& operator<<(unsigned); TextStream& operator<<(long); diff --git a/WebCore/platform/text/chromium/TextBreakIteratorInternalICUChromium.cpp b/WebCore/platform/text/chromium/TextBreakIteratorInternalICUChromium.cpp new file mode 100644 index 0000000..09096d7 --- /dev/null +++ b/WebCore/platform/text/chromium/TextBreakIteratorInternalICUChromium.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Google Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "config.h" +#include "TextBreakIteratorInternalICU.h" + +namespace WebCore { + +const char* currentTextBreakLocaleID() +{ + return "en_us"; +} + +} // namespace WebCore diff --git a/WebCore/platform/text/mac/ShapeArabic.c b/WebCore/platform/text/mac/ShapeArabic.c index 6dbc008..1e0d91b 100644 --- a/WebCore/platform/text/mac/ShapeArabic.c +++ b/WebCore/platform/text/mac/ShapeArabic.c @@ -347,8 +347,7 @@ isTashkeelChar(UChar ch) { */ static int32_t shapeUnicode(UChar *dest, int32_t sourceLength, - int32_t destSize,uint32_t options, - UErrorCode *pErrorCode, + int32_t destSize, int tashkeelFlag) { int32_t i, iend; @@ -528,11 +527,11 @@ int32_t shapeArabic(const UChar *source, int32_t sourceLength, UChar *dest, int3 switch(options&U_SHAPE_LETTERS_MASK) { case U_SHAPE_LETTERS_SHAPE : /* Call the shaping function with tashkeel flag == 1 */ - destLength = shapeUnicode(dest,sourceLength,destCapacity,options,pErrorCode,1); + destLength = shapeUnicode(dest,sourceLength,destCapacity,1); break; case U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED : /* Call the shaping function with tashkeel flag == 0 */ - destLength = shapeUnicode(dest,sourceLength,destCapacity,options,pErrorCode,0); + destLength = shapeUnicode(dest,sourceLength,destCapacity,0); break; case U_SHAPE_LETTERS_UNSHAPE : ASSERT_NOT_REACHED(); diff --git a/WebCore/platform/text/mac/StringImplMac.mm b/WebCore/platform/text/mac/StringImplMac.mm index 2180b94..3e0731c 100644 --- a/WebCore/platform/text/mac/StringImplMac.mm +++ b/WebCore/platform/text/mac/StringImplMac.mm @@ -21,6 +21,8 @@ #include "config.h" #include "StringImpl.h" +#include <Foundation/Foundation.h> + namespace WebCore { StringImpl::operator NSString *() diff --git a/WebCore/platform/text/mac/TextCodecMac.cpp b/WebCore/platform/text/mac/TextCodecMac.cpp index ac1f0fb..3baf21f 100644 --- a/WebCore/platform/text/mac/TextCodecMac.cpp +++ b/WebCore/platform/text/mac/TextCodecMac.cpp @@ -31,7 +31,9 @@ #include "CharacterNames.h" #include "CharsetData.h" #include "PlatformString.h" +#include "ThreadGlobalData.h" #include <wtf/Assertions.h> +#include <wtf/Threading.h> using std::auto_ptr; using std::min; @@ -43,8 +45,10 @@ namespace WebCore { const size_t ConversionBufferSize = 16384; -static TECObjectRef cachedConverterTEC; -static TECTextEncodingID cachedConverterEncoding = invalidEncoding; +static TECConverterWrapper& cachedConverterTEC() +{ + return threadGlobalData().cachedConverterTEC(); +} void TextCodecMac::registerEncodingNames(EncodingNameRegistrar registrar) { @@ -91,22 +95,26 @@ TextCodecMac::~TextCodecMac() void TextCodecMac::releaseTECConverter() const { if (m_converterTEC) { - if (cachedConverterTEC != 0) - TECDisposeConverter(cachedConverterTEC); - cachedConverterTEC = m_converterTEC; - cachedConverterEncoding = m_encoding; + TECConverterWrapper& cachedConverter = cachedConverterTEC(); + if (cachedConverter.converter) + TECDisposeConverter(cachedConverter.converter); + cachedConverter.converter = m_converterTEC; + cachedConverter.encoding = m_encoding; m_converterTEC = 0; } } OSStatus TextCodecMac::createTECConverter() const { - bool cachedEncodingEqual = cachedConverterEncoding == m_encoding; - cachedConverterEncoding = invalidEncoding; + TECConverterWrapper& cachedConverter = cachedConverterTEC(); + + bool cachedEncodingEqual = cachedConverter.encoding == m_encoding; + cachedConverter.encoding = invalidEncoding; + + if (cachedEncodingEqual && cachedConverter.converter) { + m_converterTEC = cachedConverter.converter; + cachedConverter.converter = 0; - if (cachedEncodingEqual && cachedConverterTEC) { - m_converterTEC = cachedConverterTEC; - cachedConverterTEC = 0; TECClearConverterContextInfo(m_converterTEC); } else { OSStatus status = TECCreateConverter(&m_converterTEC, m_encoding, @@ -116,7 +124,7 @@ OSStatus TextCodecMac::createTECConverter() const TECSetBasicOptions(m_converterTEC, kUnicodeForceASCIIRangeMask); } - + return noErr; } diff --git a/WebCore/platform/text/mac/TextCodecMac.h b/WebCore/platform/text/mac/TextCodecMac.h index aee4a97..3e7a237 100644 --- a/WebCore/platform/text/mac/TextCodecMac.h +++ b/WebCore/platform/text/mac/TextCodecMac.h @@ -60,6 +60,14 @@ namespace WebCore { mutable TECObjectRef m_converterTEC; }; + struct TECConverterWrapper { + TECConverterWrapper() : converter(0), encoding(invalidEncoding) { } + ~TECConverterWrapper() { if (converter) TECDisposeConverter(converter); } + + TECObjectRef converter; + TECTextEncodingID encoding; + }; + } // namespace WebCore #endif // TextCodecMac_h |