summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/text
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/text')
-rw-r--r--WebCore/platform/text/AtomicString.cpp62
-rw-r--r--WebCore/platform/text/AtomicString.h8
-rw-r--r--WebCore/platform/text/PlatformString.h38
-rw-r--r--WebCore/platform/text/RegularExpression.cpp122
-rw-r--r--WebCore/platform/text/RegularExpression.h14
-rw-r--r--WebCore/platform/text/String.cpp32
-rw-r--r--WebCore/platform/text/StringHash.h18
-rw-r--r--WebCore/platform/text/StringImpl.cpp55
-rw-r--r--WebCore/platform/text/StringImpl.h16
-rw-r--r--WebCore/platform/text/TextCodecICU.cpp58
-rw-r--r--WebCore/platform/text/TextCodecICU.h10
-rw-r--r--WebCore/platform/text/TextCodecUTF16.cpp7
-rw-r--r--WebCore/platform/text/TextEncoding.cpp36
-rw-r--r--WebCore/platform/text/TextEncoding.h23
-rw-r--r--WebCore/platform/text/TextEncodingRegistry.cpp34
-rw-r--r--WebCore/platform/text/TextStream.cpp5
-rw-r--r--WebCore/platform/text/TextStream.h1
-rw-r--r--WebCore/platform/text/chromium/TextBreakIteratorInternalICUChromium.cpp32
-rw-r--r--WebCore/platform/text/mac/ShapeArabic.c7
-rw-r--r--WebCore/platform/text/mac/StringImplMac.mm2
-rw-r--r--WebCore/platform/text/mac/TextCodecMac.cpp32
-rw-r--r--WebCore/platform/text/mac/TextCodecMac.h8
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