add StringBuffer/Builder.reverse fixes ISSUE 449 Change-Id: I342e7ed86c0e4efa90d09bdfe0d72c79db2654c5 Review-Link: https://gwt-review.googlesource.com/#/c/2431/ Review by: goktug@google.com git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@11591 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/core/client/impl/StringBufferImpl.java b/user/src/com/google/gwt/core/client/impl/StringBufferImpl.java index 23a7202..86c9b52 100644 --- a/user/src/com/google/gwt/core/client/impl/StringBufferImpl.java +++ b/user/src/com/google/gwt/core/client/impl/StringBufferImpl.java
@@ -15,6 +15,7 @@ */ package com.google.gwt.core.client.impl; + /** * <p> * The interface to defer bound implementations of {@link StringBuilder} and @@ -29,9 +30,35 @@ */ public abstract class StringBufferImpl { + public static String reverseString(String s) { + int length = s.length(); + + if (length <= 1) { + return s; + } + + char[] buffer = new char[length]; + + buffer[0] = s.charAt(length - 1); + + for (int i = 1; i < length; i++) { + buffer[i] = s.charAt(length - 1 - i); + if (Character.isSurrogatePair(buffer[i], buffer[i - 1])) { + swap(buffer, i - 1, i); + } + } + + return new String(buffer); + } + + private static void swap(char[] buffer, int f, int s) { + char tmp = buffer[f]; + buffer[f] = buffer[s]; + buffer[s] = tmp; + } + /** - * Append for primitive; the value can be stored and only later converted to a - * string. + * Append for primitive; the value can be stored and only later converted to a string. */ public abstract void append(Object data, boolean x); @@ -86,6 +113,11 @@ public abstract void replace(Object data, int start, int end, String toInsert); /** + * Reverses the whole StringBuffer/Builder + */ + public abstract void reverse(Object data); + + /** * Returns the string buffer as a String. */ public abstract String toString(Object data);
diff --git a/user/src/com/google/gwt/core/client/impl/StringBufferImplAppend.java b/user/src/com/google/gwt/core/client/impl/StringBufferImplAppend.java index 6dd2ed5..15c97b3 100644 --- a/user/src/com/google/gwt/core/client/impl/StringBufferImplAppend.java +++ b/user/src/com/google/gwt/core/client/impl/StringBufferImplAppend.java
@@ -73,7 +73,13 @@ } @Override + public void reverse(Object data) { + string = reverseString(string); + } + + @Override public String toString(Object data) { return string; } + }
diff --git a/user/src/com/google/gwt/core/client/impl/StringBufferImplArrayBase.java b/user/src/com/google/gwt/core/client/impl/StringBufferImplArrayBase.java index 227ef93..fd5600b 100644 --- a/user/src/com/google/gwt/core/client/impl/StringBufferImplArrayBase.java +++ b/user/src/com/google/gwt/core/client/impl/StringBufferImplArrayBase.java
@@ -76,6 +76,13 @@ } @Override + public void reverse(Object a) { + String s = takeString(a); + s = reverseString(s); + appendNonNull(a, s); + } + + @Override public final String toString(Object a) { String s = takeString(a); appendNonNull(a, s); @@ -87,4 +94,5 @@ a.length = a.explicitLength = 0; return s; }-*/; + }
diff --git a/user/super/com/google/gwt/emul/java/lang/StringBuffer.java b/user/super/com/google/gwt/emul/java/lang/StringBuffer.java index 2b24557..b7b1a53 100644 --- a/user/super/com/google/gwt/emul/java/lang/StringBuffer.java +++ b/user/super/com/google/gwt/emul/java/lang/StringBuffer.java
@@ -231,6 +231,11 @@ return this; } + public StringBuffer reverse() { + impl.reverse(data); + return this; + } + /** * Warning! This method is <b>much</b> slower than the JRE implementation. If * you need to do character level manipulation, you are strongly advised to
diff --git a/user/super/com/google/gwt/emul/java/lang/StringBuilder.java b/user/super/com/google/gwt/emul/java/lang/StringBuilder.java index e6d495a..37eb242 100644 --- a/user/super/com/google/gwt/emul/java/lang/StringBuilder.java +++ b/user/super/com/google/gwt/emul/java/lang/StringBuilder.java
@@ -231,6 +231,11 @@ return this; } + public StringBuilder reserve() { + impl.reverse(data); + return this; + } + /** * Warning! This method is <b>much</b> slower than the JRE implementation. If * you need to do character level manipulation, you are strongly advised to
diff --git a/user/test/com/google/gwt/emultest/java/lang/StringBufferTest.java b/user/test/com/google/gwt/emultest/java/lang/StringBufferTest.java index e92c177..fa0e807 100644 --- a/user/test/com/google/gwt/emultest/java/lang/StringBufferTest.java +++ b/user/test/com/google/gwt/emultest/java/lang/StringBufferTest.java
@@ -21,6 +21,11 @@ * This class tests classes StringBuffer and StringBuilder. */ public class StringBufferTest extends GWTTestCase { + + private static void assertEqualsReverse(String expected, String input) { + assertEquals(expected, new StringBuffer(input).reverse().toString()); + } + /** * This method gets the module name. * @@ -270,6 +275,35 @@ assertEquals("xxYYxx", x.toString()); } + public void testReverse() { + assertEqualsReverse("", ""); + assertEqualsReverse(" ", " "); + + assertEqualsReverse("gwt", "twg"); + assertEqualsReverse("gwt is great", "taerg si twg"); + + // Java uses UTF-16 + // char values between 0x0000 - 0xD7FF and 0xE000 - 0xFFFF + // are considered to be one char + // if the value is between 0xD800 - 0xDBFF the char is considered + // to be the lead surrogate (first) of a surrogate pair + // if the value is between 0xDC00 - 0xDFFFF the char is considered + // to be the trail surrogate (second) of a surrogate pair + // + // single appearances of surrogates are invalid in a String! + + // surrogate pair test (first one) + assertEqualsReverse("\uD800\uDC00", "\uD800\uDC00"); + // surrogate pair test (last one) + assertEqualsReverse("\uDBFF\uDFFF", "\uDBFF\uDFFF"); + // last one before surrogates start + assertEqualsReverse("\uD7FF\uD7FE", "\uD7FE\uD7FF"); + // first none surrogate + assertEqualsReverse("\uE000\uE001", "\uE001\uE000"); + // more than one surrogate pair + assertEqualsReverse("\uD801\uDC00_123_\uD802\uDC01", "\uD802\uDC01_321_\uD801\uDC00"); + } + /** * This method tests <code>setLength</code>. */