diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog index e9bbd743f88af3b61bfbb765aa18cb62a2f50f14..f73070d9ff56cdf2926319ad97fed3fef792ca11 100644 --- a/JavaScriptCore/ChangeLog +++ b/JavaScriptCore/ChangeLog @@ -1,3 +1,44 @@ +2008-03-06 Alexey Proskuryakov + + Reviewed by Darin. + + Need to create a Collator abstraction for WebCore and JavaScriptCore + + * wtf/Threading.h: + (WTF::initializeThreading): + * wtf/ThreadingGtk.cpp: + (WTF::initializeThreading): + * wtf/ThreadingNone.cpp: + * wtf/ThreadingPthreads.cpp: + * wtf/ThreadingWin.cpp: + Added AtomicallyInitializedStatic. + + * kjs/string_object.cpp: (KJS::localeCompare): Changed to use Collator. + + * GNUmakefile.am: + * JavaScriptCore.exp: + * JavaScriptCore.pri: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * JavaScriptCoreSources.bkl: + Added new fiiles to projects. + + * wtf/unicode/Collator.h: Added. + (WTF::Collator::): + * wtf/unicode/CollatorDefault.cpp: Added. + (WTF::Collator::Collator): + (WTF::Collator::~Collator): + (WTF::Collator::setOrderLowerFirst): + (WTF::Collator::collate): + * wtf/unicode/icu/CollatorICU.cpp: Added. + (WTF::cachedCollatorMutex): + (WTF::Collator::Collator): + (WTF::Collator::~Collator): + (WTF::Collator::setOrderLowerFirst): + (WTF::Collator::collate): + (WTF::Collator::createCollator): + (WTF::Collator::releaseCollator): + 2008-03-05 Kevin Ollivier Fix the wx build after the bindings move. diff --git a/JavaScriptCore/GNUmakefile.am b/JavaScriptCore/GNUmakefile.am index 73afe623fc5f5e7bf9694f8dea081c19120f0237..f76c85bc7e49c409bf202f6bdb5ce2d451bc1235 100644 --- a/JavaScriptCore/GNUmakefile.am +++ b/JavaScriptCore/GNUmakefile.am @@ -48,6 +48,8 @@ javascriptcore_sources += \ JavaScriptCore/wtf/Assertions.cpp \ JavaScriptCore/wtf/HashTable.cpp \ JavaScriptCore/wtf/ThreadingGtk.cpp \ + JavaScriptCore/wtf/unicode/CollatorDefault.cpp \ + JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp \ JavaScriptCore/wtf/unicode/UTF8.cpp # Debug build diff --git a/JavaScriptCore/JavaScriptCore.exp b/JavaScriptCore/JavaScriptCore.exp index 5c951720c998cbda87c10e1d9351886be3ff095c..4a4c68a21436776527d8598cc098a5794c4647ba 100644 --- a/JavaScriptCore/JavaScriptCore.exp +++ b/JavaScriptCore/JavaScriptCore.exp @@ -209,6 +209,7 @@ __ZN3WTF15ThreadConditionC1Ev __ZN3WTF15ThreadConditionD1Ev __ZN3WTF16fastZeroedMallocEm __ZN3WTF23waitForThreadCompletionEjPPv +__ZN3WTF32atomicallyInitializedStaticMutexE __ZN3WTF5Mutex4lockEv __ZN3WTF5Mutex6unlockEv __ZN3WTF5Mutex7tryLockEv @@ -267,8 +268,11 @@ _jscore_collector_introspection _jscore_fastmalloc_introspection _kJSClassDefinitionEmpty _kjs_strtod +__ZN3WTF8Collator18setOrderLowerFirstEb +__ZN3WTF8CollatorC1EPKc +__ZN3WTF8CollatorD1Ev +__ZNK3WTF8Collator7collateEPKtmS2_m __ZN3KJS10throwErrorEPNS_9ExecStateENS_9ErrorTypeERKNS_7UStringE __ZNK3KJS8JSObject11hasPropertyEPNS_9ExecStateEj __ZN3KJS7UString6appendEPKc __ZN3KJS7CStringaSERKS0_ - diff --git a/JavaScriptCore/JavaScriptCore.pri b/JavaScriptCore/JavaScriptCore.pri index 5a4f38561c08fa760843ed535865f323c0c6057e..f6f59d05a56e7601178f1164541c78a76e8b0d23 100644 --- a/JavaScriptCore/JavaScriptCore.pri +++ b/JavaScriptCore/JavaScriptCore.pri @@ -36,6 +36,8 @@ KJSBISON += \ SOURCES += \ wtf/Assertions.cpp \ wtf/HashTable.cpp \ + wtf/unicode/CollatorDefault.cpp \ + wtf/unicode/icu/CollatorICU.cpp \ wtf/unicode/UTF8.cpp \ bindings/NP_jsobject.cpp \ bindings/npruntime.cpp \ diff --git a/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj b/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj index 19609751448455e922a34beeaf3153594bfc5da3..bdbe691d61b8135383522fed65f6dc219062d0ec 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj +++ b/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj @@ -361,6 +361,18 @@ RelativePath="..\..\wtf\unicode\Unicode.h" > + + + + + + diff --git a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj index c1269300c3290fef8e0ad886d8b7f6dee93c3fad..27c8b0862754855f557271789824a9e9fc55abca 100644 --- a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +++ b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj @@ -190,6 +190,9 @@ E11D51760B2E798D0056C188 /* StringExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = E11D51750B2E798D0056C188 /* StringExtras.h */; settings = {ATTRIBUTES = (Private, ); }; }; E195679609E7CF1200B89D13 /* UnicodeIcu.h in Headers */ = {isa = PBXBuildFile; fileRef = E195678F09E7CF1200B89D13 /* UnicodeIcu.h */; settings = {ATTRIBUTES = (Private, ); }; }; E195679809E7CF1200B89D13 /* Unicode.h in Headers */ = {isa = PBXBuildFile; fileRef = E195679409E7CF1200B89D13 /* Unicode.h */; settings = {ATTRIBUTES = (Private, ); }; }; + E1A862A90D7EBB76001EC6AA /* CollatorICU.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1A862A80D7EBB76001EC6AA /* CollatorICU.cpp */; }; + E1A862AB0D7EBB7D001EC6AA /* Collator.h in Headers */ = {isa = PBXBuildFile; fileRef = E1A862AA0D7EBB7D001EC6AA /* Collator.h */; settings = {ATTRIBUTES = (Private, ); }; }; + E1A862D60D7F2B5C001EC6AA /* CollatorDefault.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1A862D50D7F2B5C001EC6AA /* CollatorDefault.cpp */; }; E1EE79230D6C95CD00FEA3BA /* Threading.h in Headers */ = {isa = PBXBuildFile; fileRef = E1EE79220D6C95CD00FEA3BA /* Threading.h */; settings = {ATTRIBUTES = (Private, ); }; }; E1EE79280D6C964500FEA3BA /* Locker.h in Headers */ = {isa = PBXBuildFile; fileRef = E1EE79270D6C964500FEA3BA /* Locker.h */; settings = {ATTRIBUTES = (Private, ); }; }; E1EE793D0D6C9B9200FEA3BA /* ThreadingPthreads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1EE793C0D6C9B9200FEA3BA /* ThreadingPthreads.cpp */; }; @@ -486,6 +489,9 @@ E11D51750B2E798D0056C188 /* StringExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringExtras.h; sourceTree = ""; }; E195678F09E7CF1200B89D13 /* UnicodeIcu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnicodeIcu.h; sourceTree = ""; }; E195679409E7CF1200B89D13 /* Unicode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Unicode.h; sourceTree = ""; }; + E1A862A80D7EBB76001EC6AA /* CollatorICU.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CollatorICU.cpp; sourceTree = ""; }; + E1A862AA0D7EBB7D001EC6AA /* Collator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Collator.h; sourceTree = ""; }; + E1A862D50D7F2B5C001EC6AA /* CollatorDefault.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CollatorDefault.cpp; sourceTree = ""; }; E1EE79220D6C95CD00FEA3BA /* Threading.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Threading.h; sourceTree = ""; }; E1EE79270D6C964500FEA3BA /* Locker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Locker.h; sourceTree = ""; }; E1EE793C0D6C9B9200FEA3BA /* ThreadingPthreads.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadingPthreads.cpp; sourceTree = ""; }; @@ -926,6 +932,8 @@ isa = PBXGroup; children = ( E195678E09E7CF1200B89D13 /* icu */, + E1A862AA0D7EBB7D001EC6AA /* Collator.h */, + E1A862D50D7F2B5C001EC6AA /* CollatorDefault.cpp */, E195679409E7CF1200B89D13 /* Unicode.h */, E1EF79A80CE97BA60088D500 /* UTF8.cpp */, E1EF79A90CE97BA60088D500 /* UTF8.h */, @@ -936,6 +944,7 @@ E195678E09E7CF1200B89D13 /* icu */ = { isa = PBXGroup; children = ( + E1A862A80D7EBB76001EC6AA /* CollatorICU.cpp */, E195678F09E7CF1200B89D13 /* UnicodeIcu.h */, ); path = icu; @@ -1079,6 +1088,7 @@ 932F5B5C0822A1C700736975 /* ustring.h in Headers */, 14ABB36F099C076400E2A24F /* value.h in Headers */, E1EE79280D6C964500FEA3BA /* Locker.h in Headers */, + E1A862AB0D7EBB7D001EC6AA /* Collator.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1329,6 +1339,8 @@ 937013480CA97E0E00FA14D3 /* pcre_ucp_searchfuncs.cpp in Sources */, 93E26BD408B1514100F85226 /* pcre_xclass.cpp in Sources */, E1EE793D0D6C9B9200FEA3BA /* ThreadingPthreads.cpp in Sources */, + E1A862A90D7EBB76001EC6AA /* CollatorICU.cpp in Sources */, + E1A862D60D7F2B5C001EC6AA /* CollatorDefault.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/JavaScriptCore/JavaScriptCoreSources.bkl b/JavaScriptCore/JavaScriptCoreSources.bkl index adcb1da27bb477edc3a5830e082dfaf1099724a2..f7b09d15f50fef8145193777784baf26e7a7c3e5 100644 --- a/JavaScriptCore/JavaScriptCoreSources.bkl +++ b/JavaScriptCore/JavaScriptCoreSources.bkl @@ -100,6 +100,8 @@ Source files for JSCore. wtf/HashTable.cpp wtf/TCSystemAlloc.cpp wtf/ThreadingNone.cpp + wtf/unicode/CollatorDefault.cpp + wtf/unicode/icu/CollatorICU.cpp wtf/unicode/UTF8.cpp diff --git a/JavaScriptCore/kjs/string_object.cpp b/JavaScriptCore/kjs/string_object.cpp index 04d8ebb7e2e1e145c6d12d7d61f05ee542acf868..0032c5ccea194df0991761bca18cd7f11d27ea79 100644 --- a/JavaScriptCore/kjs/string_object.cpp +++ b/JavaScriptCore/kjs/string_object.cpp @@ -30,13 +30,7 @@ #include "operations.h" #include "regexp_object.h" #include -#include - -#if PLATFORM(CF) -#include -#elif PLATFORM(WIN_OS) -#include -#endif +#include using namespace WTF; @@ -294,26 +288,10 @@ static inline UString substituteBackreferences(const UString &replacement, const return substitutedReplacement; } + static inline int localeCompare(const UString& a, const UString& b) { -#if PLATFORM(WIN_OS) - int retval = CompareStringW(LOCALE_USER_DEFAULT, 0, - reinterpret_cast(a.data()), a.size(), - reinterpret_cast(b.data()), b.size()); - return !retval ? retval : retval - 2; -#elif PLATFORM(CF) - CFStringRef sa = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, reinterpret_cast(a.data()), a.size(), kCFAllocatorNull); - CFStringRef sb = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, reinterpret_cast(b.data()), b.size(), kCFAllocatorNull); - - int retval = CFStringCompare(sa, sb, kCFCompareLocalized); - - CFRelease(sa); - CFRelease(sb); - - return retval; -#else - return compare(a, b); -#endif + return Collator::userDefault()->collate(reinterpret_cast(a.data()), a.size(), reinterpret_cast(b.data()), b.size()); } static JSValue *replace(ExecState *exec, StringImp* sourceVal, JSValue *pattern, JSValue *replacement) diff --git a/JavaScriptCore/wtf/Threading.h b/JavaScriptCore/wtf/Threading.h index 1cb52729a408bb8432dcdb2590ce4ec6d628ac14..63d828668755afec0c1a775c781adf0c74d522c6 100644 --- a/JavaScriptCore/wtf/Threading.h +++ b/JavaScriptCore/wtf/Threading.h @@ -91,6 +91,12 @@ class QWaitCondition; #include +// For portability, we do not use thread-safe statics natively supported by some compilers (e.g. gcc). +#define AtomicallyInitializedStatic(T, name) \ + WTF::atomicallyInitializedStaticMutex->lock(); \ + static T name; \ + WTF::atomicallyInitializedStaticMutex->unlock(); + namespace WTF { typedef uint32_t ThreadIdentifier; @@ -232,9 +238,13 @@ private: void initializeThreading(); +extern Mutex* atomicallyInitializedStaticMutex; + #if !PLATFORM(GTK) inline void initializeThreading() { + if (!atomicallyInitializedStaticMutex) + atomicallyInitializedStaticMutex = new Mutex; } #endif diff --git a/JavaScriptCore/wtf/ThreadingGtk.cpp b/JavaScriptCore/wtf/ThreadingGtk.cpp index a5de7a2c546c6743eb87099e0df264765e1bc8f0..fd87fce333d8115ef8c9858d69b78116a3489ba4 100644 --- a/JavaScriptCore/wtf/ThreadingGtk.cpp +++ b/JavaScriptCore/wtf/ThreadingGtk.cpp @@ -36,10 +36,15 @@ namespace WTF { +Mutex* atomicallyInitializedStaticMutex; + void initializeThreading() { - if (!g_thread_supported()) + if (!g_thread_supported()) { g_thread_init(NULL); + ASSERT(!atomicallyInitializedStaticMutex); + atomicallyInitializedStaticMutex = new Mutex; + } ASSERT(g_thread_supported()); } diff --git a/JavaScriptCore/wtf/ThreadingNone.cpp b/JavaScriptCore/wtf/ThreadingNone.cpp index 2c208649a54f2b8dac662fbb427a27a672fc02b7..a06b5ba3322aac7473cd89460046e2499f89c9e4 100644 --- a/JavaScriptCore/wtf/ThreadingNone.cpp +++ b/JavaScriptCore/wtf/ThreadingNone.cpp @@ -31,6 +31,8 @@ namespace WTF { +Mutex* atomicallyInitializedStaticMutex; + ThreadIdentifier createThread(ThreadFunction, void*) { return 0; } int waitForThreadCompletion(ThreadIdentifier, void**) { return 0; } void detachThread(ThreadIdentifier) { } diff --git a/JavaScriptCore/wtf/ThreadingPthreads.cpp b/JavaScriptCore/wtf/ThreadingPthreads.cpp index 2fea5ba7df3074c032283236f446ccf6b76111ea..edd311959c9e673fbe98d427df94a2aab86314f5 100644 --- a/JavaScriptCore/wtf/ThreadingPthreads.cpp +++ b/JavaScriptCore/wtf/ThreadingPthreads.cpp @@ -35,6 +35,8 @@ namespace WTF { +Mutex* atomicallyInitializedStaticMutex; + static Mutex& threadMapMutex() { static Mutex mutex; diff --git a/JavaScriptCore/wtf/ThreadingWin.cpp b/JavaScriptCore/wtf/ThreadingWin.cpp index c946313869110169b04a65776608a21d4a69b2be..7bff7bdca3a4c3831cbfd4160282b0a857ff8976 100644 --- a/JavaScriptCore/wtf/ThreadingWin.cpp +++ b/JavaScriptCore/wtf/ThreadingWin.cpp @@ -68,6 +68,8 @@ namespace WTF { +Mutex* atomicallyInitializedStaticMutex; + static Mutex& threadMapMutex() { static Mutex mutex; diff --git a/JavaScriptCore/wtf/unicode/Collator.h b/JavaScriptCore/wtf/unicode/Collator.h new file mode 100644 index 0000000000000000000000000000000000000000..f04779dd7d356150c17270e443b822ab26196ed5 --- /dev/null +++ b/JavaScriptCore/wtf/unicode/Collator.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WTF_Collator_h +#define WTF_Collator_h + +#include +#include +#include + +#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION +struct UCollator; +#endif + +namespace WTF { + + class Collator : Noncopyable { + public: + enum Result { Equal = 0, Greater = 1, Less = -1 }; + + Collator(const char* locale); // Parsing is lenient; e.g. language identifiers (such as "en-US") are accepted, too. + ~Collator(); + void setOrderLowerFirst(bool); + + static std::auto_ptr userDefault(); + + Result collate(const ::UChar*, size_t, const ::UChar*, size_t) const; + + private: +#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION + void createCollator() const; + void releaseCollator(); + mutable UCollator* m_collator; +#endif + char* m_locale; + bool m_lowerFirst; + }; +} + +using WTF::Collator; + +#endif diff --git a/JavaScriptCore/wtf/unicode/CollatorDefault.cpp b/JavaScriptCore/wtf/unicode/CollatorDefault.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e72ff2aa422762ff6ae569f62c3fd77c7d246016 --- /dev/null +++ b/JavaScriptCore/wtf/unicode/CollatorDefault.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "Collator.h" + +#if !USE(ICU_UNICODE) || UCONFIG_NO_COLLATION + +namespace WTF { + +Collator::Collator(const char*) +{ +} + +Collator::~Collator() +{ +} + +void Collator::setOrderLowerFirst(bool) +{ +} + +std::auto_ptr Collator::userDefault() +{ + return std::auto_ptr(new Collator); +} + +// A default implementation for platforms that lack Unicode-aware collation. +Collator::Result Collator::collate(const UChar* lhs, size_t lhsLength, const UChar* rhs, size_t rhsLength) const +{ + int lmin = lhsLength < rhsLength ? lhsLength : rhsLength; + int l = 0; + while (l < lmin && *lhs == *rhs) { + lhs++; + rhs++; + l++; + } + + if (l < lmin) + return (*lhs > *rhs) ? Greater : Less; + + if (lhsLength == rhsLength) + return Equal; + + return (lhsLength > rhsLength) ? Greater : Less; +} + +} + +#endif diff --git a/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp b/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b7f0570c2ebe7ac728e38f026c844379172abefb --- /dev/null +++ b/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "Collator.h" + +#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION + +#include "Assertions.h" +#include "Threading.h" +#include + +#if PLATFORM(DARWIN) +#include +#endif + +namespace WTF { + +static UCollator* cachedCollator; +static Mutex& cachedCollatorMutex() +{ + AtomicallyInitializedStatic(Mutex, mutex); + return mutex; +} + +Collator::Collator(const char* locale) + : m_collator(0) + , m_locale(locale ? strdup(locale) : 0) + , m_lowerFirst(false) +{ +} + +std::auto_ptr Collator::userDefault() +{ +#if PLATFORM(DARWIN) + // Mac OS X doesn't set UNIX locale to match user-selected one, so ICU default doesn't work. + CFStringRef collationOrder = (CFStringRef)CFPreferencesCopyValue(CFSTR("AppleCollationOrder"), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + char buf[256]; + if (collationOrder) { + CFStringGetCString(collationOrder, buf, sizeof(buf), kCFStringEncodingASCII); + CFRelease(collationOrder); + return std::auto_ptr(new Collator(buf)); + } else + return std::auto_ptr(new Collator("")); +#else + return std::auto_ptr(new Collator(0)); +#endif +} + +Collator::~Collator() +{ + releaseCollator(); + free(m_locale); +} + +void Collator::setOrderLowerFirst(bool lowerFirst) +{ + m_lowerFirst = lowerFirst; +} + +Collator::Result Collator::collate(const UChar* lhs, size_t lhsLength, const UChar* rhs, size_t rhsLength) const +{ + if (!m_collator) + createCollator(); + + return static_cast(ucol_strcoll(m_collator, lhs, lhsLength, rhs, rhsLength)); +} + +void Collator::createCollator() const +{ + ASSERT(!m_collator); + UErrorCode status = U_ZERO_ERROR; + + { + Locker lock(cachedCollatorMutex()); + if (cachedCollator) { + const char* cachedCollatorLocale = ucol_getLocaleByType(cachedCollator, ULOC_REQUESTED_LOCALE, &status); + ASSERT(U_SUCCESS(status)); + + UColAttributeValue cachedCollatorLowerFirst = ucol_getAttribute(cachedCollator, UCOL_CASE_FIRST, &status); + ASSERT(U_SUCCESS(status)); + + if (0 == strcmp(cachedCollatorLocale, m_locale) && ((UCOL_LOWER_FIRST == cachedCollatorLowerFirst && m_lowerFirst) || (UCOL_UPPER_FIRST == cachedCollatorLowerFirst && !m_lowerFirst))) { + m_collator = cachedCollator; + cachedCollator = 0; + return; + } + } + } + + m_collator = ucol_open(m_locale, &status); + if (U_FAILURE(status)) { + status = U_ZERO_ERROR; + m_collator = ucol_open("", &status); // Fallback to Unicode Collation Algorithm. + } + ASSERT(U_SUCCESS(status)); + + ucol_setAttribute(m_collator, UCOL_CASE_FIRST, m_lowerFirst ? UCOL_LOWER_FIRST : UCOL_UPPER_FIRST, &status); + ASSERT(U_SUCCESS(status)); +} + +void Collator::releaseCollator() +{ + { + Locker lock(cachedCollatorMutex()); + if (cachedCollator) + ucol_close(cachedCollator); + cachedCollator = m_collator; + m_collator = 0; + } +} + +} + +#endif diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog index 50d880a33a4b8f68d1bfdbd3b9bf267de16906cc..347fc6452a5415be160d70e7deffa6c079783b72 100644 --- a/LayoutTests/ChangeLog +++ b/LayoutTests/ChangeLog @@ -1,3 +1,15 @@ +2008-03-06 Alexey Proskuryakov + + Reviewed by Darin. + + Need to create a Collator abstraction for WebCore and JavaScriptCore + + Added a test to verify that collation is indeed locale-sensitive, and not just UCA. + + * fast/xsl/sort-locale-expected.txt: Added. + * fast/xsl/sort-locale.xml: Added. + * fast/xsl/sort-locale.xsl: Added. + 2008-03-06 Dan Bernstein Reviewed by Adele. diff --git a/LayoutTests/fast/xsl/sort-locale-expected.txt b/LayoutTests/fast/xsl/sort-locale-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..b247571512d1bcd95d3a97bda3912331e2b05db3 --- /dev/null +++ b/LayoutTests/fast/xsl/sort-locale-expected.txt @@ -0,0 +1,18 @@ +en + +peach +péché +pêche +sin +fr + +peach +pêche +péché +sin +fr-CA + +peach +pêche +péché +sin diff --git a/LayoutTests/fast/xsl/sort-locale.xml b/LayoutTests/fast/xsl/sort-locale.xml new file mode 100644 index 0000000000000000000000000000000000000000..800bb95ed9c76acf308abbeeec66f28b1a151c2b --- /dev/null +++ b/LayoutTests/fast/xsl/sort-locale.xml @@ -0,0 +1,8 @@ + + + + peach + péché + sin + pêche + diff --git a/LayoutTests/fast/xsl/sort-locale.xsl b/LayoutTests/fast/xsl/sort-locale.xsl new file mode 100644 index 0000000000000000000000000000000000000000..8b545fa31783bb271cc03bf8e94aa7841165d08b --- /dev/null +++ b/LayoutTests/fast/xsl/sort-locale.xsl @@ -0,0 +1,40 @@ + + + + + + +

en

+ + + + + + + +
+

fr

+ + + + + + + +
+

fr-CA

+ + + + + + + +
+ + +
+
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog index 34c09571e0a026ec16d9017bdf96833f11a976e7..1a034dca3b0affb9edb0b181216a1e66c3bd9ad5 100644 --- a/WebCore/ChangeLog +++ b/WebCore/ChangeLog @@ -1,3 +1,14 @@ +2008-03-05 Alexey Proskuryakov + + Reviewed by Darin. + + Need to create a Collator abstraction for WebCore and JavaScriptCore + + * ForwardingHeaders/wtf/unicode/Collator.h: Added. + * xml/XSLTUnicodeSort.cpp: + (WebCore::xsltUnicodeSortFunction): + * xml/XSLTUnicodeSort.h: + 2008-03-06 Darin Adler Reviewed by Mitz. diff --git a/WebCore/ForwardingHeaders/wtf/unicode/Collator.h b/WebCore/ForwardingHeaders/wtf/unicode/Collator.h new file mode 100644 index 0000000000000000000000000000000000000000..8f341a11e8a7cd55e815090696db56a8202280f1 --- /dev/null +++ b/WebCore/ForwardingHeaders/wtf/unicode/Collator.h @@ -0,0 +1 @@ +#include diff --git a/WebCore/xml/XSLTUnicodeSort.cpp b/WebCore/xml/XSLTUnicodeSort.cpp index e1ecdc4becd616cd4f4a2a6993c1478b5c257a1b..ed66112175ca4da57d81a3ac1f28f4e1d08fd240 100644 --- a/WebCore/xml/XSLTUnicodeSort.cpp +++ b/WebCore/xml/XSLTUnicodeSort.cpp @@ -31,15 +31,12 @@ #if ENABLE(XSLT) +#include "PlatformString.h" + #include #include -#if USE(ICU_UNICODE) -#include -#include -#include -#define WTF_USE_ICU_COLLATION !UCONFIG_NO_COLLATION -#endif +#include #if PLATFORM(MAC) #include "SoftLinking.h" @@ -122,14 +119,6 @@ void xsltUnicodeSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts, in xmlXPathObjectPtr tmp; int tempstype[XSLT_MAX_SORT], temporder[XSLT_MAX_SORT]; -#if USE(ICU_COLLATION) - UCollator *coll = 0; - UConverter *conv; - UErrorCode status; - UChar *target,*target2; - int targetlen, target2len; -#endif - if ((ctxt == NULL) || (sorts == NULL) || (nbsorts <= 0) || (nbsorts >= XSLT_MAX_SORT)) return; @@ -201,28 +190,12 @@ void xsltUnicodeSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts, in if (results == NULL) return; -#if USE(ICU_COLLATION) - status = U_ZERO_ERROR; - conv = ucnv_open("UTF8", &status); - if (U_FAILURE(status)) - xsltTransformError(ctxt, NULL, NULL, "xsltICUSortFunction: Error opening converter\n"); - - if (comp->has_lang) - coll = ucol_open((const char*)comp->lang, &status); - if (U_FAILURE(status) || !comp->has_lang) { - status = U_ZERO_ERROR; - coll = ucol_open("en", &status); - } - if (U_FAILURE(status)) - xsltTransformError(ctxt, NULL, NULL, "xsltICUSortFunction: Error opening collator\n"); - - if (comp->lower_first) - ucol_setAttribute(coll,UCOL_CASE_FIRST,UCOL_LOWER_FIRST,&status); - else - ucol_setAttribute(coll,UCOL_CASE_FIRST,UCOL_UPPER_FIRST,&status); - if (U_FAILURE(status)) - xsltTransformError(ctxt, NULL, NULL, "xsltICUSortFunction: Error setting collator attribute\n"); -#endif + // We are passing a language identifier to a function that expects a locale identifier. + // The implementation of Collator should be lenient, and accept both "en-US" and "en_US", for example. + // This lets an author to really specify sorting rules, e.g. "de_DE@collation=phonebook", which isn't + // possible with language alone. + Collator collator(comp->has_lang ? (const char*)comp->lang : "en"); + collator.setOrderLowerFirst(comp->lower_first); /* Shell's sort of node-set */ for (incr = len / 2; incr > 0; incr /= 2) { @@ -253,20 +226,9 @@ void xsltUnicodeSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts, in tst = 1; else tst = -1; } else { -#if USE(ICU_COLLATION) - targetlen = xmlStrlen(results[j]->stringval) + 1; - target2len = xmlStrlen(results[j + incr]->stringval) + 1; - target = (UChar*)xmlMalloc(targetlen * sizeof(UChar)); - target2 = (UChar*)xmlMalloc(target2len * sizeof(UChar)); - targetlen = ucnv_toUChars(conv, target, targetlen, (const char*)results[j]->stringval, -1, &status); - target2len = ucnv_toUChars(conv, target2, target2len, (const char*)results[j+incr]->stringval, -1, &status); - tst = ucol_strcoll(coll, target, u_strlen(target), target2, u_strlen(target2)); - xmlFree(target); - xmlFree(target2); -#else - tst = xmlStrcmp(results[j]->stringval, - results[j + incr]->stringval); -#endif + String str1 = String::fromUTF8((const char*)results[j]->stringval); + String str2 = String::fromUTF8((const char*)results[j + incr]->stringval); + tst = collator.collate(str1.characters(), str1.length(), str2.characters(), str2.length()); } if (descending) tst = -tst; @@ -319,20 +281,9 @@ void xsltUnicodeSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts, in tst = 1; else tst = -1; } else { -#if USE(ICU_COLLATION) - targetlen = xmlStrlen(res[j]->stringval) + 1; - target2len = xmlStrlen(res[j + incr]->stringval) + 1; - target = (UChar*)xmlMalloc(targetlen * sizeof(UChar)); - target2 = (UChar*)xmlMalloc(target2len * sizeof(UChar)); - targetlen = ucnv_toUChars(conv, target, targetlen, (const char*)res[j]->stringval, -1, &status); - target2len = ucnv_toUChars(conv, target2, target2len, (const char*)res[j+incr]->stringval, -1, &status); - tst = ucol_strcoll(coll, target, u_strlen(target), target2, u_strlen(target2)); - xmlFree(target); - xmlFree(target2); -#else - tst = xmlStrcmp(res[j]->stringval, - res[j + incr]->stringval); -#endif + String str1 = String::fromUTF8((const char*)res[j]->stringval); + String str2 = String::fromUTF8((const char*)res[j + incr]->stringval); + tst = collator.collate(str1.characters(), str1.length(), str2.characters(), str2.length()); } if (desc) tst = -tst; @@ -376,11 +327,6 @@ void xsltUnicodeSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts, in } } -#if USE(ICU_COLLATION) - ucol_close(coll); - ucnv_close(conv); -#endif - for (j = 0; j < nbsorts; j++) { comp = static_cast(sorts[j]->psvi); if (tempstype[j] == 1) { diff --git a/WebCore/xml/XSLTUnicodeSort.h b/WebCore/xml/XSLTUnicodeSort.h index ff5b2537346482e4edd790de66748000141d2cb1..c8d395b9c0937f3a238409438d6b524bd357e140 100644 --- a/WebCore/xml/XSLTUnicodeSort.h +++ b/WebCore/xml/XSLTUnicodeSort.h @@ -28,8 +28,6 @@ #ifndef XSLTUnicodeSort_h #define XSLTUnicodeSort_h -// FIXME: Only works as advertised for ICU with collation support enabled yet, falls back on binary comparison otherwise.. -// We need to make an abstraction for Unicode collation to implement this for other libraries. #if ENABLE(XSLT) #include