Reviewed by Maciej.
authorap@webkit.org <ap@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 23 Nov 2007 08:29:59 +0000 (08:29 +0000)
committerap@webkit.org <ap@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 23 Nov 2007 08:29:59 +0000 (08:29 +0000)
        http://bugs.webkit.org/show_bug.cgi?id=16077
        <rdar://problem/5609785> XSLT processor <xsl:sort> algorithm is incompatible with other
        browser implementations

        Test: fast/xsl/sort-unicode.xml

        * xml/XSLTProcessor.cpp:
        (WebCore::XSLTProcessor::transformToString): Set a custom sort function.

        * xml/XSLTUnicodeSort.cpp: Added.
        (init_xsltTransformError):
        (xsltTransformError):
        (WebCore::xsltUnicodeSortFunction):
        * xml/XSLTUnicodeSort.h: Added.
        ICU-based implementation of xsl:sort, using an example from libxslt distribution.
        Only minimal coding style fixes to ease synchronization with upstream in the future.

        * icu/unicode/ucol.h: Added.
        * icu/unicode/uset.h: Added.
        Taken from ICU 3.2

        * WebCore.pro:
        * WebCore.vcproj/WebCore.vcproj:
        * WebCore.xcodeproj/project.pbxproj:
        * WebCoreSources.bkl:
        Added XSLTUnicodeSort.cpp.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@27984 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/xsl/sort-unicode-expected.txt [new file with mode: 0644]
LayoutTests/fast/xsl/sort-unicode.xml [new file with mode: 0644]
LayoutTests/fast/xsl/sort-unicode.xsl [new file with mode: 0644]
WebCore/ChangeLog
WebCore/WebCore.pro
WebCore/WebCore.vcproj/WebCore.vcproj
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/WebCoreSources.bkl
WebCore/icu/unicode/ucol.h [new file with mode: 0644]
WebCore/icu/unicode/uset.h [new file with mode: 0644]
WebCore/xml/XSLTProcessor.cpp
WebCore/xml/XSLTUnicodeSort.cpp [new file with mode: 0644]
WebCore/xml/XSLTUnicodeSort.h [new file with mode: 0644]

index 1e5d6bb440a913297ac0359ebe047527364dae69..8d8a15daab66f5cd014a2e528ccb61eb171e771f 100644 (file)
@@ -1,3 +1,15 @@
+2007-11-23  Alexey Proskuryakov  <ap@webkit.org>
+
+        Reviewed by Maciej.
+
+        http://bugs.webkit.org/show_bug.cgi?id=16077
+        <rdar://problem/5609785> XSLT processor <xsl:sort> algorithm is incompatible with other
+        browser implementations
+
+        * fast/xsl/sort-unicode-expected.txt: Added.
+        * fast/xsl/sort-unicode.xml: Added.
+        * fast/xsl/sort-unicode.xsl: Added.
+
 2007-11-22  Dan Bernstein  <mitz@apple.com>
 
         Reviewed by Maciej Stachowiak.
diff --git a/LayoutTests/fast/xsl/sort-unicode-expected.txt b/LayoutTests/fast/xsl/sort-unicode-expected.txt
new file mode 100644 (file)
index 0000000..c8c961c
--- /dev/null
@@ -0,0 +1,20 @@
+lower-first
+
+Title  Artist
+abbies title   a
+Angies Title   A
+brents Title   b
+Brads Title    B
+ye     е
+yo     ё
+zh     ж
+upper-first
+
+Title  Artist
+Angies Title   A
+abbies title   a
+Brads Title    B
+brents Title   b
+ye     е
+yo     ё
+zh     ж
diff --git a/LayoutTests/fast/xsl/sort-unicode.xml b/LayoutTests/fast/xsl/sort-unicode.xml
new file mode 100644 (file)
index 0000000..45d8f30
--- /dev/null
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<?xml-stylesheet type="text/xsl" href="sort-unicode.xsl"?>
+<catalog>
+    <cd>
+        <title>Brads Title</title>
+        <artist>B</artist>
+        <country>USA</country>
+        <company>Columbia</company>
+        <price>10.90</price>
+        <year>1985</year>
+    </cd>
+    <cd>
+        <title>brents Title</title>
+        <artist>b</artist>
+        <country>UK</country>
+        <company>CBS Records</company>
+        <price>9.90</price>
+        <year>1988</year>
+    </cd>
+    <cd>
+        <title>Angies Title</title>
+        <artist>A</artist>
+        <country>USA</country>
+        <company>RCA</company>
+        <price>9.90</price>
+        <year>1982</year>
+    </cd>
+    <cd>
+        <title>abbies title</title>
+        <artist>a</artist>
+        <country>UK</country>
+        <company>Virgin records</company>
+        <price>10.20</price>
+        <year>1990</year>
+    </cd>
+    <cd>
+        <title>ye</title>
+        <artist>е</artist>
+        <country>UK</country>
+        <company>Virgin records</company>
+        <price>10.20</price>
+        <year>1990</year>
+    </cd>
+    <cd>
+        <title>yo</title>
+        <artist>ё</artist>
+        <country>UK</country>
+        <company>Virgin records</company>
+        <price>10.20</price>
+        <year>1990</year>
+    </cd>
+    <cd>
+        <title>zh</title>
+        <artist>ж</artist>
+        <country>UK</country>
+        <company>Virgin records</company>
+        <price>10.20</price>
+        <year>1990</year>
+    </cd>
+</catalog>
diff --git a/LayoutTests/fast/xsl/sort-unicode.xsl b/LayoutTests/fast/xsl/sort-unicode.xsl
new file mode 100644 (file)
index 0000000..d3b05ef
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="/">
+  <html>
+  <body>
+    <script>
+      if (window.layoutTestController)
+        layoutTestController.dumpAsText();
+    </script>
+    <h2>lower-first</h2>
+    <table border="1">
+      <tr bgcolor="#9acd32">
+        <th>Title</th>
+        <th>Artist</th>
+      </tr>
+      <xsl:for-each select="catalog/cd">
+      <xsl:sort select="artist" data-type="text" order="ascending" case-order="lower-first" />
+      <tr>
+        <td><xsl:value-of select="title"/></td>
+        <td><xsl:value-of select="artist"/></td>
+      </tr>
+      </xsl:for-each>
+    </table>
+    <h2>upper-first</h2>
+    <table border="1">
+      <tr bgcolor="#9acd32">
+        <th>Title</th>
+        <th>Artist</th>
+      </tr>
+      <xsl:for-each select="catalog/cd">
+      <xsl:sort select="artist" data-type="text" order="ascending" case-order="upper-first" />
+      <tr>
+        <td><xsl:value-of select="title"/></td>
+        <td><xsl:value-of select="artist"/></td>
+      </tr>
+      </xsl:for-each>
+    </table>
+  </body>
+  </html>
+</xsl:template>
+</xsl:stylesheet>
index d9511bee78f714e9d60fbefbadafc5c1f1a7ea48..7fe88cb80e3e24a199749299199db584bea87ddb 100644 (file)
@@ -1,3 +1,34 @@
+2007-11-23  Alexey Proskuryakov  <ap@webkit.org>
+
+        Reviewed by Maciej.
+
+        http://bugs.webkit.org/show_bug.cgi?id=16077
+        <rdar://problem/5609785> XSLT processor <xsl:sort> algorithm is incompatible with other
+        browser implementations
+
+        Test: fast/xsl/sort-unicode.xml
+
+        * xml/XSLTProcessor.cpp:
+        (WebCore::XSLTProcessor::transformToString): Set a custom sort function.
+
+        * xml/XSLTUnicodeSort.cpp: Added.
+        (init_xsltTransformError):
+        (xsltTransformError):
+        (WebCore::xsltUnicodeSortFunction):
+        * xml/XSLTUnicodeSort.h: Added.
+        ICU-based implementation of xsl:sort, using an example from libxslt distribution.
+        Only minimal coding style fixes to ease synchronization with upstream in the future.
+
+        * icu/unicode/ucol.h: Added.
+        * icu/unicode/uset.h: Added.
+        Taken from ICU 3.2
+
+        * WebCore.pro:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * WebCoreSources.bkl:
+        Added XSLTUnicodeSort.cpp.
+
 2007-11-22  Alexey Proskuryakov  <ap@webkit.org>
 
         Reviewed by Maciej.
index 39265aca5c6f74f5332cd0344e96bc11f56c14e5..afd1b8c50b9cfeba2c497e5126c3583c48d76fab 100644 (file)
@@ -822,6 +822,7 @@ SOURCES += \
     xml/XSLImportRule.cpp \
     xml/XSLStyleSheet.cpp \
     xml/XSLTExtensions.cpp \
+    xml/XSLTUnicodeSort.cpp \
     xml/XSLTProcessor.cpp
 
 gtk-port {
index 01e5c8cc407113cb048244e2b6b6679a8e065c65..cc7221991e9887c1a4f4f129599052f41e866041 100644 (file)
                                RelativePath="..\xml\XSLTProcessor.h"\r
                                >\r
                        </File>\r
+                       <File\r
+                               RelativePath="..\xml\XSLTUnicodeSort.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\xml\XSLTUnicodeSort.h"\r
+                               >\r
+                       </File>\r
                </Filter>\r
                <Filter\r
                        Name="dom"\r
index f48769db110e10038a8951471fa77edd7dcb3a0e..2c9a306b36796c9bf94f2ae6f6f3fe8b70bd18ee 100644 (file)
                E14843D60A6754A6007E4D39 /* TextCodecMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E14843910A6752BF007E4D39 /* TextCodecMac.cpp */; };
                E15863990CD10B730066E2C9 /* TextCodecUserDefined.h in Headers */ = {isa = PBXBuildFile; fileRef = E15863970CD10B730066E2C9 /* TextCodecUserDefined.h */; };
                E158639A0CD10B730066E2C9 /* TextCodecUserDefined.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E15863980CD10B730066E2C9 /* TextCodecUserDefined.cpp */; };
+               E1BE512D0CF6C512002EA959 /* XSLTUnicodeSort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1BE512B0CF6C512002EA959 /* XSLTUnicodeSort.cpp */; };
+               E1BE512E0CF6C512002EA959 /* XSLTUnicodeSort.h in Headers */ = {isa = PBXBuildFile; fileRef = E1BE512C0CF6C512002EA959 /* XSLTUnicodeSort.h */; };
                E1E6EEA40B628DA8005F2F70 /* JSHTMLSelectElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1E6EEA30B628DA8005F2F70 /* JSHTMLSelectElement.cpp */; };
                E1E6EEA80B628DB3005F2F70 /* JSHTMLSelectElement.h in Headers */ = {isa = PBXBuildFile; fileRef = E1E6EEA70B628DB3005F2F70 /* JSHTMLSelectElement.h */; };
                E1EBBBD40AAC9B87001FE8E2 /* CSSCharsetRule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1EBBBD30AAC9B87001FE8E2 /* CSSCharsetRule.cpp */; };
                E14843910A6752BF007E4D39 /* TextCodecMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = TextCodecMac.cpp; path = mac/TextCodecMac.cpp; sourceTree = "<group>"; };
                E15863970CD10B730066E2C9 /* TextCodecUserDefined.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextCodecUserDefined.h; sourceTree = "<group>"; };
                E15863980CD10B730066E2C9 /* TextCodecUserDefined.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextCodecUserDefined.cpp; sourceTree = "<group>"; };
+               E1BE512B0CF6C512002EA959 /* XSLTUnicodeSort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XSLTUnicodeSort.cpp; sourceTree = "<group>"; };
+               E1BE512C0CF6C512002EA959 /* XSLTUnicodeSort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XSLTUnicodeSort.h; sourceTree = "<group>"; };
                E1E6EEA30B628DA8005F2F70 /* JSHTMLSelectElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLSelectElement.cpp; sourceTree = "<group>"; };
                E1E6EEA70B628DB3005F2F70 /* JSHTMLSelectElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = JSHTMLSelectElement.h; sourceTree = "<group>"; };
                E1EBBBD30AAC9B87001FE8E2 /* CSSCharsetRule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSCharsetRule.cpp; sourceTree = "<group>"; };
                                E1F1E82E0C3C2BB9006DB391 /* XSLTExtensions.h */,
                                BC06F24B06D18A7E004A6FA3 /* XSLTProcessor.cpp */,
                                BC06F24C06D18A7E004A6FA3 /* XSLTProcessor.h */,
+                               E1BE512B0CF6C512002EA959 /* XSLTUnicodeSort.cpp */,
+                               E1BE512C0CF6C512002EA959 /* XSLTUnicodeSort.h */,
                        );
                        path = xml;
                        sourceTree = "<group>";
                                BCB16C2D0979C3BD00467741 /* loader.h in Headers */,
                                93309DF8099E64920056E581 /* markup.h in Headers */,
                                93309E1E099E64920056E581 /* visible_units.h in Headers */,
+                               E1BE512E0CF6C512002EA959 /* XSLTUnicodeSort.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                0867D690FE84028FC02AAC07 /* Project object */ = {
                        isa = PBXProject;
                        buildConfigurationList = 149C284308902B11008A9EFC /* Build configuration list for PBXProject "WebCore" */;
-                       compatibilityVersion = "Xcode 2.4";
                        hasScannedForEncodings = 1;
                        knownRegions = (
                                English,
                                BCB16C2C0979C3BD00467741 /* loader.cpp in Sources */,
                                93309DF7099E64920056E581 /* markup.cpp in Sources */,
                                93309E1D099E64920056E581 /* visible_units.cpp in Sources */,
+                               E1BE512D0CF6C512002EA959 /* XSLTUnicodeSort.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index d1b4530da74103359b625f11d9f54a16b8fef7a9..9664d8274152cb061a37506f37a90c42c1c835d2 100644 (file)
@@ -740,6 +740,7 @@ This file contains the list of files needed to build WebCore.
         xml/XSLImportRule.cpp
         xml/XSLStyleSheet.cpp
         xml/XSLTExtensions.cpp
+        xml/XSLTUnicodeSort.cpp
         xml/XSLTProcessor.cpp
         xml/xmlhttprequest.cpp
     </set>
diff --git a/WebCore/icu/unicode/ucol.h b/WebCore/icu/unicode/ucol.h
new file mode 100644 (file)
index 0000000..cbfb1c3
--- /dev/null
@@ -0,0 +1,1219 @@
+/*
+*******************************************************************************
+* Copyright (c) 1996-2005, International Business Machines Corporation and others.
+* All Rights Reserved.
+*******************************************************************************
+*/
+
+#ifndef UCOL_H
+#define UCOL_H
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "unicode/unorm.h"
+#include "unicode/parseerr.h"
+#include "unicode/uloc.h"
+#include "unicode/uset.h"
+
+/**
+ * \file
+ * \brief C API: Collator 
+ *
+ * <h2> Collator C API </h2>
+ *
+ * The C API for Collator performs locale-sensitive
+ * string comparison. You use this service to build
+ * searching and sorting routines for natural language text.
+ * <em>Important: </em>The ICU collation service has been reimplemented 
+ * in order to achieve better performance and UCA compliance. 
+ * For details, see the 
+ * <a href="http://icu.sourceforge.net/cvs/icu/~checkout~/icuhtml/design/collation/ICU_collation_design.htm">
+ * collation design document</a>.
+ * <p>
+ * For more information about the collation service see 
+ * <a href="http://icu.sourceforge.net/icu/userguide/Collate_Intro.html">the users guide</a>.
+ * <p>
+ * Collation service provides correct sorting orders for most locales supported in ICU. 
+ * If specific data for a locale is not available, the orders eventually falls back
+ * to the <a href="http://www.unicode.org/unicode/reports/tr10/">UCA sort order</a>. 
+ * <p>
+ * Sort ordering may be customized by providing your own set of rules. For more on
+ * this subject see the 
+ * <a href="http://icu.sourceforge.net/icu/userguide/Collate_Customization.html">
+ * Collation customization</a> section of the users guide.
+ * <p>
+ * @see         UCollationResult
+ * @see         UNormalizationMode
+ * @see         UCollationStrength
+ * @see         UCollationElements
+ */
+
+/** A collation element iterator.
+*  For usage in C programs.
+*/
+struct collIterate;
+/** structure representing collation element iterator instance 
+ * @stable ICU 2.0
+ */
+typedef struct collIterate collIterate;
+
+/** A collator.
+*  For usage in C programs.
+*/
+struct UCollator;
+/** structure representing a collator object instance 
+ * @stable ICU 2.0
+ */
+typedef struct UCollator UCollator;
+
+
+/**
+ * UCOL_LESS is returned if source string is compared to be less than target
+ * string in the u_strcoll() method.
+ * UCOL_EQUAL is returned if source string is compared to be equal to target
+ * string in the u_strcoll() method.
+ * UCOL_GREATER is returned if source string is compared to be greater than
+ * target string in the u_strcoll() method.
+ * @see u_strcoll()
+ * <p>
+ * Possible values for a comparison result 
+ * @stable ICU 2.0
+ */
+typedef enum {
+  /** string a == string b */
+  UCOL_EQUAL    = 0,
+  /** string a > string b */
+  UCOL_GREATER    = 1,
+  /** string a < string b */
+  UCOL_LESS    = -1
+} UCollationResult ;
+
+
+/** Enum containing attribute values for controling collation behavior.
+ * Here are all the allowable values. Not every attribute can take every value. The only
+ * universal value is UCOL_DEFAULT, which resets the attribute value to the predefined  
+ * value for that locale 
+ * @stable ICU 2.0
+ */
+typedef enum {
+  /** accepted by most attributes */
+  UCOL_DEFAULT = -1,
+
+  /** Primary collation strength */
+  UCOL_PRIMARY = 0,
+  /** Secondary collation strength */
+  UCOL_SECONDARY = 1,
+  /** Tertiary collation strength */
+  UCOL_TERTIARY = 2,
+  /** Default collation strength */
+  UCOL_DEFAULT_STRENGTH = UCOL_TERTIARY,
+  UCOL_CE_STRENGTH_LIMIT,
+  /** Quaternary collation strength */
+  UCOL_QUATERNARY=3,
+  /** Identical collation strength */
+  UCOL_IDENTICAL=15,
+  UCOL_STRENGTH_LIMIT,
+
+  /** Turn the feature off - works for UCOL_FRENCH_COLLATION, 
+      UCOL_CASE_LEVEL, UCOL_HIRAGANA_QUATERNARY_MODE
+      & UCOL_DECOMPOSITION_MODE*/
+  UCOL_OFF = 16,
+  /** Turn the feature on - works for UCOL_FRENCH_COLLATION, 
+      UCOL_CASE_LEVEL, UCOL_HIRAGANA_QUATERNARY_MODE
+      & UCOL_DECOMPOSITION_MODE*/
+  UCOL_ON = 17,
+  
+  /** Valid for UCOL_ALTERNATE_HANDLING. Alternate handling will be shifted */
+  UCOL_SHIFTED = 20,
+  /** Valid for UCOL_ALTERNATE_HANDLING. Alternate handling will be non ignorable */
+  UCOL_NON_IGNORABLE = 21,
+
+  /** Valid for UCOL_CASE_FIRST - 
+      lower case sorts before upper case */
+  UCOL_LOWER_FIRST = 24,
+  /** upper case sorts before lower case */
+  UCOL_UPPER_FIRST = 25,
+
+  UCOL_ATTRIBUTE_VALUE_COUNT
+
+} UColAttributeValue;
+
+/**
+ * Base letter represents a primary difference.  Set comparison
+ * level to UCOL_PRIMARY to ignore secondary and tertiary differences.
+ * Use this to set the strength of a Collator object.
+ * Example of primary difference, "abc" &lt; "abd"
+ * 
+ * Diacritical differences on the same base letter represent a secondary
+ * difference.  Set comparison level to UCOL_SECONDARY to ignore tertiary
+ * differences. Use this to set the strength of a Collator object.
+ * Example of secondary difference, "ä" >> "a".
+ *
+ * Uppercase and lowercase versions of the same character represents a
+ * tertiary difference.  Set comparison level to UCOL_TERTIARY to include
+ * all comparison differences. Use this to set the strength of a Collator
+ * object.
+ * Example of tertiary difference, "abc" &lt;&lt;&lt; "ABC".
+ *
+ * Two characters are considered "identical" when they have the same
+ * unicode spellings.  UCOL_IDENTICAL.
+ * For example, "ä" == "ä".
+ *
+ * UCollationStrength is also used to determine the strength of sort keys 
+ * generated from UCollator objects
+ * These values can be now found in the UColAttributeValue enum.
+ * @stable ICU 2.0
+ **/
+typedef UColAttributeValue UCollationStrength;
+
+/** Attributes that collation service understands. All the attributes can take UCOL_DEFAULT
+ * value, as well as the values specific to each one. 
+ * @stable ICU 2.0
+ */
+typedef enum {
+     /** Attribute for direction of secondary weights - used in French.\ 
+      * Acceptable values are UCOL_ON, which results in secondary weights
+      * being considered backwards and UCOL_OFF which treats secondary
+      * weights in the order they appear.*/
+     UCOL_FRENCH_COLLATION, 
+     /** Attribute for handling variable elements.\ 
+      * Acceptable values are UCOL_NON_IGNORABLE (default)
+      * which treats all the codepoints with non-ignorable 
+      * primary weights in the same way,
+      * and UCOL_SHIFTED which causes codepoints with primary 
+      * weights that are equal or below the variable top value
+      * to be ignored on primary level and moved to the quaternary 
+      * level.*/
+     UCOL_ALTERNATE_HANDLING, 
+     /** Controls the ordering of upper and lower case letters.\ 
+      * Acceptable values are UCOL_OFF (default), which orders
+      * upper and lower case letters in accordance to their tertiary
+      * weights, UCOL_UPPER_FIRST which forces upper case letters to 
+      * sort before lower case letters, and UCOL_LOWER_FIRST which does 
+      * the opposite. */
+     UCOL_CASE_FIRST, 
+     /** Controls whether an extra case level (positioned before the third
+      * level) is generated or not.\ Acceptable values are UCOL_OFF (default), 
+      * when case level is not generated, and UCOL_ON which causes the case
+      * level to be generated.\ Contents of the case level are affected by
+      * the value of UCOL_CASE_FIRST attribute.\ A simple way to ignore 
+      * accent differences in a string is to set the strength to UCOL_PRIMARY
+      * and enable case level. */
+     UCOL_CASE_LEVEL,
+     /** Controls whether the normalization check and necessary normalizations
+      * are performed.\ When set to UCOL_OFF (default) no normalization check
+      * is performed.\ The correctness of the result is guaranteed only if the 
+      * input data is in so-called FCD form (see users manual for more info).\ 
+      * When set to UCOL_ON, an incremental check is performed to see whether the input data
+      * is in the FCD form.\ If the data is not in the FCD form, incremental 
+      * NFD normalization is performed. */
+     UCOL_NORMALIZATION_MODE, 
+     /** An alias for UCOL_NORMALIZATION_MODE attribute */
+     UCOL_DECOMPOSITION_MODE = UCOL_NORMALIZATION_MODE,
+     /** The strength attribute.\ Can be either UCOL_PRIMARY, UCOL_SECONDARY,
+      * UCOL_TERTIARY, UCOL_QUATERNARY or UCOL_IDENTICAL.\ The usual strength
+      * for most locales (except Japanese) is tertiary.\ Quaternary strength 
+      * is useful when combined with shifted setting for alternate handling
+      * attribute and for JIS x 4061 collation, when it is used to distinguish
+      * between Katakana  and Hiragana (this is achieved by setting the 
+      * UCOL_HIRAGANA_QUATERNARY mode to on.\ Otherwise, quaternary level
+      * is affected only by the number of non ignorable code points in
+      * the string.\ Identical strength is rarely useful, as it amounts 
+      * to codepoints of the NFD form of the string. */
+     UCOL_STRENGTH,  
+     /** when turned on, this attribute 
+      * positions Hiragana before all  
+      * non-ignorables on quaternary level
+      * This is a sneaky way to produce JIS
+      * sort order */     
+     UCOL_HIRAGANA_QUATERNARY_MODE,
+     /** when turned on, this attribute 
+      * generates a collation key
+      * for the numeric value of substrings
+      * of digits. This is a way to get '100' 
+      * to sort AFTER '2'.*/          
+     UCOL_NUMERIC_COLLATION, 
+     UCOL_ATTRIBUTE_COUNT
+} UColAttribute;
+
+/** Options for retrieving the rule string 
+ *  @stable ICU 2.0
+ */
+typedef enum {
+  /** Retrieve tailoring only */
+  UCOL_TAILORING_ONLY, 
+  /** Retrieve UCA rules and tailoring */
+  UCOL_FULL_RULES 
+} UColRuleOption ;
+
+/**
+ * Open a UCollator for comparing strings.
+ * The UCollator pointer is used in all the calls to the Collation 
+ * service. After finished, collator must be disposed of by calling
+ * {@link #ucol_close }.
+ * @param loc The locale containing the required collation rules. 
+ *            Special values for locales can be passed in - 
+ *            if NULL is passed for the locale, the default locale
+ *            collation rules will be used. If empty string ("") or
+ *            "root" are passed, UCA rules will be used.
+ * @param status A pointer to an UErrorCode to receive any errors
+ * @return A pointer to a UCollator, or 0 if an error occurred.
+ * @see ucol_openRules
+ * @see ucol_safeClone
+ * @see ucol_close
+ * @stable ICU 2.0
+ */
+U_STABLE UCollator* U_EXPORT2 
+ucol_open(const char *loc, UErrorCode *status);
+
+/**
+ * Produce an UCollator instance according to the rules supplied.
+ * The rules are used to change the default ordering, defined in the
+ * UCA in a process called tailoring. The resulting UCollator pointer
+ * can be used in the same way as the one obtained by {@link #ucol_strcoll }.
+ * @param rules A string describing the collation rules. For the syntax
+ *              of the rules please see users guide.
+ * @param rulesLength The length of rules, or -1 if null-terminated.
+ * @param normalizationMode The normalization mode: One of
+ *             UCOL_OFF     (expect the text to not need normalization),
+ *             UCOL_ON      (normalize), or
+ *             UCOL_DEFAULT (set the mode according to the rules)
+ * @param strength The default collation strength; one of UCOL_PRIMARY, UCOL_SECONDARY,
+ * UCOL_TERTIARY, UCOL_IDENTICAL,UCOL_DEFAULT_STRENGTH - can be also set in the rules.
+ * @param parseError  A pointer to UParseError to recieve information about errors
+ *                    occurred during parsing. This argument can currently be set
+ *                    to NULL, but at users own risk. Please provide a real structure.
+ * @param status A pointer to an UErrorCode to receive any errors
+ * @return A pointer to a UCollator.\ It is not guaranteed that NULL be returned in case
+ *         of error - please use status argument to check for errors.
+ * @see ucol_open
+ * @see ucol_safeClone
+ * @see ucol_close
+ * @stable ICU 2.0
+ */
+U_STABLE UCollator* U_EXPORT2 
+ucol_openRules( const UChar        *rules,
+                int32_t            rulesLength,
+                UColAttributeValue normalizationMode,
+                UCollationStrength strength,
+                UParseError        *parseError,
+                UErrorCode         *status);
+
+/** 
+ * Open a collator defined by a short form string.
+ * The structure and the syntax of the string is defined in the "Naming collators"
+ * section of the users guide: 
+ * http://icu.sourceforge.net/icu/userguide/Collate_Concepts.html#Naming_Collators
+ * Attributes are overriden by the subsequent attributes. So, for "S2_S3", final
+ * strength will be 3. 3066bis locale overrides individual locale parts.
+ * The call to this function is equivalent to a call to ucol_open, followed by a 
+ * series of calls to ucol_setAttribute and ucol_setVariableTop.
+ * @param definition A short string containing a locale and a set of attributes. 
+ *                   Attributes not explicitly mentioned are left at the default
+ *                   state for a locale.
+ * @param parseError if not NULL, structure that will get filled with error's pre
+ *                   and post context in case of error.
+ * @param forceDefaults if FALSE, the settings that are the same as the collator 
+ *                   default settings will not be applied (for example, setting
+ *                   French secondary on a French collator would not be executed). 
+ *                   If TRUE, all the settings will be applied regardless of the 
+ *                   collator default value. If the definition
+ *                   strings are to be cached, should be set to FALSE.
+ * @param status     Error code. Apart from regular error conditions connected to 
+ *                   instantiating collators (like out of memory or similar), this
+ *                   API will return an error if an invalid attribute or attribute/value
+ *                   combination is specified.
+ * @return           A pointer to a UCollator or 0 if an error occured (including an 
+ *                   invalid attribute).
+ * @see ucol_open
+ * @see ucol_setAttribute
+ * @see ucol_setVariableTop
+ * @see ucol_getShortDefinitionString
+ * @see ucol_normalizeShortDefinitionString
+ * @draft ICU 3.0
+ *
+ */
+U_CAPI UCollator* U_EXPORT2
+ucol_openFromShortString( const char *definition,
+                          UBool forceDefaults,
+                          UParseError *parseError,
+                          UErrorCode *status);
+
+/**
+ * Get a set containing the contractions defined by the collator. The set includes
+ * both the UCA contractions and the contractions defined by the collator. This set
+ * will contain only strings. If a tailoring explicitly suppresses contractions from 
+ * the UCA (like Russian), removed contractions will not be in the resulting set.
+ * @param coll collator 
+ * @param conts the set to hold the result. It gets emptied before
+ *              contractions are added. 
+ * @param status to hold the error code
+ * @return the size of the contraction set
+ *
+ * @draft ICU 3.0
+ */
+U_CAPI int32_t U_EXPORT2
+ucol_getContractions( const UCollator *coll,
+                  USet *conts,
+                  UErrorCode *status);
+
+
+/** 
+ * Close a UCollator.
+ * Once closed, a UCollator should not be used.\ Every open collator should
+ * be closed.\ Otherwise, a memory leak will result.
+ * @param coll The UCollator to close.
+ * @see ucol_open
+ * @see ucol_openRules
+ * @see ucol_safeClone
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2 
+ucol_close(UCollator *coll);
+
+/**
+ * Compare two strings.
+ * The strings will be compared using the options already specified.
+ * @param coll The UCollator containing the comparison rules.
+ * @param source The source string.
+ * @param sourceLength The length of source, or -1 if null-terminated.
+ * @param target The target string.
+ * @param targetLength The length of target, or -1 if null-terminated.
+ * @return The result of comparing the strings; one of UCOL_EQUAL,
+ * UCOL_GREATER, UCOL_LESS
+ * @see ucol_greater
+ * @see ucol_greaterOrEqual
+ * @see ucol_equal
+ * @stable ICU 2.0
+ */
+U_STABLE UCollationResult U_EXPORT2 
+ucol_strcoll(    const    UCollator    *coll,
+        const    UChar        *source,
+        int32_t            sourceLength,
+        const    UChar        *target,
+        int32_t            targetLength);
+
+/**
+ * Determine if one string is greater than another.
+ * This function is equivalent to {@link #ucol_strcoll } == UCOL_GREATER
+ * @param coll The UCollator containing the comparison rules.
+ * @param source The source string.
+ * @param sourceLength The length of source, or -1 if null-terminated.
+ * @param target The target string.
+ * @param targetLength The length of target, or -1 if null-terminated.
+ * @return TRUE if source is greater than target, FALSE otherwise.
+ * @see ucol_strcoll
+ * @see ucol_greaterOrEqual
+ * @see ucol_equal
+ * @stable ICU 2.0
+ */
+U_STABLE UBool U_EXPORT2 
+ucol_greater(const UCollator *coll,
+             const UChar     *source, int32_t sourceLength,
+             const UChar     *target, int32_t targetLength);
+
+/**
+ * Determine if one string is greater than or equal to another.
+ * This function is equivalent to {@link #ucol_strcoll } != UCOL_LESS
+ * @param coll The UCollator containing the comparison rules.
+ * @param source The source string.
+ * @param sourceLength The length of source, or -1 if null-terminated.
+ * @param target The target string.
+ * @param targetLength The length of target, or -1 if null-terminated.
+ * @return TRUE if source is greater than or equal to target, FALSE otherwise.
+ * @see ucol_strcoll
+ * @see ucol_greater
+ * @see ucol_equal
+ * @stable ICU 2.0
+ */
+U_STABLE UBool U_EXPORT2 
+ucol_greaterOrEqual(const UCollator *coll,
+                    const UChar     *source, int32_t sourceLength,
+                    const UChar     *target, int32_t targetLength);
+
+/**
+ * Compare two strings for equality.
+ * This function is equivalent to {@link #ucol_strcoll } == UCOL_EQUAL
+ * @param coll The UCollator containing the comparison rules.
+ * @param source The source string.
+ * @param sourceLength The length of source, or -1 if null-terminated.
+ * @param target The target string.
+ * @param targetLength The length of target, or -1 if null-terminated.
+ * @return TRUE if source is equal to target, FALSE otherwise
+ * @see ucol_strcoll
+ * @see ucol_greater
+ * @see ucol_greaterOrEqual
+ * @stable ICU 2.0
+ */
+U_STABLE UBool U_EXPORT2 
+ucol_equal(const UCollator *coll,
+           const UChar     *source, int32_t sourceLength,
+           const UChar     *target, int32_t targetLength);
+
+/**
+ * Compare two UTF-8 encoded trings.
+ * The strings will be compared using the options already specified.
+ * @param coll The UCollator containing the comparison rules.
+ * @param sIter The source string iterator.
+ * @param tIter The target string iterator.
+ * @return The result of comparing the strings; one of UCOL_EQUAL,
+ * UCOL_GREATER, UCOL_LESS
+ * @param status A pointer to an UErrorCode to receive any errors
+ * @see ucol_strcoll
+ * @stable ICU 2.6
+ */
+U_STABLE UCollationResult U_EXPORT2 
+ucol_strcollIter(  const    UCollator    *coll,
+                  UCharIterator *sIter,
+                  UCharIterator *tIter,
+                  UErrorCode *status);
+
+/**
+ * Get the collation strength used in a UCollator.
+ * The strength influences how strings are compared.
+ * @param coll The UCollator to query.
+ * @return The collation strength; one of UCOL_PRIMARY, UCOL_SECONDARY,
+ * UCOL_TERTIARY, UCOL_QUATERNARY, UCOL_IDENTICAL
+ * @see ucol_setStrength
+ * @stable ICU 2.0
+ */
+U_STABLE UCollationStrength U_EXPORT2 
+ucol_getStrength(const UCollator *coll);
+
+/**
+ * Set the collation strength used in a UCollator.
+ * The strength influences how strings are compared.
+ * @param coll The UCollator to set.
+ * @param strength The desired collation strength; one of UCOL_PRIMARY, 
+ * UCOL_SECONDARY, UCOL_TERTIARY, UCOL_QUATERNARY, UCOL_IDENTICAL, UCOL_DEFAULT
+ * @see ucol_getStrength
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2 
+ucol_setStrength(UCollator *coll,
+                 UCollationStrength strength);
+
+/**
+ * Get the display name for a UCollator.
+ * The display name is suitable for presentation to a user.
+ * @param objLoc The locale of the collator in question.
+ * @param dispLoc The locale for display.
+ * @param result A pointer to a buffer to receive the attribute.
+ * @param resultLength The maximum size of result.
+ * @param status A pointer to an UErrorCode to receive any errors
+ * @return The total buffer size needed; if greater than resultLength,
+ * the output was truncated.
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2 
+ucol_getDisplayName(    const    char        *objLoc,
+            const    char        *dispLoc,
+            UChar             *result,
+            int32_t         resultLength,
+            UErrorCode        *status);
+
+/**
+ * Get a locale for which collation rules are available.
+ * A UCollator in a locale returned by this function will perform the correct
+ * collation for the locale.
+ * @param index The index of the desired locale.
+ * @return A locale for which collation rules are available, or 0 if none.
+ * @see ucol_countAvailable
+ * @stable ICU 2.0
+ */
+U_STABLE const char* U_EXPORT2 
+ucol_getAvailable(int32_t index);
+
+/**
+ * Determine how many locales have collation rules available.
+ * This function is most useful as determining the loop ending condition for
+ * calls to {@link #ucol_getAvailable }.
+ * @return The number of locales for which collation rules are available.
+ * @see ucol_getAvailable
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2 
+ucol_countAvailable(void);
+
+#if !UCONFIG_NO_SERVICE
+/**
+ * Create a string enumerator of all locales for which a valid
+ * collator may be opened.
+ * @param status input-output error code
+ * @return a string enumeration over locale strings. The caller is
+ * responsible for closing the result.
+ * @draft ICU 3.0
+ */
+U_DRAFT UEnumeration* U_EXPORT2
+ucol_openAvailableLocales(UErrorCode *status);
+#endif
+
+/**
+ * Create a string enumerator of all possible keywords that are relevant to
+ * collation. At this point, the only recognized keyword for this
+ * service is "collation".
+ * @param status input-output error code
+ * @return a string enumeration over locale strings. The caller is
+ * responsible for closing the result.
+ * @draft ICU 3.0
+ */
+U_DRAFT UEnumeration* U_EXPORT2
+ucol_getKeywords(UErrorCode *status);
+
+/**
+ * Given a keyword, create a string enumeration of all values
+ * for that keyword that are currently in use.
+ * @param keyword a particular keyword as enumerated by
+ * ucol_getKeywords. If any other keyword is passed in, *status is set
+ * to U_ILLEGAL_ARGUMENT_ERROR.
+ * @param status input-output error code
+ * @return a string enumeration over collation keyword values, or NULL
+ * upon error. The caller is responsible for closing the result.
+ * @draft ICU 3.0
+ */
+U_DRAFT UEnumeration* U_EXPORT2
+ucol_getKeywordValues(const char *keyword, UErrorCode *status);
+
+/**
+ * Return the functionally equivalent locale for the given
+ * requested locale, with respect to given keyword, for the
+ * collation service.  If two locales return the same result, then
+ * collators instantiated for these locales will behave
+ * equivalently.  The converse is not always true; two collators
+ * may in fact be equivalent, but return different results, due to
+ * internal details.  The return result has no other meaning than
+ * that stated above, and implies nothing as to the relationship
+ * between the two locales.  This is intended for use by
+ * applications who wish to cache collators, or otherwise reuse
+ * collators when possible.  The functional equivalent may change
+ * over time.  For more information, please see the <a
+ * href="http://icu.sourceforge.net/icu/userguide/locale.html#services">
+ * Locales and Services</a> section of the ICU User Guide.
+ * @param result fillin for the functionally equivalent locale
+ * @param resultCapacity capacity of the fillin buffer
+ * @param keyword a particular keyword as enumerated by
+ * ucol_getKeywords.
+ * @param locale the requested locale
+ * @param isAvailable if non-NULL, pointer to a fillin parameter that
+ * indicates whether the requested locale was 'available' to the
+ * collation service. A locale is defined as 'available' if it
+ * physically exists within the collation locale data.
+ * @param status pointer to input-output error code
+ * @return the actual buffer size needed for the locale.  If greater
+ * than resultCapacity, the returned full name will be truncated and
+ * an error code will be returned.
+ * @draft ICU 3.0
+ */
+U_DRAFT int32_t U_EXPORT2
+ucol_getFunctionalEquivalent(char* result, int32_t resultCapacity,
+                             const char* keyword, const char* locale,
+                             UBool* isAvailable, UErrorCode* status);
+
+/**
+ * Get the collation rules from a UCollator.
+ * The rules will follow the rule syntax.
+ * @param coll The UCollator to query.
+ * @param length 
+ * @return The collation rules.
+ * @stable ICU 2.0
+ */
+U_STABLE const UChar* U_EXPORT2 
+ucol_getRules(    const    UCollator    *coll, 
+        int32_t            *length);
+
+/** Get the short definition string for a collator. This API harvests the collator's
+ *  locale and the attribute set and produces a string that can be used for opening 
+ *  a collator with the same properties using the ucol_openFromShortString API.
+ *  This string will be normalized.
+ *  The structure and the syntax of the string is defined in the "Naming collators"
+ *  section of the users guide: 
+ *  http://icu.sourceforge.net/icu/userguide/Collate_Concepts.html#Naming_Collators
+ *  This API supports preflighting.
+ *  @param coll a collator
+ *  @param locale a locale that will appear as a collators locale in the resulting
+ *                short string definition. If NULL, the locale will be harvested 
+ *                from the collator.
+ *  @param buffer space to hold the resulting string
+ *  @param capacity capacity of the buffer
+ *  @param status for returning errors. All the preflighting errors are featured
+ *  @return length of the resulting string
+ *  @see ucol_openFromShortString
+ *  @see ucol_normalizeShortDefinitionString
+ *  @draft ICU 3.0
+ */
+U_CAPI int32_t U_EXPORT2
+ucol_getShortDefinitionString(const UCollator *coll,
+                              const char *locale,
+                              char *buffer,
+                              int32_t capacity,
+                              UErrorCode *status);
+
+/** Verifies and normalizes short definition string.
+ *  Normalized short definition string has all the option sorted by the argument name,
+ *  so that equivalent definition strings are the same. 
+ *  This API supports preflighting.
+ *  @param source definition string
+ *  @param destination space to hold the resulting string
+ *  @param capacity capacity of the buffer
+ *  @param parseError if not NULL, structure that will get filled with error's pre
+ *                   and post context in case of error.
+ *  @param status     Error code. This API will return an error if an invalid attribute 
+ *                    or attribute/value combination is specified. All the preflighting 
+ *                    errors are also featured
+ *  @return length of the resulting normalized string.
+ *
+ *  @see ucol_openFromShortString
+ *  @see ucol_getShortDefinitionString
+ * 
+ *  @draft ICU 3.0
+ */
+
+U_CAPI int32_t U_EXPORT2
+ucol_normalizeShortDefinitionString(const char *source,
+                                    char *destination,
+                                    int32_t capacity,
+                                    UParseError *parseError,
+                                    UErrorCode *status);
+        
+
+/**
+ * Get a sort key for a string from a UCollator.
+ * Sort keys may be compared using <TT>strcmp</TT>.
+ * @param coll The UCollator containing the collation rules.
+ * @param source The string to transform.
+ * @param sourceLength The length of source, or -1 if null-terminated.
+ * @param result A pointer to a buffer to receive the attribute.
+ * @param resultLength The maximum size of result.
+ * @return The size needed to fully store the sort key..
+ * @see ucol_keyHashCode
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2 
+ucol_getSortKey(const    UCollator    *coll,
+        const    UChar        *source,
+        int32_t        sourceLength,
+        uint8_t        *result,
+        int32_t        resultLength);
+
+
+/** Gets the next count bytes of a sort key. Caller needs
+ *  to preserve state array between calls and to provide
+ *  the same type of UCharIterator set with the same string.
+ *  The destination buffer provided must be big enough to store
+ *  the number of requested bytes. Generated sortkey is not 
+ *  compatible with sortkeys generated using ucol_getSortKey
+ *  API, since we don't do any compression. If uncompressed
+ *  sortkeys are required, this API can be used.
+ *  @param coll The UCollator containing the collation rules.
+ *  @param iter UCharIterator containing the string we need 
+ *              the sort key to be calculated for.
+ *  @param state Opaque state of sortkey iteration.
+ *  @param dest Buffer to hold the resulting sortkey part
+ *  @param count number of sort key bytes required.
+ *  @param status error code indicator.
+ *  @return the actual number of bytes of a sortkey. It can be
+ *          smaller than count if we have reached the end of 
+ *          the sort key.
+ *  @stable ICU 2.6
+ */
+U_STABLE int32_t U_EXPORT2 
+ucol_nextSortKeyPart(const UCollator *coll,
+                     UCharIterator *iter,
+                     uint32_t state[2],
+                     uint8_t *dest, int32_t count,
+                     UErrorCode *status);
+
+/** enum that is taken by ucol_getBound API 
+ * See below for explanation                
+ * do not change the values assigned to the 
+ * members of this enum. Underlying code    
+ * depends on them having these numbers     
+ * @stable ICU 2.0
+ */
+typedef enum {
+  /** lower bound */
+  UCOL_BOUND_LOWER = 0,
+  /** upper bound that will match strings of exact size */
+  UCOL_BOUND_UPPER = 1,
+  /** upper bound that will match all the strings that have the same initial substring as the given string */
+  UCOL_BOUND_UPPER_LONG = 2,
+  UCOL_BOUND_VALUE_COUNT
+} UColBoundMode;
+
+/**
+ * Produce a bound for a given sortkey and a number of levels.
+ * Return value is always the number of bytes needed, regardless of 
+ * whether the result buffer was big enough or even valid.<br>
+ * Resulting bounds can be used to produce a range of strings that are
+ * between upper and lower bounds. For example, if bounds are produced
+ * for a sortkey of string "smith", strings between upper and lower 
+ * bounds with one level would include "Smith", "SMITH", "sMiTh".<br>
+ * There are two upper bounds that can be produced. If UCOL_BOUND_UPPER
+ * is produced, strings matched would be as above. However, if bound
+ * produced using UCOL_BOUND_UPPER_LONG is used, the above example will
+ * also match "Smithsonian" and similar.<br>
+ * For more on usage, see example in cintltst/capitst.c in procedure
+ * TestBounds.
+ * Sort keys may be compared using <TT>strcmp</TT>.
+ * @param source The source sortkey.
+ * @param sourceLength The length of source, or -1 if null-terminated. 
+ *                     (If an unmodified sortkey is passed, it is always null 
+ *                      terminated).
+ * @param boundType Type of bound required. It can be UCOL_BOUND_LOWER, which 
+ *                  produces a lower inclusive bound, UCOL_BOUND_UPPER, that 
+ *                  produces upper bound that matches strings of the same length 
+ *                  or UCOL_BOUND_UPPER_LONG that matches strings that have the 
+ *                  same starting substring as the source string.
+ * @param noOfLevels  Number of levels required in the resulting bound (for most 
+ *                    uses, the recommended value is 1). See users guide for 
+ *                    explanation on number of levels a sortkey can have.
+ * @param result A pointer to a buffer to receive the resulting sortkey.
+ * @param resultLength The maximum size of result.
+ * @param status Used for returning error code if something went wrong. If the 
+ *               number of levels requested is higher than the number of levels
+ *               in the source key, a warning (U_SORT_KEY_TOO_SHORT_WARNING) is 
+ *               issued.
+ * @return The size needed to fully store the bound. 
+ * @see ucol_keyHashCode
+ * @stable ICU 2.1
+ */
+U_STABLE int32_t U_EXPORT2 
+ucol_getBound(const uint8_t       *source,
+        int32_t             sourceLength,
+        UColBoundMode       boundType,
+        uint32_t            noOfLevels,
+        uint8_t             *result,
+        int32_t             resultLength,
+        UErrorCode          *status);
+        
+/**
+ * Gets the version information for a Collator. Version is currently
+ * an opaque 32-bit number which depends, among other things, on major
+ * versions of the collator tailoring and UCA.
+ * @param coll The UCollator to query.
+ * @param info the version # information, the result will be filled in
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2
+ucol_getVersion(const UCollator* coll, UVersionInfo info);
+
+/**
+ * Gets the UCA version information for a Collator. Version is the
+ * UCA version number (3.1.1, 4.0).
+ * @param coll The UCollator to query.
+ * @param info the version # information, the result will be filled in
+ * @draft ICU 2.8
+ */
+U_DRAFT void U_EXPORT2
+ucol_getUCAVersion(const UCollator* coll, UVersionInfo info);
+
+/** 
+ * Merge two sort keys. The levels are merged with their corresponding counterparts
+ * (primaries with primaries, secondaries with secondaries etc.). Between the values
+ * from the same level a separator is inserted.
+ * example (uncompressed): 
+ * 191B1D 01 050505 01 910505 00 and 1F2123 01 050505 01 910505 00
+ * will be merged as 
+ * 191B1D 02 1F212301 050505 02 050505 01 910505 02 910505 00
+ * This allows for concatenating of first and last names for sorting, among other things.
+ * If the destination buffer is not big enough, the results are undefined.
+ * If any of source lengths are zero or any of source pointers are NULL/undefined, 
+ * result is of size zero.
+ * @param src1 pointer to the first sortkey
+ * @param src1Length length of the first sortkey
+ * @param src2 pointer to the second sortkey
+ * @param src2Length length of the second sortkey
+ * @param dest buffer to hold the result
+ * @param destCapacity size of the buffer for the result
+ * @return size of the result. If the buffer is big enough size is always
+ *         src1Length+src2Length-1
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2 
+ucol_mergeSortkeys(const uint8_t *src1, int32_t src1Length,
+                   const uint8_t *src2, int32_t src2Length,
+                   uint8_t *dest, int32_t destCapacity);
+
+/**
+ * Universal attribute setter
+ * @param coll collator which attributes are to be changed
+ * @param attr attribute type 
+ * @param value attribute value
+ * @param status to indicate whether the operation went on smoothly or there were errors
+ * @see UColAttribute
+ * @see UColAttributeValue
+ * @see ucol_getAttribute
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2 
+ucol_setAttribute(UCollator *coll, UColAttribute attr, UColAttributeValue value, UErrorCode *status);
+
+/**
+ * Universal attribute getter
+ * @param coll collator which attributes are to be changed
+ * @param attr attribute type
+ * @return attribute value
+ * @param status to indicate whether the operation went on smoothly or there were errors
+ * @see UColAttribute
+ * @see UColAttributeValue
+ * @see ucol_setAttribute
+ * @stable ICU 2.0
+ */
+U_STABLE UColAttributeValue  U_EXPORT2 
+ucol_getAttribute(const UCollator *coll, UColAttribute attr, UErrorCode *status);
+
+/** Variable top
+ * is a two byte primary value which causes all the codepoints with primary values that
+ * are less or equal than the variable top to be shifted when alternate handling is set
+ * to UCOL_SHIFTED.
+ * Sets the variable top to a collation element value of a string supplied. 
+ * @param coll collator which variable top needs to be changed
+ * @param varTop one or more (if contraction) UChars to which the variable top should be set
+ * @param len length of variable top string. If -1 it is considered to be zero terminated.
+ * @param status error code. If error code is set, the return value is undefined. 
+ *               Errors set by this function are: <br>
+ *    U_CE_NOT_FOUND_ERROR if more than one character was passed and there is no such 
+ *    a contraction<br>
+ *    U_PRIMARY_TOO_LONG_ERROR if the primary for the variable top has more than two bytes
+ * @return a 32 bit value containing the value of the variable top in upper 16 bits. 
+ *         Lower 16 bits are undefined
+ * @see ucol_getVariableTop
+ * @see ucol_restoreVariableTop
+ * @stable ICU 2.0
+ */
+U_STABLE uint32_t U_EXPORT2 
+ucol_setVariableTop(UCollator *coll, 
+                    const UChar *varTop, int32_t len, 
+                    UErrorCode *status);
+
+/** 
+ * Gets the variable top value of a Collator. 
+ * Lower 16 bits are undefined and should be ignored.
+ * @param coll collator which variable top needs to be retrieved
+ * @param status error code (not changed by function). If error code is set, 
+ *               the return value is undefined.
+ * @return the variable top value of a Collator.
+ * @see ucol_setVariableTop
+ * @see ucol_restoreVariableTop
+ * @stable ICU 2.0
+ */
+U_STABLE uint32_t U_EXPORT2 ucol_getVariableTop(const UCollator *coll, UErrorCode *status);
+
+/** 
+ * Sets the variable top to a collation element value supplied. Variable top is 
+ * set to the upper 16 bits. 
+ * Lower 16 bits are ignored.
+ * @param coll collator which variable top needs to be changed
+ * @param varTop CE value, as returned by ucol_setVariableTop or ucol)getVariableTop
+ * @param status error code (not changed by function)
+ * @see ucol_getVariableTop
+ * @see ucol_setVariableTop
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2 
+ucol_restoreVariableTop(UCollator *coll, const uint32_t varTop, UErrorCode *status);
+
+/**
+ * Thread safe cloning operation. The result is a clone of a given collator.
+ * @param coll collator to be cloned
+ * @param stackBuffer user allocated space for the new clone. 
+ * If NULL new memory will be allocated. 
+ *  If buffer is not large enough, new memory will be allocated.
+ *  Clients can use the U_COL_SAFECLONE_BUFFERSIZE. 
+ *  This will probably be enough to avoid memory allocations.
+ * @param pBufferSize pointer to size of allocated space. 
+ *  If *pBufferSize == 0, a sufficient size for use in cloning will 
+ *  be returned ('pre-flighting')
+ *  If *pBufferSize is not enough for a stack-based safe clone, 
+ *  new memory will be allocated.
+ * @param status to indicate whether the operation went on smoothly or there were errors
+ *    An informational status value, U_SAFECLONE_ALLOCATED_ERROR, is used if any
+ * allocations were necessary.
+ * @return pointer to the new clone
+ * @see ucol_open
+ * @see ucol_openRules
+ * @see ucol_close
+ * @stable ICU 2.0
+ */
+U_STABLE UCollator* U_EXPORT2 
+ucol_safeClone(const UCollator *coll,
+               void            *stackBuffer,
+               int32_t         *pBufferSize,
+               UErrorCode      *status);
+
+/** default memory size for the new clone. It needs to be this large for os/400 large pointers 
+ * @stable ICU 2.0
+ */
+#define U_COL_SAFECLONE_BUFFERSIZE 512
+
+/**
+ * Returns current rules. Delta defines whether full rules are returned or just the tailoring. 
+ * Returns number of UChars needed to store rules. If buffer is NULL or bufferLen is not enough 
+ * to store rules, will store up to available space.
+ * @param coll collator to get the rules from
+ * @param delta one of UCOL_TAILORING_ONLY, UCOL_FULL_RULES. 
+ * @param buffer buffer to store the result in. If NULL, you'll get no rules.
+ * @param bufferLen lenght of buffer to store rules in. If less then needed you'll get only the part that fits in.
+ * @return current rules
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2 
+ucol_getRulesEx(const UCollator *coll, UColRuleOption delta, UChar *buffer, int32_t bufferLen);
+
+/**
+ * gets the locale name of the collator. If the collator
+ * is instantiated from the rules, then this function returns
+ * NULL.
+ * @param coll The UCollator for which the locale is needed
+ * @param type You can choose between requested, valid and actual
+ *             locale. For description see the definition of
+ *             ULocDataLocaleType in uloc.h
+ * @param status error code of the operation
+ * @return real locale name from which the collation data comes. 
+ *         If the collator was instantiated from rules, returns
+ *         NULL.
+ * @deprecated ICU 2.8 Use ucol_getLocaleByType instead
+ */
+U_DEPRECATED const char * U_EXPORT2
+ucol_getLocale(const UCollator *coll, ULocDataLocaleType type, UErrorCode *status);
+
+
+/**
+ * gets the locale name of the collator. If the collator
+ * is instantiated from the rules, then this function returns
+ * NULL.
+ * @param coll The UCollator for which the locale is needed
+ * @param type You can choose between requested, valid and actual
+ *             locale. For description see the definition of
+ *             ULocDataLocaleType in uloc.h
+ * @param status error code of the operation
+ * @return real locale name from which the collation data comes. 
+ *         If the collator was instantiated from rules, returns
+ *         NULL.
+ * @draft ICU 2.8 likely to change in ICU 3.0, based on feedback
+ */
+U_DRAFT const char * U_EXPORT2
+ucol_getLocaleByType(const UCollator *coll, ULocDataLocaleType type, UErrorCode *status);
+
+/**
+ * Get an Unicode set that contains all the characters and sequences tailored in 
+ * this collator. The result must be disposed of by using uset_close.
+ * @param coll        The UCollator for which we want to get tailored chars
+ * @param status      error code of the operation
+ * @return a pointer to newly created USet. Must be be disposed by using uset_close
+ * @see ucol_openRules
+ * @see uset_close
+ * @stable ICU 2.4
+ */
+U_STABLE USet * U_EXPORT2
+ucol_getTailoredSet(const UCollator *coll, UErrorCode *status);
+
+/**
+ * Returned by ucol_collatorToIdentifier to signify that collator is
+ * not encodable as an identifier.
+ * @internal ICU 3.0
+ */
+#define UCOL_SIT_COLLATOR_NOT_ENCODABLE 0x80000000
+
+/**
+ * Get a 31-bit identifier given a collator. 
+ * @param coll UCollator
+ *  @param locale a locale that will appear as a collators locale in the resulting
+ *                short string definition. If NULL, the locale will be harvested 
+ *                from the collator.
+ * @param status holds error messages
+ * @return 31-bit identifier. MSB is used if the collator cannot be encoded. In that
+ *         case UCOL_SIT_COLLATOR_NOT_ENCODABLE is returned
+ * @see ucol_openFromIdentifier
+ * @see ucol_identifierToShortString
+ * @internal ICU 3.0
+ */
+U_INTERNAL uint32_t U_EXPORT2
+ucol_collatorToIdentifier(const UCollator *coll,
+                          const char *locale,
+                          UErrorCode *status);
+
+/**
+ * Open a collator given a 31-bit identifier
+ * @param identifier 31-bit identifier, encoded by calling ucol_collatorToIdentifier
+ * @param forceDefaults if FALSE, the settings that are the same as the collator 
+ *                   default settings will not be applied (for example, setting
+ *                   French secondary on a French collator would not be executed). 
+ *                   If TRUE, all the settings will be applied regardless of the 
+ *                   collator default value. If the definition
+ *                   strings that can be produced from a collator instantiated by 
+ *                   calling this API are to be cached, should be set to FALSE.
+ * @param status for returning errors
+ * @return UCollator object
+ * @see ucol_collatorToIdentifier
+ * @see ucol_identifierToShortString
+ * @internal ICU 3.0
+ */
+U_INTERNAL UCollator* U_EXPORT2
+ucol_openFromIdentifier(uint32_t identifier,
+                        UBool forceDefaults,
+                        UErrorCode *status);
+
+
+/**
+ * Calculate the short definition string given an identifier. Supports preflighting.
+ * @param identifier 31-bit identifier, encoded by calling ucol_collatorToIdentifier
+ * @param buffer buffer to store the result
+ * @param capacity buffer capacity
+ * @param forceDefaults whether the settings that are the same as the default setting
+ *                      should be forced anyway. Setting this argument to FALSE reduces
+ *                      the number of different configurations, but decreases performace
+ *                      as a collator has to be instantiated.
+ * @param status for returning errors
+ * @return length of the short definition string
+ * @see ucol_collatorToIdentifier
+ * @see ucol_openFromIdentifier
+ * @see ucol_shortStringToIdentifier
+ * @internal ICU 3.0
+ */
+U_INTERNAL int32_t U_EXPORT2
+ucol_identifierToShortString(uint32_t identifier,
+                             char *buffer,
+                             int32_t capacity,
+                             UBool forceDefaults,
+                             UErrorCode *status);
+
+/**
+ * Calculate the identifier given a short definition string. Supports preflighting.
+ * @param definition short string definition
+ * @param forceDefaults whether the settings that are the same as the default setting
+ *                      should be forced anyway. Setting this argument to FALSE reduces
+ *                      the number of different configurations, but decreases performace
+ *                      as a collator has to be instantiated.
+ * @param status for returning errors
+ * @return identifier
+ * @see ucol_collatorToIdentifier
+ * @see ucol_openFromIdentifier
+ * @see ucol_identifierToShortString
+ * @internal ICU 3.0
+ */
+U_INTERNAL uint32_t U_EXPORT2
+ucol_shortStringToIdentifier(const char *definition,
+                             UBool forceDefaults,
+                             UErrorCode *status);
+
+
+
+/**
+ * Universal attribute getter that returns UCOL_DEFAULT if the value is default
+ * @param coll collator which attributes are to be changed
+ * @param attr attribute type
+ * @return attribute value or UCOL_DEFAULT if the value is default
+ * @param status to indicate whether the operation went on smoothly or there were errors
+ * @see UColAttribute
+ * @see UColAttributeValue
+ * @see ucol_setAttribute
+ * @internal ICU 3.0
+ */
+U_INTERNAL UColAttributeValue  U_EXPORT2
+ucol_getAttributeOrDefault(const UCollator *coll, UColAttribute attr, UErrorCode *status);
+
+/** Check whether two collators are equal. Collators are considered equal if they
+ *  will sort strings the same. This means that both the current attributes and the
+ *  rules must be equivalent. Currently used for RuleBasedCollator::operator==.
+ *  @param source first collator
+ *  @param target second collator
+ *  @return TRUE or FALSE
+ *  @internal ICU 3.0
+ */
+U_INTERNAL UBool U_EXPORT2
+ucol_equals(const UCollator *source, const UCollator *target);
+
+/** Calculates the set of unsafe code points, given a collator.
+ *   A character is unsafe if you could append any character and cause the ordering to alter significantly.
+ *   Collation sorts in normalized order, so anything that rearranges in normalization can cause this.
+ *   Thus if you have a character like a_umlaut, and you add a lower_dot to it,
+ *   then it normalizes to a_lower_dot + umlaut, and sorts differently.
+ *  @param coll Collator
+ *  @param unsafe a fill-in set to receive the unsafe points
+ *  @param status for catching errors
+ *  @return number of elements in the set
+ *  @internal ICU 3.0
+ */
+U_INTERNAL int32_t U_EXPORT2
+ucol_getUnsafeSet( const UCollator *coll,
+                  USet *unsafe,
+                  UErrorCode *status);
+
+/** Reset UCA's static pointers. You don't want to use this, unless your static memory can go away.
+ * @internal ICU 3.2.1
+ */
+U_INTERNAL void U_EXPORT2
+ucol_forgetUCA(void);
+
+/** Touches all resources needed for instantiating a collator from a short string definition,
+ *  thus filling up the cache.
+ * @param definition A short string containing a locale and a set of attributes. 
+ *                   Attributes not explicitly mentioned are left at the default
+ *                   state for a locale.
+ * @param parseError if not NULL, structure that will get filled with error's pre
+ *                   and post context in case of error.
+ * @param forceDefaults if FALSE, the settings that are the same as the collator 
+ *                   default settings will not be applied (for example, setting
+ *                   French secondary on a French collator would not be executed). 
+ *                   If TRUE, all the settings will be applied regardless of the 
+ *                   collator default value. If the definition
+ *                   strings are to be cached, should be set to FALSE.
+ * @param status     Error code. Apart from regular error conditions connected to 
+ *                   instantiating collators (like out of memory or similar), this
+ *                   API will return an error if an invalid attribute or attribute/value
+ *                   combination is specified.
+ * @see ucol_openFromShortString
+ * @internal ICU 3.2.1
+ */
+U_INTERNAL void U_EXPORT2
+ucol_prepareShortStringOpen( const char *definition,
+                          UBool forceDefaults,
+                          UParseError *parseError,
+                          UErrorCode *status);
+
+/** Creates a binary image of a collator. This binary image can be stored and 
+ *  later used to instantiate a collator using ucol_openBinary.
+ *  This API supports preflighting.
+ *  @param coll Collator
+ *  @param buffer a fill-in buffer to receive the binary image
+ *  @param capacity capacity of the destination buffer
+ *  @param status for catching errors
+ *  @return size of the image
+ *  @see ucol_openBinary
+ *  @draft ICU 3.2
+ */
+U_DRAFT int32_t U_EXPORT2
+ucol_cloneBinary(const UCollator *coll,
+                 uint8_t *buffer, int32_t capacity,
+                 UErrorCode *status);
+
+/** Opens a collator from a collator binary image created using
+ *  ucol_cloneBinary. Binary image used in instantiation of the 
+ *  collator remains owned by the user and should stay around for 
+ *  the lifetime of the collator. The API also takes a base collator
+ *  which usualy should be UCA.
+ *  @param bin binary image owned by the user and required through the
+ *             lifetime of the collator
+ *  @param length size of the image. If negative, the API will try to
+ *                figure out the length of the image
+ *  @param base fallback collator, usually UCA. Base is required to be
+ *              present through the lifetime of the collator. Currently 
+ *              it cannot be NULL.
+ *  @param status for catching errors
+ *  @return newly created collator
+ *  @see ucol_cloneBinary
+ *  @draft ICU 3.2
+ */
+U_DRAFT UCollator* U_EXPORT2
+ucol_openBinary(const uint8_t *bin, int32_t length, 
+                const UCollator *base, 
+                UErrorCode *status);
+
+
+#endif /* #if !UCONFIG_NO_COLLATION */
+
+#endif
+
diff --git a/WebCore/icu/unicode/uset.h b/WebCore/icu/unicode/uset.h
new file mode 100644 (file)
index 0000000..b82ceb8
--- /dev/null
@@ -0,0 +1,745 @@
+/*
+*******************************************************************************
+*
+*   Copyright (C) 2002-2004, International Business Machines
+*   Corporation and others.  All Rights Reserved.
+*
+*******************************************************************************
+*   file name:  uset.h
+*   encoding:   US-ASCII
+*   tab size:   8 (not used)
+*   indentation:4
+*
+*   created on: 2002mar07
+*   created by: Markus W. Scherer
+*
+*   C version of UnicodeSet.
+*/
+
+
+/**
+ * \file
+ * \brief C API: Unicode Set
+ *
+ * <p>This is a C wrapper around the C++ UnicodeSet class.</p>
+ */
+
+#ifndef __USET_H__
+#define __USET_H__
+
+#include "unicode/utypes.h"
+#include "unicode/uchar.h"
+
+#ifndef UCNV_H
+struct USet;
+/**
+ * A UnicodeSet.  Use the uset_* API to manipulate.  Create with
+ * uset_open*, and destroy with uset_close.
+ * @stable ICU 2.4
+ */
+typedef struct USet USet;
+#endif
+
+/**
+ * Bitmask values to be passed to uset_openPatternOptions() or
+ * uset_applyPattern() taking an option parameter.
+ * @stable ICU 2.4
+ */
+enum {
+    /**
+     * Ignore white space within patterns unless quoted or escaped.
+     * @stable ICU 2.4
+     */
+    USET_IGNORE_SPACE = 1,  
+
+    /**
+     * Enable case insensitive matching.  E.g., "[ab]" with this flag
+     * will match 'a', 'A', 'b', and 'B'.  "[^ab]" with this flag will
+     * match all except 'a', 'A', 'b', and 'B'. This performs a full
+     * closure over case mappings, e.g. U+017F for s.
+     * @stable ICU 2.4
+     */
+    USET_CASE_INSENSITIVE = 2,  
+
+    /**
+     * Bitmask for UnicodeSet::closeOver() indicating letter case.
+     * This may be ORed together with other selectors.
+     * @internal
+     */
+    USET_CASE = 2,
+
+    /**
+     * Enable case insensitive matching.  E.g., "[ab]" with this flag
+     * will match 'a', 'A', 'b', and 'B'.  "[^ab]" with this flag will
+     * match all except 'a', 'A', 'b', and 'B'. This adds the lower-,
+     * title-, and uppercase mappings as well as the case folding
+     * of each existing element in the set.
+     * @draft ICU 3.2
+     */
+    USET_ADD_CASE_MAPPINGS = 4,
+
+    /**
+     * Enough for any single-code point set
+     * @internal
+     */
+    USET_SERIALIZED_STATIC_ARRAY_CAPACITY=8
+};
+
+/**
+ * A serialized form of a Unicode set.  Limited manipulations are
+ * possible directly on a serialized set.  See below.
+ * @stable ICU 2.4
+ */
+typedef struct USerializedSet {
+    /**
+     * The serialized Unicode Set.
+     * @stable ICU 2.4
+     */
+    const uint16_t *array;
+    /**
+     * The length of the array that contains BMP characters.
+     * @stable ICU 2.4
+     */
+    int32_t bmpLength;
+    /**
+     * The total length of the array.
+     * @stable ICU 2.4
+     */
+    int32_t length;
+    /**
+     * A small buffer for the array to reduce memory allocations.
+     * @stable ICU 2.4
+     */
+    uint16_t staticArray[USET_SERIALIZED_STATIC_ARRAY_CAPACITY];
+} USerializedSet;
+
+/*********************************************************************
+ * USet API
+ *********************************************************************/
+
+/**
+ * Creates a USet object that contains the range of characters
+ * start..end, inclusive.
+ * @param start first character of the range, inclusive
+ * @param end last character of the range, inclusive
+ * @return a newly created USet.  The caller must call uset_close() on
+ * it when done.
+ * @stable ICU 2.4
+ */
+U_STABLE USet* U_EXPORT2
+uset_open(UChar32 start, UChar32 end);
+
+/**
+ * Creates a set from the given pattern.  See the UnicodeSet class
+ * description for the syntax of the pattern language.
+ * @param pattern a string specifying what characters are in the set
+ * @param patternLength the length of the pattern, or -1 if null
+ * terminated
+ * @param ec the error code
+ * @stable ICU 2.4
+ */
+U_STABLE USet* U_EXPORT2
+uset_openPattern(const UChar* pattern, int32_t patternLength,
+                 UErrorCode* ec);
+
+/**
+ * Creates a set from the given pattern.  See the UnicodeSet class
+ * description for the syntax of the pattern language.
+ * @param pattern a string specifying what characters are in the set
+ * @param patternLength the length of the pattern, or -1 if null
+ * terminated
+ * @param options bitmask for options to apply to the pattern.
+ * Valid options are USET_IGNORE_SPACE and USET_CASE_INSENSITIVE.
+ * @param ec the error code
+ * @stable ICU 2.4
+ */
+U_STABLE USet* U_EXPORT2
+uset_openPatternOptions(const UChar* pattern, int32_t patternLength,
+                 uint32_t options,
+                 UErrorCode* ec);
+
+/**
+ * Disposes of the storage used by a USet object.  This function should
+ * be called exactly once for objects returned by uset_open().
+ * @param set the object to dispose of
+ * @stable ICU 2.4
+ */
+U_STABLE void U_EXPORT2
+uset_close(USet* set);
+
+/**
+ * Causes the USet object to represent the range <code>start - end</code>.
+ * If <code>start > end</code> then this USet is set to an empty range.
+ * @param set the object to set to the given range
+ * @param start first character in the set, inclusive
+ * @param end last character in the set, inclusive
+ * @draft ICU 3.2
+ */
+U_DRAFT void U_EXPORT2
+uset_set(USet* set,
+         UChar32 start, UChar32 end);
+
+/**
+ * Modifies the set to represent the set specified by the given
+ * pattern. See the UnicodeSet class description for the syntax of 
+ * the pattern language. See also the User Guide chapter about UnicodeSet.
+ * <em>Empties the set passed before applying the pattern.</em>
+ * @param set               The set to which the pattern is to be applied. 
+ * @param pattern           A pointer to UChar string specifying what characters are in the set.
+ *                          The character at pattern[0] must be a '['.
+ * @param patternLength     The length of the UChar string. -1 if NUL terminated.
+ * @param options           A bitmask for options to apply to the pattern.
+ *                          Valid options are USET_IGNORE_SPACE and USET_CASE_INSENSITIVE.
+ * @param status            Returns an error if the pattern cannot be parsed.
+ * @return                  Upon successful parse, the value is either
+ *                          the index of the character after the closing ']' 
+ *                          of the parsed pattern.
+ *                          If the status code indicates failure, then the return value 
+ *                          is the index of the error in the source.
+ *                                  
+ * @draft ICU 2.8
+ */
+U_DRAFT int32_t U_EXPORT2 
+uset_applyPattern(USet *set,
+                  const UChar *pattern, int32_t patternLength,
+                  uint32_t options,
+                  UErrorCode *status);
+
+/**
+ * Modifies the set to contain those code points which have the given value
+ * for the given binary or enumerated property, as returned by
+ * u_getIntPropertyValue.  Prior contents of this set are lost.
+ *
+ * @param set the object to contain the code points defined by the property
+ *
+ * @param prop a property in the range UCHAR_BIN_START..UCHAR_BIN_LIMIT-1
+ * or UCHAR_INT_START..UCHAR_INT_LIMIT-1
+ * or UCHAR_MASK_START..UCHAR_MASK_LIMIT-1.
+ *
+ * @param value a value in the range u_getIntPropertyMinValue(prop)..
+ * u_getIntPropertyMaxValue(prop), with one exception.  If prop is
+ * UCHAR_GENERAL_CATEGORY_MASK, then value should not be a UCharCategory, but
+ * rather a mask value produced by U_GET_GC_MASK().  This allows grouped
+ * categories such as [:L:] to be represented.
+ *
+ * @param ec error code input/output parameter
+ *
+ * @draft ICU 3.2
+ */
+U_DRAFT void U_EXPORT2
+uset_applyIntPropertyValue(USet* set,
+                           UProperty prop, int32_t value, UErrorCode* ec);
+
+/**
+ * Modifies the set to contain those code points which have the
+ * given value for the given property.  Prior contents of this
+ * set are lost.
+ *
+ * @param set the object to contain the code points defined by the given
+ * property and value alias
+ *
+ * @param prop a string specifying a property alias, either short or long.
+ * The name is matched loosely.  See PropertyAliases.txt for names and a
+ * description of loose matching.  If the value string is empty, then this
+ * string is interpreted as either a General_Category value alias, a Script
+ * value alias, a binary property alias, or a special ID.  Special IDs are
+ * matched loosely and correspond to the following sets:
+ *
+ * "ANY" = [\\u0000-\\U0010FFFF],
+ * "ASCII" = [\\u0000-\\u007F].
+ *
+ * @param propLength the length of the prop, or -1 if NULL
+ *
+ * @param value a string specifying a value alias, either short or long.
+ * The name is matched loosely.  See PropertyValueAliases.txt for names
+ * and a description of loose matching.  In addition to aliases listed,
+ * numeric values and canonical combining classes may be expressed
+ * numerically, e.g., ("nv", "0.5") or ("ccc", "220").  The value string
+ * may also be empty.
+ *
+ * @param valueLength the length of the value, or -1 if NULL
+ *
+ * @param ec error code input/output parameter
+ *
+ * @draft ICU 3.2
+ */
+U_DRAFT void U_EXPORT2
+uset_applyPropertyAlias(USet* set,
+                        const UChar *prop, int32_t propLength,
+                        const UChar *value, int32_t valueLength,
+                        UErrorCode* ec);
+
+/**
+ * Return true if the given position, in the given pattern, appears
+ * to be the start of a UnicodeSet pattern.
+ *
+ * @param pattern a string specifying the pattern
+ * @param patternLength the length of the pattern, or -1 if NULL
+ * @param pos the given position
+ * @draft ICU 3.2
+ */
+U_DRAFT UBool U_EXPORT2
+uset_resemblesPattern(const UChar *pattern, int32_t patternLength,
+                      int32_t pos);
+
+/**
+ * Returns a string representation of this set.  If the result of
+ * calling this function is passed to a uset_openPattern(), it
+ * will produce another set that is equal to this one.
+ * @param set the set
+ * @param result the string to receive the rules, may be NULL
+ * @param resultCapacity the capacity of result, may be 0 if result is NULL
+ * @param escapeUnprintable if TRUE then convert unprintable
+ * character to their hex escape representations, \\uxxxx or
+ * \\Uxxxxxxxx.  Unprintable characters are those other than
+ * U+000A, U+0020..U+007E.
+ * @param ec error code.
+ * @return length of string, possibly larger than resultCapacity
+ * @stable ICU 2.4
+ */
+U_STABLE int32_t U_EXPORT2
+uset_toPattern(const USet* set,
+               UChar* result, int32_t resultCapacity,
+               UBool escapeUnprintable,
+               UErrorCode* ec);
+
+/**
+ * Adds the given character to the given USet.  After this call,
+ * uset_contains(set, c) will return TRUE.
+ * @param set the object to which to add the character
+ * @param c the character to add
+ * @stable ICU 2.4
+ */
+U_STABLE void U_EXPORT2
+uset_add(USet* set, UChar32 c);
+
+/**
+ * Adds all of the elements in the specified set to this set if
+ * they're not already present.  This operation effectively
+ * modifies this set so that its value is the <i>union</i> of the two
+ * sets.  The behavior of this operation is unspecified if the specified
+ * collection is modified while the operation is in progress.
+ *
+ * @param set the object to which to add the set
+ * @param additionalSet the source set whose elements are to be added to this set.
+ * @stable ICU 2.6
+ */
+U_STABLE void U_EXPORT2
+uset_addAll(USet* set, const USet *additionalSet);
+
+/**
+ * Adds the given range of characters to the given USet.  After this call,
+ * uset_contains(set, start, end) will return TRUE.
+ * @param set the object to which to add the character
+ * @param start the first character of the range to add, inclusive
+ * @param end the last character of the range to add, inclusive
+ * @stable ICU 2.2
+ */
+U_STABLE void U_EXPORT2
+uset_addRange(USet* set, UChar32 start, UChar32 end);
+
+/**
+ * Adds the given string to the given USet.  After this call,
+ * uset_containsString(set, str, strLen) will return TRUE.
+ * @param set the object to which to add the character
+ * @param str the string to add
+ * @param strLen the length of the string or -1 if null terminated.
+ * @stable ICU 2.4
+ */
+U_STABLE void U_EXPORT2
+uset_addString(USet* set, const UChar* str, int32_t strLen);
+
+/**
+ * Removes the given character from the given USet.  After this call,
+ * uset_contains(set, c) will return FALSE.
+ * @param set the object from which to remove the character
+ * @param c the character to remove
+ * @stable ICU 2.4
+ */
+U_STABLE void U_EXPORT2
+uset_remove(USet* set, UChar32 c);
+
+/**
+ * Removes the given range of characters from the given USet.  After this call,
+ * uset_contains(set, start, end) will return FALSE.
+ * @param set the object to which to add the character
+ * @param start the first character of the range to remove, inclusive
+ * @param end the last character of the range to remove, inclusive
+ * @stable ICU 2.2
+ */
+U_STABLE void U_EXPORT2
+uset_removeRange(USet* set, UChar32 start, UChar32 end);
+
+/**
+ * Removes the given string to the given USet.  After this call,
+ * uset_containsString(set, str, strLen) will return FALSE.
+ * @param set the object to which to add the character
+ * @param str the string to remove
+ * @param strLen the length of the string or -1 if null terminated.
+ * @stable ICU 2.4
+ */
+U_STABLE void U_EXPORT2
+uset_removeString(USet* set, const UChar* str, int32_t strLen);
+
+/**
+ * Removes from this set all of its elements that are contained in the
+ * specified set.  This operation effectively modifies this
+ * set so that its value is the <i>asymmetric set difference</i> of
+ * the two sets.
+ * @param set the object from which the elements are to be removed
+ * @param removeSet the object that defines which elements will be
+ * removed from this set
+ * @draft ICU 3.2
+ */
+U_DRAFT void U_EXPORT2
+uset_removeAll(USet* set, const USet* removeSet);
+
+/**
+ * Retain only the elements in this set that are contained in the
+ * specified range.  If <code>start > end</code> then an empty range is
+ * retained, leaving the set empty.  This is equivalent to
+ * a boolean logic AND, or a set INTERSECTION.
+ *
+ * @param set the object for which to retain only the specified range
+ * @param start first character, inclusive, of range to be retained
+ * to this set.
+ * @param end last character, inclusive, of range to be retained
+ * to this set.
+ * @draft ICU 3.2
+ */
+U_DRAFT void U_EXPORT2
+uset_retain(USet* set, UChar32 start, UChar32 end);
+
+/**
+ * Retains only the elements in this set that are contained in the
+ * specified set.  In other words, removes from this set all of
+ * its elements that are not contained in the specified set.  This
+ * operation effectively modifies this set so that its value is
+ * the <i>intersection</i> of the two sets.
+ *
+ * @param set the object on which to perform the retain
+ * @param retain set that defines which elements this set will retain
+ * @draft ICU 3.2
+ */
+U_DRAFT void U_EXPORT2
+uset_retainAll(USet* set, const USet* retain);
+
+/**
+ * Reallocate this objects internal structures to take up the least
+ * possible space, without changing this object's value.
+ *
+ * @param set the object on which to perfrom the compact
+ * @draft ICU 3.2
+ */
+U_DRAFT void U_EXPORT2
+uset_compact(USet* set);
+
+/**
+ * Inverts this set.  This operation modifies this set so that
+ * its value is its complement.  This operation does not affect
+ * the multicharacter strings, if any.
+ * @param set the set
+ * @stable ICU 2.4
+ */
+U_STABLE void U_EXPORT2
+uset_complement(USet* set);
+
+/**
+ * Complements in this set all elements contained in the specified
+ * set.  Any character in the other set will be removed if it is
+ * in this set, or will be added if it is not in this set.
+ *
+ * @param set the set with which to complement
+ * @param complement set that defines which elements will be xor'ed
+ * from this set.
+ * @draft ICU 3.2
+ */
+U_DRAFT void U_EXPORT2
+uset_complementAll(USet* set, const USet* complement);
+
+/**
+ * Removes all of the elements from this set.  This set will be
+ * empty after this call returns.
+ * @param set the set
+ * @stable ICU 2.4
+ */
+U_STABLE void U_EXPORT2
+uset_clear(USet* set);
+
+/**
+ * Returns TRUE if the given USet contains no characters and no
+ * strings.
+ * @param set the set
+ * @return true if set is empty
+ * @stable ICU 2.4
+ */
+U_STABLE UBool U_EXPORT2
+uset_isEmpty(const USet* set);
+
+/**
+ * Returns TRUE if the given USet contains the given character.
+ * @param set the set
+ * @param c The codepoint to check for within the set
+ * @return true if set contains c
+ * @stable ICU 2.4
+ */
+U_STABLE UBool U_EXPORT2
+uset_contains(const USet* set, UChar32 c);
+
+/**
+ * Returns TRUE if the given USet contains all characters c
+ * where start <= c && c <= end.
+ * @param set the set
+ * @param start the first character of the range to test, inclusive
+ * @param end the last character of the range to test, inclusive
+ * @return TRUE if set contains the range
+ * @stable ICU 2.2
+ */
+U_STABLE UBool U_EXPORT2
+uset_containsRange(const USet* set, UChar32 start, UChar32 end);
+
+/**
+ * Returns TRUE if the given USet contains the given string.
+ * @param set the set
+ * @param str the string
+ * @param strLen the length of the string or -1 if null terminated.
+ * @return true if set contains str
+ * @stable ICU 2.4
+ */
+U_STABLE UBool U_EXPORT2
+uset_containsString(const USet* set, const UChar* str, int32_t strLen);
+
+/**
+ * Returns the index of the given character within this set, where
+ * the set is ordered by ascending code point.  If the character
+ * is not in this set, return -1.  The inverse of this method is
+ * <code>charAt()</code>.
+ * @param set the set
+ * @param c the character to obtain the index for
+ * @return an index from 0..size()-1, or -1
+ * @draft ICU 3.2
+ */
+U_DRAFT int32_t U_EXPORT2
+uset_indexOf(const USet* set, UChar32 c);
+
+/**
+ * Returns the character at the given index within this set, where
+ * the set is ordered by ascending code point.  If the index is
+ * out of range, return (UChar32)-1.  The inverse of this method is
+ * <code>indexOf()</code>.
+ * @param set the set
+ * @param index an index from 0..size()-1 to obtain the char for
+ * @return the character at the given index, or (UChar32)-1.
+ * @draft ICU 3.2
+ */
+U_DRAFT UChar32 U_EXPORT2
+uset_charAt(const USet* set, int32_t index);
+
+/**
+ * Returns the number of characters and strings contained in the given
+ * USet.
+ * @param set the set
+ * @return a non-negative integer counting the characters and strings
+ * contained in set
+ * @stable ICU 2.4
+ */
+U_STABLE int32_t U_EXPORT2
+uset_size(const USet* set);
+
+/**
+ * Returns the number of items in this set.  An item is either a range
+ * of characters or a single multicharacter string.
+ * @param set the set
+ * @return a non-negative integer counting the character ranges
+ * and/or strings contained in set
+ * @stable ICU 2.4
+ */
+U_STABLE int32_t U_EXPORT2
+uset_getItemCount(const USet* set);
+
+/**
+ * Returns an item of this set.  An item is either a range of
+ * characters or a single multicharacter string.
+ * @param set the set
+ * @param itemIndex a non-negative integer in the range 0..
+ * uset_getItemCount(set)-1
+ * @param start pointer to variable to receive first character
+ * in range, inclusive
+ * @param end pointer to variable to receive last character in range,
+ * inclusive
+ * @param str buffer to receive the string, may be NULL
+ * @param strCapacity capacity of str, or 0 if str is NULL
+ * @param ec error code
+ * @return the length of the string (>= 2), or 0 if the item is a
+ * range, in which case it is the range *start..*end, or -1 if
+ * itemIndex is out of range
+ * @stable ICU 2.4
+ */
+U_STABLE int32_t U_EXPORT2
+uset_getItem(const USet* set, int32_t itemIndex,
+             UChar32* start, UChar32* end,
+             UChar* str, int32_t strCapacity,
+             UErrorCode* ec);
+
+/**
+ * Returns true if set1 contains all the characters and strings
+ * of set2. It answers the question, 'Is set1 a subset of set2?'
+ * @param set1 set to be checked for containment
+ * @param set2 set to be checked for containment
+ * @return true if the test condition is met
+ * @draft ICU 3.2
+ */
+U_DRAFT UBool U_EXPORT2
+uset_containsAll(const USet* set1, const USet* set2);
+
+/**
+ * Returns true if set1 contains none of the characters and strings
+ * of set2. It answers the question, 'Is set1 a disjoint set of set2?'
+ * @param set1 set to be checked for containment
+ * @param set2 set to be checked for containment
+ * @return true if the test condition is met
+ * @draft ICU 3.2
+ */
+U_DRAFT UBool U_EXPORT2
+uset_containsNone(const USet* set1, const USet* set2);
+
+/**
+ * Returns true if set1 contains some of the characters and strings
+ * of set2. It answers the question, 'Does set1 and set2 have an intersection?'
+ * @param set1 set to be checked for containment
+ * @param set2 set to be checked for containment
+ * @return true if the test condition is met
+ * @draft ICU 3.2
+ */
+U_DRAFT UBool U_EXPORT2
+uset_containsSome(const USet* set1, const USet* set2);
+
+/**
+ * Returns true if set1 contains all of the characters and strings
+ * of set2, and vis versa. It answers the question, 'Is set1 equal to set2?'
+ * @param set1 set to be checked for containment
+ * @param set2 set to be checked for containment
+ * @return true if the test condition is met
+ * @draft ICU 3.2
+ */
+U_DRAFT UBool U_EXPORT2
+uset_equals(const USet* set1, const USet* set2);
+
+/*********************************************************************
+ * Serialized set API
+ *********************************************************************/
+
+/**
+ * Serializes this set into an array of 16-bit integers.  Serialization
+ * (currently) only records the characters in the set; multicharacter
+ * strings are ignored.
+ *
+ * The array
+ * has following format (each line is one 16-bit integer):
+ *
+ *  length     = (n+2*m) | (m!=0?0x8000:0)
+ *  bmpLength  = n; present if m!=0
+ *  bmp[0]
+ *  bmp[1]
+ *  ...
+ *  bmp[n-1]
+ *  supp-high[0]
+ *  supp-low[0]
+ *  supp-high[1]
+ *  supp-low[1]
+ *  ...
+ *  supp-high[m-1]
+ *  supp-low[m-1]
+ *
+ * The array starts with a header.  After the header are n bmp
+ * code points, then m supplementary code points.  Either n or m
+ * or both may be zero.  n+2*m is always <= 0x7FFF.
+ *
+ * If there are no supplementary characters (if m==0) then the
+ * header is one 16-bit integer, 'length', with value n.
+ *
+ * If there are supplementary characters (if m!=0) then the header
+ * is two 16-bit integers.  The first, 'length', has value
+ * (n+2*m)|0x8000.  The second, 'bmpLength', has value n.
+ *
+ * After the header the code points are stored in ascending order.
+ * Supplementary code points are stored as most significant 16
+ * bits followed by least significant 16 bits.
+ *
+ * @param set the set
+ * @param dest pointer to buffer of destCapacity 16-bit integers.
+ * May be NULL only if destCapacity is zero.
+ * @param destCapacity size of dest, or zero.  Must not be negative.
+ * @param pErrorCode pointer to the error code.  Will be set to
+ * U_INDEX_OUTOFBOUNDS_ERROR if n+2*m > 0x7FFF.  Will be set to
+ * U_BUFFER_OVERFLOW_ERROR if n+2*m+(m!=0?2:1) > destCapacity.
+ * @return the total length of the serialized format, including
+ * the header, that is, n+2*m+(m!=0?2:1), or 0 on error other
+ * than U_BUFFER_OVERFLOW_ERROR.
+ * @stable ICU 2.4
+ */
+U_STABLE int32_t U_EXPORT2
+uset_serialize(const USet* set, uint16_t* dest, int32_t destCapacity, UErrorCode* pErrorCode);
+
+/**
+ * Given a serialized array, fill in the given serialized set object.
+ * @param fillSet pointer to result
+ * @param src pointer to start of array
+ * @param srcLength length of array
+ * @return true if the given array is valid, otherwise false
+ * @stable ICU 2.4
+ */
+U_STABLE UBool U_EXPORT2
+uset_getSerializedSet(USerializedSet* fillSet, const uint16_t* src, int32_t srcLength);
+
+/**
+ * Set the USerializedSet to contain the given character (and nothing
+ * else).
+ * @param fillSet pointer to result
+ * @param c The codepoint to set
+ * @stable ICU 2.4
+ */
+U_STABLE void U_EXPORT2
+uset_setSerializedToOne(USerializedSet* fillSet, UChar32 c);
+
+/**
+ * Returns TRUE if the given USerializedSet contains the given
+ * character.
+ * @param set the serialized set
+ * @param c The codepoint to check for within the set
+ * @return true if set contains c
+ * @stable ICU 2.4
+ */
+U_STABLE UBool U_EXPORT2
+uset_serializedContains(const USerializedSet* set, UChar32 c);
+
+/**
+ * Returns the number of disjoint ranges of characters contained in
+ * the given serialized set.  Ignores any strings contained in the
+ * set.
+ * @param set the serialized set
+ * @return a non-negative integer counting the character ranges
+ * contained in set
+ * @stable ICU 2.4
+ */
+U_STABLE int32_t U_EXPORT2
+uset_getSerializedRangeCount(const USerializedSet* set);
+
+/**
+ * Returns a range of characters contained in the given serialized
+ * set.
+ * @param set the serialized set
+ * @param rangeIndex a non-negative integer in the range 0..
+ * uset_getSerializedRangeCount(set)-1
+ * @param pStart pointer to variable to receive first character
+ * in range, inclusive
+ * @param pEnd pointer to variable to receive last character in range,
+ * inclusive
+ * @return true if rangeIndex is valid, otherwise false
+ * @stable ICU 2.4
+ */
+U_STABLE UBool U_EXPORT2
+uset_getSerializedRange(const USerializedSet* set, int32_t rangeIndex,
+                        UChar32* pStart, UChar32* pEnd);
+
+#endif
index d5f223cc2a3a9ea4f4728830db60d7a634e37d71..f7aca06db386e6b18fb650808ff3f80287ab500a 100644 (file)
@@ -44,6 +44,7 @@
 #include "TextResourceDecoder.h"
 #include "XMLTokenizer.h"
 #include "XSLTExtensions.h"
+#include "XSLTUnicodeSort.h"
 #include "loader.h"
 #include "markup.h"
 #include <libxslt/imports.h>
@@ -63,6 +64,7 @@ SOFT_LINK(libxslt, xsltFreeTransformContext, void, (xsltTransformContextPtr ctxt
 SOFT_LINK(libxslt, xsltNewTransformContext, xsltTransformContextPtr, (xsltStylesheetPtr style, xmlDocPtr doc), (style, doc))
 SOFT_LINK(libxslt, xsltApplyStylesheetUser, xmlDocPtr, (xsltStylesheetPtr style, xmlDocPtr doc, const char** params, const char* output, FILE* profile, xsltTransformContextPtr userCtxt), (style, doc, params, output, profile, userCtxt))
 SOFT_LINK(libxslt, xsltQuoteUserParams, int, (xsltTransformContextPtr ctxt, const char** params), (ctxt, params))
+SOFT_LINK(libxslt, xsltSetCtxtSortFunc, void, (xsltTransformContextPtr ctxt, xsltSortFunc handler), (ctxt, handler))
 SOFT_LINK(libxslt, xsltSetLoaderFunc, void, (xsltDocLoaderFunc f), (f))
 SOFT_LINK(libxslt, xsltSaveResultTo, int, (xmlOutputBufferPtr buf, xmlDocPtr result, xsltStylesheetPtr style), (buf, result, style))
 SOFT_LINK(libxslt, xsltNextImport, xsltStylesheetPtr, (xsltStylesheetPtr style), (style))
@@ -349,6 +351,11 @@ bool XSLTProcessor::transformToString(Node* sourceNode, String& mimeType, String
 
         xsltTransformContextPtr transformContext = xsltNewTransformContext(sheet, sourceDoc);
         registerXSLTExtensions(transformContext);
+#if USE(ICU_UNICODE)
+        // <http://bugs.webkit.org/show_bug.cgi?id=16077>: XSLT processor <xsl:sort> algorithm only compares by code point
+        // Only implemented for ICU yet.
+        xsltSetCtxtSortFunc(transformContext, xsltUnicodeSortFunction);
+#endif
 
         // This is a workaround for a bug in libxslt. 
         // The bug has been fixed in version 1.1.13, so once we ship that this can be removed.
diff --git a/WebCore/xml/XSLTUnicodeSort.cpp b/WebCore/xml/XSLTUnicodeSort.cpp
new file mode 100644 (file)
index 0000000..139eab4
--- /dev/null
@@ -0,0 +1,392 @@
+/*
+ * Copyright (C) 2007 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 "XSLTUnicodeSort.h"
+
+#if ENABLE(XSLT) && USE(ICU_UNICODE)
+
+#include <libxslt/templates.h>
+#include <libxslt/xsltutils.h>
+#include <unicode/ucnv.h>
+#include <unicode/ucol.h>
+#include <unicode/ustring.h>
+
+#if PLATFORM(MAC)
+#include "SoftLinking.h"
+#endif
+
+#if PLATFORM(MAC)
+SOFT_LINK_LIBRARY(libxslt)
+SOFT_LINK(libxslt, xsltComputeSortResult, xmlXPathObjectPtr*, (xsltTransformContextPtr ctxt, xmlNodePtr sort), (ctxt, sort))
+SOFT_LINK(libxslt, xsltEvalAttrValueTemplate, xmlChar*, (xsltTransformContextPtr ctxt, xmlNodePtr node, const xmlChar *name, const xmlChar *ns), (ctxt, node, name, ns))
+
+static void init_xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
+static void (*softLink_xsltTransformError)(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *, ...) = init_xsltTransformError;
+
+static void init_xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char* msg, ...)
+{
+    softLink_xsltTransformError = (void (*) (xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *, ...))dlsym(libxsltLibrary(), "xsltTransformError");
+    ASSERT(softLink_xsltTransformError);
+
+    va_list args;
+    va_start(args, msg);
+#if PLATFORM(WIN_OS)
+    char str[1024];
+    vsnprintf(str, sizeof(str) - 1, msg, args);
+#else
+    char* str;
+    vasprintf(&str, msg, args);
+#endif
+    va_end(args);
+
+    softLink_xsltTransformError(ctxt, style, node, "%s", str);
+
+#if !PLATFORM(WIN_OS)
+    free(str);
+#endif
+}
+
+inline void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char* msg, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
+
+inline void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char* msg, ...)
+{
+    va_list args;
+    va_start(args, msg);
+#if PLATFORM(WIN_OS)
+    char str[1024];
+    vsnprintf(str, sizeof(str) - 1, msg, args);
+#else
+    char* str;
+    vasprintf(&str, msg, args);
+#endif
+    va_end(args);
+
+    softLink_xsltTransformError(ctxt, style, node, "%s", str);
+
+#if !PLATFORM(WIN_OS)
+    free(str);
+#endif
+}
+
+#endif
+
+namespace WebCore {
+
+// Based on default implementation from libxslt 1.1.22 and xsltICUSort.c example.
+void xsltUnicodeSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts, int nbsorts)
+{
+#ifdef XSLT_REFACTORED
+    xsltStyleItemSortPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+    xmlXPathObjectPtr *resultsTab[XSLT_MAX_SORT];
+    xmlXPathObjectPtr *results = NULL, *res;
+    xmlNodeSetPtr list = NULL;
+    int descending, number, desc, numb;
+    int len = 0;
+    int i, j, incr;
+    int tst;
+    int depth;
+    xmlNodePtr node;
+    xmlXPathObjectPtr tmp;    
+    int tempstype[XSLT_MAX_SORT], temporder[XSLT_MAX_SORT];
+
+    /* Start ICU change */
+    UCollator *coll = 0;
+    UConverter *conv;
+    UErrorCode status;
+    UChar *target,*target2;
+    int targetlen, target2len;
+    /* End ICU change */
+
+    if ((ctxt == NULL) || (sorts == NULL) || (nbsorts <= 0) ||
+        (nbsorts >= XSLT_MAX_SORT))
+        return;
+    if (sorts[0] == NULL)
+        return;
+    comp = static_cast<xsltStylePreComp*>(sorts[0]->psvi);
+    if (comp == NULL)
+        return;
+
+    list = ctxt->nodeList;
+    if ((list == NULL) || (list->nodeNr <= 1))
+        return; /* nothing to do */
+
+    for (j = 0; j < nbsorts; j++) {
+        comp = static_cast<xsltStylePreComp*>(sorts[j]->psvi);
+        tempstype[j] = 0;
+        if ((comp->stype == NULL) && (comp->has_stype != 0)) {
+            comp->stype =
+                xsltEvalAttrValueTemplate(ctxt, sorts[j],
+                                          (const xmlChar *) "data-type",
+                                          XSLT_NAMESPACE);
+            if (comp->stype != NULL) {
+                tempstype[j] = 1;
+                if (xmlStrEqual(comp->stype, (const xmlChar *) "text"))
+                    comp->number = 0;
+                else if (xmlStrEqual(comp->stype, (const xmlChar *) "number"))
+                    comp->number = 1;
+                else {
+                    xsltTransformError(ctxt, NULL, sorts[j],
+                          "xsltDoSortFunction: no support for data-type = %s\n",
+                                     comp->stype);
+                    comp->number = 0; /* use default */
+                }
+            }
+        }
+        temporder[j] = 0;
+        if ((comp->order == NULL) && (comp->has_order != 0)) {
+            comp->order = xsltEvalAttrValueTemplate(ctxt, sorts[j],
+                                                    (const xmlChar *) "order",
+                                                    XSLT_NAMESPACE);
+            if (comp->order != NULL) {
+                temporder[j] = 1;
+                if (xmlStrEqual(comp->order, (const xmlChar *) "ascending"))
+                    comp->descending = 0;
+                else if (xmlStrEqual(comp->order,
+                                     (const xmlChar *) "descending"))
+                    comp->descending = 1;
+                else {
+                    xsltTransformError(ctxt, NULL, sorts[j],
+                             "xsltDoSortFunction: invalid value %s for order\n",
+                                     comp->order);
+                    comp->descending = 0; /* use default */
+                }
+            }
+        }
+    }
+
+    len = list->nodeNr;
+
+    resultsTab[0] = xsltComputeSortResult(ctxt, sorts[0]);
+    for (i = 1;i < XSLT_MAX_SORT;i++)
+        resultsTab[i] = NULL;
+
+    results = resultsTab[0];
+
+    comp = static_cast<xsltStylePreComp*>(sorts[0]->psvi);
+    descending = comp->descending;
+    number = comp->number;
+    if (results == NULL)
+        return;
+
+    /* Start ICU change */
+    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");
+    /* End ICU change */
+
+    /* Shell's sort of node-set */
+    for (incr = len / 2; incr > 0; incr /= 2) {
+        for (i = incr; i < len; i++) {
+            j = i - incr;
+            if (results[i] == NULL)
+                continue;
+            
+            while (j >= 0) {
+                if (results[j] == NULL)
+                    tst = 1;
+                else {
+                    if (number) {
+                        /* We make NaN smaller than number in accordance
+                           with XSLT spec */
+                        if (xmlXPathIsNaN(results[j]->floatval)) {
+                            if (xmlXPathIsNaN(results[j + incr]->floatval))
+                                tst = 0;
+                            else
+                                tst = -1;
+                        } else if (xmlXPathIsNaN(results[j + incr]->floatval))
+                            tst = 1;
+                        else if (results[j]->floatval ==
+                                results[j + incr]->floatval)
+                            tst = 0;
+                        else if (results[j]->floatval > 
+                                results[j + incr]->floatval)
+                            tst = 1;
+                        else tst = -1;
+                    } else {
+                        /* Start ICU change */
+                        targetlen = xmlStrlen(results[j]->stringval) * 2;
+                        target2len = xmlStrlen(results[j + incr]->stringval) * 2;
+                        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));
+                        /* End ICU change */
+                    }
+                    if (descending)
+                        tst = -tst;
+                }
+                if (tst == 0) {
+                    /*
+                     * Okay we need to use multi level sorts
+                     */
+                    depth = 1;
+                    while (depth < nbsorts) {
+                        if (sorts[depth] == NULL)
+                            break;
+                        comp = static_cast<xsltStylePreComp*>(sorts[depth]->psvi);
+                        if (comp == NULL)
+                            break;
+                        desc = comp->descending;
+                        numb = comp->number;
+
+                        /*
+                         * Compute the result of the next level for the
+                         * full set, this might be optimized ... or not
+                         */
+                        if (resultsTab[depth] == NULL) 
+                            resultsTab[depth] = xsltComputeSortResult(ctxt,
+                                                        sorts[depth]);
+                        res = resultsTab[depth];
+                        if (res == NULL) 
+                            break;
+                        if (res[j] == NULL) {
+                            if (res[j+incr] != NULL)
+                                tst = 1;
+                        } else {
+                            if (numb) {
+                                /* We make NaN smaller than number in
+                                   accordance with XSLT spec */
+                                if (xmlXPathIsNaN(res[j]->floatval)) {
+                                    if (xmlXPathIsNaN(res[j +
+                                                    incr]->floatval))
+                                        tst = 0;
+                                    else
+                                        tst = -1;
+                                } else if (xmlXPathIsNaN(res[j + incr]->
+                                                floatval))
+                                    tst = 1;
+                                else if (res[j]->floatval == res[j + incr]->
+                                                floatval)
+                                    tst = 0;
+                                else if (res[j]->floatval > 
+                                        res[j + incr]->floatval)
+                                    tst = 1;
+                                else tst = -1;
+                            } else {
+                                /* Start ICU change */
+                                targetlen = xmlStrlen(res[j]->stringval) * 2;
+                                target2len = xmlStrlen(res[j + incr]->stringval) * 2;
+                                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));
+                                /* End ICU change */
+                            }
+                            if (desc)
+                                tst = -tst;
+                        }
+
+                        /*
+                         * if we still can't differenciate at this level
+                         * try one level deeper.
+                         */
+                        if (tst != 0)
+                            break;
+                        depth++;
+                    }
+                }
+                if (tst == 0) {
+                    tst = results[j]->index > results[j + incr]->index;
+                }
+                if (tst > 0) {
+                    tmp = results[j];
+                    results[j] = results[j + incr];
+                    results[j + incr] = tmp;
+                    node = list->nodeTab[j];
+                    list->nodeTab[j] = list->nodeTab[j + incr];
+                    list->nodeTab[j + incr] = node;
+                    depth = 1;
+                    while (depth < nbsorts) {
+                        if (sorts[depth] == NULL)
+                            break;
+                        if (resultsTab[depth] == NULL)
+                            break;
+                        res = resultsTab[depth];
+                        tmp = res[j];
+                        res[j] = res[j + incr];
+                        res[j + incr] = tmp;
+                        depth++;
+                    }
+                    j -= incr;
+                } else
+                    break;
+            }
+        }
+    }
+
+    /* Start ICU change */
+    ucol_close(coll);
+    ucnv_close(conv);
+    /* End ICU change */
+
+    for (j = 0; j < nbsorts; j++) {
+        comp = static_cast<xsltStylePreComp*>(sorts[j]->psvi);
+        if (tempstype[j] == 1) {
+            /* The data-type needs to be recomputed each time */
+            xmlFree((void *)(comp->stype));
+            comp->stype = NULL;
+        }
+        if (temporder[j] == 1) {
+            /* The order needs to be recomputed each time */
+            xmlFree((void *)(comp->order));
+            comp->order = NULL;
+        }
+        if (resultsTab[j] != NULL) {
+            for (i = 0;i < len;i++)
+                xmlXPathFreeObject(resultsTab[j][i]);
+            xmlFree(resultsTab[j]);
+        }
+    }
+}
+
+}
+
+#endif
diff --git a/WebCore/xml/XSLTUnicodeSort.h b/WebCore/xml/XSLTUnicodeSort.h
new file mode 100644 (file)
index 0000000..c5a76ec
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2007 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 XSLTUnicodeSort_h
+#define XSLTUnicodeSort_h
+
+// Only implemented for ICU yet.
+// FIXME: We need to make an abstraction for Unicode collation to implement this for other libraries.
+#if ENABLE(XSLT) && USE(ICU_UNICODE)
+
+#include <libxslt/xsltInternals.h>
+
+namespace WebCore {
+
+    void xsltUnicodeSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr* sorts, int nbsorts);
+
+}
+
+#endif
+#endif