]> granicus.if.org Git - icu/commitdiff
ICU-12410 move/re-port case folding, support Edits
authorMarkus Scherer <markus.icu@gmail.com>
Thu, 9 Feb 2017 00:12:54 +0000 (00:12 +0000)
committerMarkus Scherer <markus.icu@gmail.com>
Thu, 9 Feb 2017 00:12:54 +0000 (00:12 +0000)
X-SVN-Rev: 39651

icu4j/main/classes/core/src/com/ibm/icu/impl/CaseMapImpl.java
icu4j/main/classes/core/src/com/ibm/icu/lang/UCharacter.java

index f5822c85ef09aca861510e29b293538081c0b146..c8cfadb5bafcc0604a92aa13e9de595717362a8e 100644 (file)
@@ -338,6 +338,26 @@ public final class CaseMapImpl {
         }
     }
 
+    public static <A extends Appendable> A fold(int options,
+            CharSequence src, A dest, Edits edits) {
+        try {
+            if (edits != null) {
+                edits.reset();
+            }
+            int length = src.length();
+            for (int i = 0; i < length;) {
+                int c = Character.codePointAt(src, i);
+                int cpLength = Character.charCount(c);
+                i += cpLength;
+                c = UCaseProps.INSTANCE.toFullFolding(c, dest, options);
+                appendResult(c, dest, cpLength, options, edits);
+            }
+            return dest;
+        } catch (IOException e) {
+            throw new ICUUncheckedIOException(e);
+        }
+    }
+
     private static final class GreekUpper {
         // Data bits.
         private static final int UPPER_MASK = 0x3ff;
index ff6d7a5daac2afd84149eb773d4b7f8652f5a5fd..7b2af3061c8e44f41ad687675103552de0aea2f9 100644 (file)
@@ -5351,27 +5351,19 @@ public final class UCharacter implements ECharacterCategory, ECharacterDirection
      * @stable ICU 2.6
      */
     public static final String foldCase(String str, int options) {
-        StringBuilder result = new StringBuilder(str.length());
-        int c, i, length;
-
-        length = str.length();
-        for(i=0; i<length;) {
-            c=str.codePointAt(i);
-            i+=Character.charCount(c);
-            c = UCaseProps.INSTANCE.toFullFolding(c, result, options);
-
-            /* decode the result */
-            if(c<0) {
-                /* (not) original code point */
-                c=~c;
-            } else if(c<=UCaseProps.MAX_STRING_LENGTH) {
-                /* mapping already appended to result */
-                continue;
-                /* } else { append single-code point mapping */
+        if (str.length() <= 100) {
+            if (str.isEmpty()) {
+                return str;
             }
-            result.appendCodePoint(c);
+            // Collect and apply only changes.
+            // Good if no or few changes. Bad (slow) if many changes.
+            Edits edits = new Edits();
+            StringBuilder replacementChars = CaseMapImpl.fold(
+                    CaseMapImpl.OMIT_UNCHANGED_TEXT, str, new StringBuilder(), edits);
+            return applyEdits(str, replacementChars, edits);
+        } else {
+            return CaseMapImpl.fold(0, str, new StringBuilder(str.length()), null).toString();
         }
-        return result.toString();
     }
 
     /**