Merge "Make String's fast-path UTF-8 decoder more like icu4c."
diff --git a/luni/src/main/java/java/lang/String.java b/luni/src/main/java/java/lang/String.java
index f3aeb64..89691e7 100644
--- a/luni/src/main/java/java/lang/String.java
+++ b/luni/src/main/java/java/lang/String.java
@@ -282,14 +282,14 @@
if (idx + utfCount > last) {
v[s++] = REPLACEMENT_CHAR;
- break;
+ continue;
}
// Extract usable bits from b0
int val = b0 & (0x1f >> (utfCount - 1));
- for (int i = 0; i < utfCount; i++) {
+ for (int i = 0; i < utfCount; ++i) {
byte b = d[idx++];
- if ((b & 0xC0) != 0x80) {
+ if ((b & 0xc0) != 0x80) {
v[s++] = REPLACEMENT_CHAR;
idx--; // Put the input char back
continue outer;
diff --git a/luni/src/test/java/libcore/java/lang/StringTest.java b/luni/src/test/java/libcore/java/lang/StringTest.java
index 2c7d3d4..5aa596f 100644
--- a/luni/src/test/java/libcore/java/lang/StringTest.java
+++ b/luni/src/test/java/libcore/java/lang/StringTest.java
@@ -25,6 +25,7 @@
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
import java.util.Arrays;
import java.util.Locale;
import junit.framework.TestCase;
@@ -326,4 +327,18 @@
public void test_replaceAll() throws Exception {
assertEquals("project_Id", "projectId".replaceAll("(?!^)(\\p{Upper})(?!$)", "_$1"));
}
+
+ // https://code.google.com/p/android/issues/detail?id=23831
+ public void test_23831() throws Exception {
+ byte[] bytes = { (byte) 0xf5, (byte) 0xa9, (byte) 0xea, (byte) 0x21 };
+ String expected = "\ufffd\ufffd\u0021";
+
+ // Since we use icu4c for CharsetDecoder...
+ CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
+ decoder.onMalformedInput(CodingErrorAction.REPLACE);
+ assertEquals(expected, decoder.decode(ByteBuffer.wrap(bytes)).toString());
+
+ // Our fast-path code in String should behave the same...
+ assertEquals(expected, new String(bytes, "UTF-8"));
+ }
}