src/java.base/share/classes/java/lang/String.java

Print this page
rev 13827 : 8151384: Examine sun.misc.ASCIICaseInsensitiveComparator
Reviewed-by:

@@ -1220,20 +1220,49 @@
         private static final long serialVersionUID = 8575799808933029326L;
 
         public int compare(String s1, String s2) {
             byte v1[] = s1.value;
             byte v2[] = s2.value;
-            int n1 = s1.length();
-            int n2 = s2.length();
             boolean s1IsLatin1 = s1.isLatin1();
-            boolean s2IsLatin1 = s2.isLatin1();
-            int min = Math.min(n1, n2);
-            for (int i = 0; i < min; i++) {
-                char c1 = s1IsLatin1 ? StringLatin1.getChar(v1, i)
-                                     : StringUTF16.getChar(v1, i);
-                char c2 = s2IsLatin1 ? StringLatin1.getChar(v2, i)
-                                     : StringUTF16.getChar(v2, i);
+            if (s1.coder() == s2.coder()) {
+                return s1IsLatin1 ? compareLatin1(v1, v2)
+                        : compareUTF16(v1, v2);
+            }
+            return s1IsLatin1 ? compareLatin1ToUTF16(v1, v2)
+                    : compareLatin1ToUTF16(v2, v1) * -1;
+        }
+
+        private static final int compareLatin1(byte[] v1, byte[] v2) {
+            int len1 = v1.length;
+            int len2 = v2.length;
+            int lim = Math.min(len1, len2);
+            for (int i = 0; i < lim; i++) {
+                char c1 = StringLatin1.getChar(v1, i);
+                char c2 = StringLatin1.getChar(v2, i);
+                if (c1 != c2) {
+                    c1 = (char) CharacterDataLatin1.instance.toUpperCase(c1);
+                    c2 = (char) CharacterDataLatin1.instance.toUpperCase(c2);
+                    if (c1 != c2) {
+                        c1 = (char) CharacterDataLatin1.instance.toLowerCase(c1);
+                        c2 = (char) CharacterDataLatin1.instance.toLowerCase(c2);
+                        if (c1 != c2) {
+                            // No overflow because of numeric promotion
+                            return c1 - c2;
+                        }
+                    }
+                }
+            }
+            return len1 - len2;
+        }
+
+        private static final int compareUTF16(byte[] v1, byte[] v2) {
+            int len1 = StringUTF16.length(v1);
+            int len2 = StringUTF16.length(v2);
+            int lim = Math.min(len1, len2);
+            for (int i = 0; i < lim; i++) {
+                char c1 = StringUTF16.getChar(v1, i);
+                char c2 = StringUTF16.getChar(v2, i);
                 if (c1 != c2) {
                     c1 = Character.toUpperCase(c1);
                     c2 = Character.toUpperCase(c2);
                     if (c1 != c2) {
                         c1 = Character.toLowerCase(c1);

@@ -1243,11 +1272,34 @@
                             return c1 - c2;
                         }
                     }
                 }
             }
-            return n1 - n2;
+            return len1 - len2;
+        }
+
+        private static final int compareLatin1ToUTF16(byte[] v1, byte[] v2) {
+            int len1 = v1.length;
+            int len2 = StringUTF16.length(v2);
+            int lim = Math.min(len1, len2);
+            for (int i = 0; i < lim; i++) {
+                char c1 = StringLatin1.getChar(v1, i);
+                char c2 = StringUTF16.getChar(v2, i);
+                if (c1 != c2) {
+                    c1 = (char) CharacterDataLatin1.instance.toUpperCase(c1);
+                    c2 = Character.toUpperCase(c2);
+                    if (c1 != c2) {
+                        c1 = (char) CharacterDataLatin1.instance.toLowerCase(c1);
+                        c2 = Character.toLowerCase(c2);
+                        if (c1 != c2) {
+                            // No overflow because of numeric promotion
+                            return c1 - c2;
+                        }
+                    }
+                }
+            }
+            return len1 - len2;
         }
 
         /** Replaces the de-serialized object. */
         private Object readResolve() { return CASE_INSENSITIVE_ORDER; }
     }