You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by te...@apache.org on 2008/09/15 15:10:21 UTC
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
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)