harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From telli...@apache.org
Subject svn commit: r695465 - in /harmony/enhanced/classlib/trunk/modules/luni/src: main/java/java/lang/AbstractStringBuilder.java test/api/common/org/apache/harmony/luni/tests/java/lang/StringBuilderTest.java
Date Mon, 15 Sep 2008 13:10:21 GMT
Author: tellison
Date: Mon Sep 15 06:10:20 2008
New Revision: 695465

URL: http://svn.apache.org/viewvc?rev=695465&view=rev
Log:
Ensure that StringBuilder/StringBuffer reverses correctly with surrogate chars.

Modified:
    harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/lang/AbstractStringBuilder.java
    harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/lang/StringBuilderTest.java

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/lang/AbstractStringBuilder.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/lang/AbstractStringBuilder.java?rev=695465&r1=695464&r2=695465&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/lang/AbstractStringBuilder.java
(original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/lang/AbstractStringBuilder.java
Mon Sep 15 06:10:20 2008
@@ -457,15 +457,72 @@
             return;
         }
         if (!shared) {
-            for (int i = 0, end = count, mid = count / 2; i < mid; i++) {
-                char temp = value[--end];
-                value[end] = value[i];
-                value[i] = temp;
+            int end = count - 1;
+            char frontHigh = value[0];
+            char endLow = value[end];
+            boolean allowFrontSur = true, allowEndSur = true;
+            for (int i = 0, mid = count / 2; i < mid; i++, --end) {
+                char frontLow = value[i + 1];
+                char endHigh = value[end - 1];
+                boolean surAtFront = allowFrontSur && frontLow >= 0xdc00
+                        && frontLow <= 0xdfff && frontHigh >= 0xd800
+                        && frontHigh <= 0xdbff;
+                if (surAtFront && (count < 3)) {
+                    return;
+                }
+                boolean surAtEnd = allowEndSur && endHigh >= 0xd800
+                        && endHigh <= 0xdbff && endLow >= 0xdc00
+                        && endLow <= 0xdfff;
+                allowFrontSur = allowEndSur = true;
+                if (surAtFront == surAtEnd) {
+                    if (surAtFront) {
+                        // both surrogates
+                        value[end] = frontLow;
+                        value[end - 1] = frontHigh;
+                        value[i] = endHigh;
+                        value[i + 1] = endLow;
+                        frontHigh = value[i + 2];
+                        endLow = value[end - 2];
+                        i++;
+                        end--;
+                    } else {
+                        // neither surrogates
+                        value[end] = frontHigh;
+                        value[i] = endLow;
+                        frontHigh = frontLow;
+                        endLow = endHigh;
+                    }
+                } else {
+                    if (surAtFront) {
+                        // surrogate only at the front
+                        value[end] = frontLow;
+                        value[i] = endLow;
+                        endLow = endHigh;
+                        allowFrontSur = false;
+                    } else {
+                        // surrogate only at the end
+                        value[end] = frontHigh;
+                        value[i] = endHigh;
+                        frontHigh = frontLow;
+                        allowEndSur = false;
+                    }
+                }
+            }
+            if ((count & 1) == 1 && (!allowFrontSur || !allowEndSur)) {
+                value[end] = allowFrontSur ? endLow : frontHigh;
             }
         } else {
             char[] newData = new char[value.length];
             for (int i = 0, end = count; i < count; i++) {
-                newData[--end] = value[i];
+                char high = value[i];
+                if ((i + 1) < count && high >= 0xd800 && high <=
0xdbff) {
+                    char low = value[i + 1];
+                    if (low >= 0xdc00 && low <= 0xdfff) {
+                        newData[--end] = low;
+                        i++;
+                    }
+                }
+                newData[--end] = high;
             }
             value = newData;
             shared = false;

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/lang/StringBuilderTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/lang/StringBuilderTest.java?rev=695465&r1=695464&r2=695465&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/lang/StringBuilderTest.java
(original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/lang/StringBuilderTest.java
Mon Sep 15 06:10:20 2008
@@ -1553,27 +1553,118 @@
 		assertEquals("12XXX7",buffer.toString());
 	}
 
+    private void reverseTest(String org, String rev, String back) {
+        // create non-shared StringBuilder
+        StringBuilder sb = new StringBuilder(org);
+        sb.reverse();
+        String reversed = sb.toString();
+        assertEquals(rev, reversed);
+        // create non-shared StringBuilder
+        sb = new StringBuilder(reversed);
+        sb.reverse();
+        reversed = sb.toString();
+        assertEquals(back, reversed);
+
+        // test algorithm when StringBuilder is shared
+        sb = new StringBuilder(org);
+        String copy = sb.toString();
+        assertEquals(org, copy);
+        sb.reverse();
+        reversed = sb.toString();
+        assertEquals(rev, reversed);
+        sb = new StringBuilder(reversed);
+        copy = sb.toString();
+        assertEquals(rev, copy);
+        sb.reverse();
+        reversed = sb.toString();
+        assertEquals(back, reversed);
+    }
+
 	/**
 	 * @tests java.lang.StringBuilder.reverse()
 	 */
 	public void test_reverse() {
-		final String fixture = "0123456789";
-		StringBuilder sb = new StringBuilder(fixture);
-		assertSame(sb, sb.reverse());
-		assertEquals("9876543210", sb.toString());
+        final String fixture = "0123456789";
+        StringBuilder sb = new StringBuilder(fixture);
+        assertSame(sb, sb.reverse());
+        assertEquals("9876543210", sb.toString());
 
-		sb = new StringBuilder("012345678");
-		assertSame(sb, sb.reverse());
-		assertEquals("876543210", sb.toString());
-
-		sb.setLength(1);
-		assertSame(sb, sb.reverse());
-		assertEquals("8", sb.toString());
+        sb = new StringBuilder("012345678");
+        assertSame(sb, sb.reverse());
+        assertEquals("876543210", sb.toString());
 
-		sb.setLength(0);
-		assertSame(sb, sb.reverse());
-		assertEquals("", sb.toString());
-	}
+        sb.setLength(1);
+        assertSame(sb, sb.reverse());
+        assertEquals("8", sb.toString());
+
+        sb.setLength(0);
+        assertSame(sb, sb.reverse());
+        assertEquals("", sb.toString());
+
+        String str;
+        str = "a";
+        reverseTest(str, str, str);
+
+        str = "ab";
+        reverseTest(str, "ba", str);
+
+        str = "abcdef";
+        reverseTest(str, "fedcba", str);
+
+        str = "abcdefg";
+        reverseTest(str, "gfedcba", str);
+
+        str = "\ud800\udc00";
+        reverseTest(str, str, str);
+
+        str = "\udc00\ud800";
+        reverseTest(str, "\ud800\udc00", "\ud800\udc00");
+
+        str = "a\ud800\udc00";
+        reverseTest(str, "\ud800\udc00a", str);
+
+        str = "ab\ud800\udc00";
+        reverseTest(str, "\ud800\udc00ba", str);
+
+        str = "abc\ud800\udc00";
+        reverseTest(str, "\ud800\udc00cba", str);
+
+        str = "\ud800\udc00\udc01\ud801\ud802\udc02";
+        reverseTest(str, "\ud802\udc02\ud801\udc01\ud800\udc00",
+                "\ud800\udc00\ud801\udc01\ud802\udc02");
+
+        str = "\ud800\udc00\ud801\udc01\ud802\udc02";
+        reverseTest(str, "\ud802\udc02\ud801\udc01\ud800\udc00", str);
+
+        str = "\ud800\udc00\udc01\ud801a";
+        reverseTest(str, "a\ud801\udc01\ud800\udc00",
+                "\ud800\udc00\ud801\udc01a");
+
+        str = "a\ud800\udc00\ud801\udc01";
+        reverseTest(str, "\ud801\udc01\ud800\udc00a", str);
+
+        str = "\ud800\udc00\udc01\ud801ab";
+        reverseTest(str, "ba\ud801\udc01\ud800\udc00",
+                "\ud800\udc00\ud801\udc01ab");
+
+        str = "ab\ud800\udc00\ud801\udc01";
+        reverseTest(str, "\ud801\udc01\ud800\udc00ba", str);
+
+        str = "\ud800\udc00\ud801\udc01";
+        reverseTest(str, "\ud801\udc01\ud800\udc00", str);
+
+        str = "a\ud800\udc00z\ud801\udc01";
+        reverseTest(str, "\ud801\udc01z\ud800\udc00a", str);
+
+        str = "a\ud800\udc00bz\ud801\udc01";
+        reverseTest(str, "\ud801\udc01zb\ud800\udc00a", str);
+
+        str = "abc\ud802\udc02\ud801\udc01\ud800\udc00";
+        reverseTest(str, "\ud800\udc00\ud801\udc01\ud802\udc02cba", str);
+
+        str = "abcd\ud802\udc02\ud801\udc01\ud800\udc00";
+        reverseTest(str, "\ud800\udc00\ud801\udc01\ud802\udc02dcba", str);
+    }
 
 	/**
 	 * @tests java.lang.StringBuilder.setCharAt(int, char)



Mime
View raw message