summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2013-09-13 21:38:10 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2013-09-13 21:38:11 +0000
commit16882522e9c5fd8e153b45b25df6bcf70fabb914 (patch)
tree4bbb825b10dd31c9547b7079e751a93e1eb591aa
parent6dc885813d1626e0ff1d41ff1940a1e682a57ff2 (diff)
parent6ad37f500b023ef09fd177ad8cd8e2ba0b842cae (diff)
downloadlibcore-16882522e9c5fd8e153b45b25df6bcf70fabb914.zip
libcore-16882522e9c5fd8e153b45b25df6bcf70fabb914.tar.gz
libcore-16882522e9c5fd8e153b45b25df6bcf70fabb914.tar.bz2
Merge "Clean up CharsetDecoder and CharsetEncoder."
-rw-r--r--harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/ASCIICharsetEncoderTest.java82
-rw-r--r--harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetDecoderTest.java33
-rw-r--r--harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetEncoderTest.java28
-rw-r--r--harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetDecoderTest.java27
-rw-r--r--harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetEncoderTest.java56
-rw-r--r--harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetTest.java17
-rw-r--r--luni/src/main/java/java/nio/charset/CharsetDecoder.java145
-rw-r--r--luni/src/main/java/java/nio/charset/CharsetEncoder.java109
8 files changed, 235 insertions, 262 deletions
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/ASCIICharsetEncoderTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/ASCIICharsetEncoderTest.java
index 6f59190..a85576c 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/ASCIICharsetEncoderTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/ASCIICharsetEncoderTest.java
@@ -4,9 +4,9 @@
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -33,7 +33,7 @@ public class ASCIICharsetEncoderTest extends TestCase {
// charset for ascii
private static final Charset cs = Charset.forName("ascii");
private static final CharsetEncoder encoder = cs.newEncoder();
- private static final int MAXCODEPOINT = 0x7F;
+ private static final int MAXCODEPOINT = 0x7F;
/*
* @see CharsetEncoderTest#setUp()
*/
@@ -96,21 +96,21 @@ public class ASCIICharsetEncoderTest extends TestCase {
public void testEncodeMapping() throws CharacterCodingException {
encoder.reset();
-
+
for (int i =0; i <= MAXCODEPOINT; i++) {
char[] chars = Character.toChars(i);
CharBuffer cb = CharBuffer.wrap(chars);
ByteBuffer bb = encoder.encode(cb);
assertEquals(i, bb.get(0));
}
-
+
CharBuffer cb = CharBuffer.wrap("\u0080");
try {
encoder.encode(cb);
} catch (UnmappableCharacterException e) {
//expected
}
-
+
cb = CharBuffer.wrap("\ud800");
try {
encoder.encode(cb);
@@ -128,11 +128,11 @@ public class ASCIICharsetEncoderTest extends TestCase {
//expected
}
}
-
+
public void testInternalState() {
CharBuffer in = CharBuffer.wrap("A");
ByteBuffer out = ByteBuffer.allocate(0x10);
-
+
//normal encoding process
encoder.reset();
encoder.encode(in, out, false);
@@ -140,13 +140,13 @@ public class ASCIICharsetEncoderTest extends TestCase {
encoder.encode(in, out, true);
encoder.flush(out);
}
-
+
//reset could be called at any time
public void testInternalState_Reset() {
CharsetEncoder newEncoder = cs.newEncoder();
//Init - > reset
newEncoder.reset();
-
+
//reset - > reset
newEncoder.reset();
@@ -174,7 +174,7 @@ public class ASCIICharsetEncoderTest extends TestCase {
newEncoder.reset();
}
}
-
+
public void testInternalState_Encoding() {
CharsetEncoder newEncoder = cs.newEncoder();
//Init - > encoding
@@ -183,27 +183,27 @@ public class ASCIICharsetEncoderTest extends TestCase {
ByteBuffer out = ByteBuffer.allocate(0x10);
newEncoder.encode(in, out, false);
}
-
+
//reset - > encoding
{
CharBuffer in = CharBuffer.wrap("A");
ByteBuffer out = ByteBuffer.allocate(0x10);
- newEncoder.reset();
+ newEncoder.reset();
newEncoder.encode(in, out, false);
}
//reset - > encoding - > encoding
{
- newEncoder.reset();
+ newEncoder.reset();
CharBuffer in = CharBuffer.wrap("A");
ByteBuffer out = ByteBuffer.allocate(0x10);
newEncoder.encode(in, out, false);
in = CharBuffer.wrap("BC");
newEncoder.encode(in, out, false);
}
-
+
//encoding_end - > encoding
{
- newEncoder.reset();
+ newEncoder.reset();
CharBuffer in = CharBuffer.wrap("A");
ByteBuffer out = ByteBuffer.allocate(0x10);
newEncoder.encode(in, out, true);
@@ -217,7 +217,7 @@ public class ASCIICharsetEncoderTest extends TestCase {
}
//flushed - > encoding
{
- newEncoder.reset();
+ newEncoder.reset();
CharBuffer in = CharBuffer.wrap("A");
ByteBuffer out = ByteBuffer.allocate(0x10);
newEncoder.encode(in, out, true);
@@ -231,7 +231,7 @@ public class ASCIICharsetEncoderTest extends TestCase {
}
}
}
-
+
public void testInternalState_Encoding_END() {
CharsetEncoder newEncoder = cs.newEncoder();
@@ -241,7 +241,7 @@ public class ASCIICharsetEncoderTest extends TestCase {
ByteBuffer out = ByteBuffer.allocate(0x10);
newEncoder.encode(in, out, true);
}
-
+
//Reset -> encoding_end
{
CharBuffer in = CharBuffer.wrap("A");
@@ -259,7 +259,7 @@ public class ASCIICharsetEncoderTest extends TestCase {
in = CharBuffer.wrap("BC");
newEncoder.encode(in, out, true);
}
-
+
//Reset -> encoding_end
{
newEncoder.reset();
@@ -269,7 +269,7 @@ public class ASCIICharsetEncoderTest extends TestCase {
in = CharBuffer.wrap("BC");
newEncoder.encode(in, out, true);
}
-
+
//Flushed -> encoding_end
{
newEncoder.reset();
@@ -286,10 +286,10 @@ public class ASCIICharsetEncoderTest extends TestCase {
}
}
}
-
+
public void testInternalState_Flushed() {
CharsetEncoder newEncoder = cs.newEncoder();
-
+
// init -> flushed
{
ByteBuffer out = ByteBuffer.allocate(0x10);
@@ -316,7 +316,7 @@ public class ASCIICharsetEncoderTest extends TestCase {
//expected
}
}
-
+
//encoding - > flushed
{
newEncoder.reset();
@@ -331,7 +331,7 @@ public class ASCIICharsetEncoderTest extends TestCase {
// expected
}
}
-
+
//encoding_end -> flushed
{
newEncoder.reset();
@@ -340,7 +340,7 @@ public class ASCIICharsetEncoderTest extends TestCase {
newEncoder.encode(in, out, true);
newEncoder.flush(out);
}
-
+
//flushd - > flushed
{
newEncoder.reset();
@@ -348,15 +348,10 @@ public class ASCIICharsetEncoderTest extends TestCase {
ByteBuffer out = ByteBuffer.allocate(0x10);
newEncoder.encode(in, out, true);
newEncoder.flush(out);
- try {
- newEncoder.flush(out);
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
- }
+ newEncoder.flush(out);
}
}
-
+
public void testInternalState_Encode() throws CharacterCodingException {
CharsetEncoder newEncoder = cs.newEncoder();
//Init - > encode
@@ -364,14 +359,14 @@ public class ASCIICharsetEncoderTest extends TestCase {
CharBuffer in = CharBuffer.wrap("A");
newEncoder.encode(in);
}
-
+
//Reset - > encode
{
newEncoder.reset();
CharBuffer in = CharBuffer.wrap("A");
newEncoder.encode(in);
}
-
+
//Encoding -> encode
{
newEncoder.reset();
@@ -381,7 +376,7 @@ public class ASCIICharsetEncoderTest extends TestCase {
in = CharBuffer.wrap("BC");
newEncoder.encode(in);
}
-
+
//Encoding_end -> encode
{
newEncoder.reset();
@@ -391,7 +386,7 @@ public class ASCIICharsetEncoderTest extends TestCase {
in = CharBuffer.wrap("BC");
newEncoder.encode(in);
}
-
+
//Flushed -> reset
{
newEncoder.reset();
@@ -403,17 +398,17 @@ public class ASCIICharsetEncoderTest extends TestCase {
out = newEncoder.encode(in);
}
}
-
+
public void testInternalState_from_Encode() throws CharacterCodingException {
CharsetEncoder newEncoder = cs.newEncoder();
-
+
//Encode -> Reset
{
CharBuffer in = CharBuffer.wrap("A");
newEncoder.encode(in);
newEncoder.reset();
}
-
+
// Encode -> encoding
{
CharBuffer in = CharBuffer.wrap("A");
@@ -426,12 +421,13 @@ public class ASCIICharsetEncoderTest extends TestCase {
// expected
}
}
-
+
//Encode -> Encoding_end
{
CharBuffer in = CharBuffer.wrap("A");
- newEncoder.encode(in);
ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.reset();
+ newEncoder.encode(in, out, false);
newEncoder.encode(in, out, true);
}
@@ -441,7 +437,7 @@ public class ASCIICharsetEncoderTest extends TestCase {
ByteBuffer out = newEncoder.encode(in);
newEncoder.flush(out);
}
-
+
//Encode - > encode
{
CharBuffer in = CharBuffer.wrap("A");
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetDecoderTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetDecoderTest.java
index 4ed4ab9..1a7b984 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetDecoderTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetDecoderTest.java
@@ -4,9 +4,9 @@
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -62,7 +62,7 @@ public class CharsetDecoderTest extends TestCase {
return null;
}
}
-
+
/**
* @tests java.nio.charset.CharsetDecoder#decode(java.nio.ByteBuffer)
*/
@@ -86,7 +86,7 @@ public class CharsetDecoderTest extends TestCase {
//
// charbuf = Charset.forName("UTF-16LE").decode(buf);
// assertEquals("Assert 2: charset UTF16LE", 0, charbuf.length());
-
+
// Regression for HARMONY-99
CharsetDecoder decoder2 = Charset.forName("UTF-16").newDecoder();
decoder2.onMalformedInput(CodingErrorAction.REPORT);
@@ -97,9 +97,9 @@ public class CharsetDecoderTest extends TestCase {
fail("Assert 3: MalformedInputException should have thrown");
} catch (MalformedInputException e) {
//expected
- }
+ }
}
-
+
/*
* Test malfunction decode(ByteBuffer)
*/
@@ -124,7 +124,7 @@ public class CharsetDecoderTest extends TestCase {
// expected
}
}
-
+
/*
* Mock charset class with malfunction decode & encode.
*/
@@ -173,8 +173,8 @@ public class CharsetDecoderTest extends TestCase {
protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
throw new BufferOverflowException();
}
- }
-
+ }
+
/*
* Test the method decode(ByteBuffer) .
*/
@@ -249,16 +249,16 @@ public class CharsetDecoderTest extends TestCase {
CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
decoder.onMalformedInput(CodingErrorAction.REPORT);
+ decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
/*
* When bytebuffer has a backing array...
*/
for (byte[] bytes : invalidSequences) {
try {
- decoder.decode(ByteBuffer.wrap(bytes));
- fail("No exception thrown on " + Arrays.toString(bytes));
- } catch (MalformedInputException e) {
- // expected
+ CharBuffer cb = decoder.decode(ByteBuffer.wrap(bytes));
+ fail("No exception thrown on " + Arrays.toString(bytes) + " '" + cb + "'");
+ } catch (MalformedInputException expected) {
}
}
@@ -269,10 +269,9 @@ public class CharsetDecoderTest extends TestCase {
try {
ByteBuffer bb = ByteBuffer.allocateDirect(8);
bb.put(bytes).flip();
- decoder.decode(bb);
- fail("No exception thrown on " + Arrays.toString(bytes));
- } catch (MalformedInputException e) {
- // expected
+ CharBuffer cb = decoder.decode(bb);
+ fail("No exception thrown on " + Arrays.toString(bytes) + " '" + cb + "'");
+ } catch (MalformedInputException expected) {
}
}
}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetEncoderTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetEncoderTest.java
index dd514da..c3f1a8d 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetEncoderTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetEncoderTest.java
@@ -157,26 +157,36 @@ public class CharsetEncoderTest extends TestCase {
public void test_EncodeLjava_nio_CharBufferLjava_nio_ByteBufferB() throws Exception {
Charset utf8 = Charset.forName("utf-8");
CharsetEncoder encoder = utf8.newEncoder();
- CharBuffer in1 = CharBuffer.wrap("\ud800");
- CharBuffer in2 = CharBuffer.wrap("\udc00");
- ByteBuffer out = ByteBuffer.allocate(4);
+ CharBuffer char1 = CharBuffer.wrap("\ud800");
+ CharBuffer char2 = CharBuffer.wrap("\udc00");
+ ByteBuffer bytes = ByteBuffer.allocate(4);
encoder.reset();
// If we supply just the high surrogate...
- CoderResult result = encoder.encode(in1, out, false);
+ CoderResult result = encoder.encode(char1, bytes, false);
// ...we're not done...
assertTrue(result.isUnderflow());
- assertEquals(4, out.remaining());
+ assertEquals(4, bytes.remaining());
// ...but if we then supply the low surrogate...
- result = encoder.encode(in2, out, true);
+ result = encoder.encode(char2, bytes, true);
+ assertTrue(result.isUnderflow());
// ...we're done. Note that the RI loses its state in
// between the two characters, so it can't do this.
- assertEquals(0, out.remaining());
+ assertEquals(0, bytes.remaining());
+
+ // Did we get the UTF-8 for U+10000?
+ assertEquals(4, bytes.limit());
+ assertEquals((byte) 0xf0, bytes.get(0));
+ assertEquals((byte) 0x90, bytes.get(1));
+ assertEquals((byte) 0x80, bytes.get(2));
+ assertEquals((byte) 0x80, bytes.get(3));
// See what we got in the output buffer by decoding and checking that we
// get back the same surrogate pair.
- out.flip();
- CharBuffer chars = utf8.newDecoder().decode(out);
+ bytes.flip();
+ CharBuffer chars = utf8.newDecoder().decode(bytes);
+ assertEquals(0, bytes.remaining());
+ assertEquals(2, chars.limit());
assertEquals(0xd800, chars.get(0));
assertEquals(0xdc00, chars.get(1));
}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetDecoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetDecoderTest.java
index 9cd59ea..7fbe9e7 100644
--- a/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetDecoderTest.java
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetDecoderTest.java
@@ -4,9 +4,9 @@
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -600,6 +600,15 @@ public class CharsetDecoderTest extends TestCase {
public void testFlushIllegalState() throws CharacterCodingException {
ByteBuffer in = ByteBuffer.wrap(new byte[] { 98, 98 });
CharBuffer out = CharBuffer.allocate(5);
+
+ // Illegal state: after reset.
+ decoder.reset();
+ try {
+ decoder.flush(out);
+ fail();
+ } catch (IllegalStateException expected) {
+ }
+
// Normal case: after decode with endOfInput is true
decoder.reset();
decoder.decode(in, out, true);
@@ -607,23 +616,19 @@ public class CharsetDecoderTest extends TestCase {
CoderResult result = decoder.flush(out);
assertSame(result, CoderResult.UNDERFLOW);
- // Illegal state: flush twice
- try {
- decoder.flush(out);
- fail("should throw IllegalStateException");
- } catch (IllegalStateException e) {
- }
+ // Good state: flush twice
+ decoder.flush(out);
// Illegal state: flush after decode with endOfInput is false
decoder.reset();
decoder.decode(in, out, false);
try {
decoder.flush(out);
- fail("should throw IllegalStateException");
- } catch (IllegalStateException e) {
+ fail();
+ } catch (IllegalStateException expected) {
}
}
-
+
// test illegal states for decode facade
public void testDecodeFacadeIllegalState() throws CharacterCodingException {
// decode facade can be execute in anywhere
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetEncoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetEncoderTest.java
index ef219be..b63f4d9 100644
--- a/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetEncoderTest.java
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetEncoderTest.java
@@ -278,34 +278,36 @@ public class CharsetEncoderTest extends TestCase {
assertSame(encoder, encoder.reset());
}
- public void testFlushIllegalState() throws CharacterCodingException {
- CharBuffer in = CharBuffer.wrap("aaa");
- ByteBuffer out = ByteBuffer.allocate(5);
-
- // Normal case: after encode with endOfInput is true
- assertSame(encoder, encoder.reset());
- encoder.encode(in, out, true);
- out.rewind();
- CoderResult result = encoder.flush(out);
-
- // Illegal state: flush twice
- try {
- encoder.flush(out);
- fail("should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // Expected
- }
+ public void testFlushIllegalState() throws CharacterCodingException {
+ CharBuffer in = CharBuffer.wrap("aaa");
+ ByteBuffer out = ByteBuffer.allocate(5);
+
+ // Illegal state: after reset.
+ encoder.reset();
+ try {
+ encoder.flush(out);
+ fail();
+ } catch (IllegalStateException expected) {
+ }
- // Illegal state: flush after encode with endOfInput is false
- assertSame(encoder, encoder.reset());
- encoder.encode(in, out, false);
- try {
- encoder.flush(out);
- fail("should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // Expected
- }
- }
+ // Normal case: after encode with endOfInput is true
+ assertSame(encoder, encoder.reset());
+ encoder.encode(in, out, true);
+ out.rewind();
+ CoderResult result = encoder.flush(out);
+
+ // Good state: flush twice
+ encoder.flush(out);
+
+ // Illegal state: flush after encode with endOfInput is false
+ assertSame(encoder, encoder.reset());
+ encoder.encode(in, out, false);
+ try {
+ encoder.flush(out);
+ fail();
+ } catch (IllegalStateException expected) {
+ }
+ }
public void testFlushAfterConstructing() {
ByteBuffer out = ByteBuffer.allocate(5);
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetTest.java
index adee76e..92f230e 100644
--- a/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetTest.java
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetTest.java
@@ -136,17 +136,24 @@ public class CharsetTest extends TestCase {
}
public void test_EUC_JP_replacement_character() throws Exception {
- assertEncodes(Charset.forName("EUC-JP"), "\ufffd", 0xf4, 0xfe);
+ // We have text either side of the replacement character, because all kinds of errors
+ // could lead to a replacement character being returned.
+ assertEncodes(Charset.forName("EUC-JP"), " \ufffd ", ' ', 0xf4, 0xfe, ' ');
+ assertDecodes(Charset.forName("EUC-JP"), " \ufffd ", ' ', 0xf4, 0xfe, ' ');
}
public void test_SCSU_replacement_character() throws Exception {
- assertDecodes(Charset.forName("SCSU"), "\ufffd", 14, 0xff);
- assertEncodes(Charset.forName("SCSU"), "\ufffd", 14, 0xff);
+ // We have text either side of the replacement character, because all kinds of errors
+ // could lead to a replacement character being returned.
+ assertEncodes(Charset.forName("SCSU"), " \ufffd ", ' ', 14, 0xff, 0xfd, ' ');
+ assertDecodes(Charset.forName("SCSU"), " \ufffd ", ' ', 14, 0xff, 0xfd, ' ');
}
public void test_Shift_JIS_replacement_character() throws Exception {
- assertDecodes(Charset.forName("Shift_JIS"), "\ufffd", 0xfc);
- assertEncodes(Charset.forName("Shift_JIS"), "\ufffd", 0xfc);
+ // We have text either side of the replacement character, because all kinds of errors
+ // could lead to a replacement character being returned.
+ assertEncodes(Charset.forName("Shift_JIS"), " \ufffd ", ' ', 0xfc, 0xfc, ' ');
+ assertDecodes(Charset.forName("Shift_JIS"), " \ufffd ", ' ', 0xfc, 0xfc, ' ');
}
public void test_UTF_16() throws Exception {
diff --git a/luni/src/main/java/java/nio/charset/CharsetDecoder.java b/luni/src/main/java/java/nio/charset/CharsetDecoder.java
index 7aa546c..7b53ceb 100644
--- a/luni/src/main/java/java/nio/charset/CharsetDecoder.java
+++ b/luni/src/main/java/java/nio/charset/CharsetDecoder.java
@@ -82,22 +82,22 @@ import java.nio.CharBuffer;
* @see java.nio.charset.CharsetEncoder
*/
public abstract class CharsetDecoder {
- private static final int INIT = 0;
- private static final int ONGOING = 1;
- private static final int END = 2;
- private static final int FLUSH = 3;
+ private static final String RESET = "RESET";
+ private static final String ONGOING = "ONGOING";
+ private static final String END_OF_INPUT = "END_OF_INPUT";
+ private static final String FLUSHED = "FLUSHED";
+
+ private final Charset charset;
private final float averageCharsPerByte;
private final float maxCharsPerByte;
- private final Charset cs;
-
- private CodingErrorAction malformedInputAction;
- private CodingErrorAction unmappableCharacterAction;
+ private String replacementChars = "\ufffd";
- private String replacementChars;
+ private String state = RESET;
- private int status;
+ private CodingErrorAction malformedInputAction = CodingErrorAction.REPORT;
+ private CodingErrorAction unmappableCharacterAction = CodingErrorAction.REPORT;
/**
* Constructs a new <code>CharsetDecoder</code> using the given
@@ -114,8 +114,7 @@ public abstract class CharsetDecoder {
* the maximum number of characters created by this decoder for
* one input byte, must be positive.
* @throws IllegalArgumentException
- * if <code>averageCharsPerByte</code> or
- * <code>maxCharsPerByte</code> is negative.
+ * if {@code averageCharsPerByte <= 0 || maxCharsPerByte <= 0 || averageCharsPerByte > maxCharsPerByte}.
*/
protected CharsetDecoder(Charset charset, float averageCharsPerByte, float maxCharsPerByte) {
if (averageCharsPerByte <= 0 || maxCharsPerByte <= 0) {
@@ -126,11 +125,7 @@ public abstract class CharsetDecoder {
}
this.averageCharsPerByte = averageCharsPerByte;
this.maxCharsPerByte = maxCharsPerByte;
- cs = charset;
- status = INIT;
- malformedInputAction = CodingErrorAction.REPORT;
- unmappableCharacterAction = CodingErrorAction.REPORT;
- replacementChars = "\ufffd";
+ this.charset = charset;
}
/**
@@ -145,7 +140,7 @@ public abstract class CharsetDecoder {
* Returns the {@link Charset} which this decoder uses.
*/
public final Charset charset() {
- return cs;
+ return charset;
}
/**
@@ -182,35 +177,30 @@ public abstract class CharsetDecoder {
* if another exception happened during the decode operation.
*/
public final CharBuffer decode(ByteBuffer in) throws CharacterCodingException {
- reset();
int length = (int) (in.remaining() * averageCharsPerByte);
- CharBuffer output = CharBuffer.allocate(length);
- CoderResult result = null;
- while (true) {
- result = decode(in, output, false);
- checkCoderResult(result);
- if (result.isUnderflow()) {
- break;
- } else if (result.isOverflow()) {
- output = allocateMore(output);
+ CharBuffer out = CharBuffer.allocate(length);
+
+ reset();
+
+ while (state != FLUSHED) {
+ CoderResult result = decode(in, out, true);
+ if (result == CoderResult.OVERFLOW) {
+ out = allocateMore(out);
+ continue; // No point trying to flush to an already-full buffer.
+ } else {
+ checkCoderResult(result);
}
- }
- result = decode(in, output, true);
- checkCoderResult(result);
- while (true) {
- result = flush(output);
- checkCoderResult(result);
- if (result.isOverflow()) {
- output = allocateMore(output);
+ result = flush(out);
+ if (result == CoderResult.OVERFLOW) {
+ out = allocateMore(out);
} else {
- break;
+ checkCoderResult(result);
}
}
- output.flip();
- status = FLUSH;
- return output;
+ out.flip();
+ return out;
}
/*
@@ -304,54 +294,42 @@ public abstract class CharsetDecoder {
* <code>BufferOverflowException</code>.
*/
public final CoderResult decode(ByteBuffer in, CharBuffer out, boolean endOfInput) {
- if (status == FLUSH || (!endOfInput && status == END)) {
- throw new IllegalStateException();
+ if (state != RESET && state != ONGOING && !(endOfInput && state == END_OF_INPUT)) {
+ throw illegalStateException();
}
- CoderResult result = null;
+ state = endOfInput ? END_OF_INPUT : ONGOING;
- // begin to decode
while (true) {
- CodingErrorAction action = null;
+ CoderResult result;
try {
result = decodeLoop(in, out);
} catch (BufferOverflowException ex) {
- // unexpected exception
throw new CoderMalfunctionError(ex);
} catch (BufferUnderflowException ex) {
- // unexpected exception
throw new CoderMalfunctionError(ex);
}
- /*
- * result handling
- */
- if (result.isUnderflow()) {
- int remaining = in.remaining();
- status = endOfInput ? END : ONGOING;
- if (endOfInput && remaining > 0) {
- result = CoderResult.malformedForLength(remaining);
+ if (result == CoderResult.UNDERFLOW) {
+ if (endOfInput && in.hasRemaining()) {
+ result = CoderResult.malformedForLength(in.remaining());
} else {
return result;
}
- }
- if (result.isOverflow()) {
+ } else if (result == CoderResult.OVERFLOW) {
return result;
}
- // set coding error handle action
- action = malformedInputAction;
- if (result.isUnmappable()) {
- action = unmappableCharacterAction;
- }
- // If the action is IGNORE or REPLACE, we should continue decoding.
- if (action == CodingErrorAction.REPLACE) {
+
+ // We have a real error, so do what the appropriate action tells us what to do...
+ CodingErrorAction action =
+ result.isUnmappable() ? unmappableCharacterAction : malformedInputAction;
+ if (action == CodingErrorAction.REPORT) {
+ return result;
+ } else if (action == CodingErrorAction.REPLACE) {
if (out.remaining() < replacementChars.length()) {
return CoderResult.OVERFLOW;
}
out.put(replacementChars);
- } else {
- if (action != CodingErrorAction.IGNORE)
- return result;
}
in.position(in.position() + result.length());
}
@@ -442,20 +420,15 @@ public abstract class CharsetDecoder {
* @return <code>CoderResult.UNDERFLOW</code> or
* <code>CoderResult.OVERFLOW</code>.
* @throws IllegalStateException
- * if this decoder hasn't read all input bytes during one
- * decoding process, which means neither after calling
- * {@link #decode(ByteBuffer) decode(ByteBuffer)} nor after
- * calling {@link #decode(ByteBuffer, CharBuffer, boolean)
- * decode(ByteBuffer, CharBuffer, boolean)} with true as value
- * for the last boolean parameter.
+ * if this decoder isn't already flushed or at end of input.
*/
public final CoderResult flush(CharBuffer out) {
- if (status != END && status != INIT) {
- throw new IllegalStateException();
+ if (state != FLUSHED && state != END_OF_INPUT) {
+ throw illegalStateException();
}
CoderResult result = implFlush(out);
if (result == CoderResult.UNDERFLOW) {
- status = FLUSH;
+ state = FLUSHED;
}
return result;
}
@@ -582,7 +555,7 @@ public abstract class CharsetDecoder {
* the new action on malformed input error.
* @return this decoder.
* @throws IllegalArgumentException
- * if {@code newAction} is {@code null}.
+ * if {@code newAction == null}.
*/
public final CharsetDecoder onMalformedInput(CodingErrorAction newAction) {
if (newAction == null) {
@@ -604,7 +577,7 @@ public abstract class CharsetDecoder {
* the new action on unmappable character error.
* @return this decoder.
* @throws IllegalArgumentException
- * if {@code newAction} is {@code null}.
+ * if {@code newAction == null}.
*/
public final CharsetDecoder onUnmappableCharacter(CodingErrorAction newAction) {
if (newAction == null) {
@@ -631,8 +604,8 @@ public abstract class CharsetDecoder {
* new replacement as argument.
*
* @param replacement
- * the replacement string, cannot be null or empty. Its length
- * cannot be larger than {@link #maxCharsPerByte()}.
+ * the replacement string cannot be null, empty, or longer
+ * than {@link #maxCharsPerByte()}.
* @return this decoder.
* @throws IllegalArgumentException
* if the given replacement cannot satisfy the requirement
@@ -655,14 +628,12 @@ public abstract class CharsetDecoder {
}
/**
- * Resets this decoder. This method will reset the internal status, and then
- * calls <code>implReset()</code> to reset any status related to the
+ * Resets this decoder. This method will reset the internal state, and then
+ * calls {@link #implReset} to reset any state related to the
* specific charset.
- *
- * @return this decoder.
*/
public final CharsetDecoder reset() {
- status = INIT;
+ state = RESET;
implReset();
return this;
}
@@ -674,4 +645,8 @@ public abstract class CharsetDecoder {
public CodingErrorAction unmappableCharacterAction() {
return unmappableCharacterAction;
}
+
+ private IllegalStateException illegalStateException() {
+ throw new IllegalStateException("State: " + state);
+ }
}
diff --git a/luni/src/main/java/java/nio/charset/CharsetEncoder.java b/luni/src/main/java/java/nio/charset/CharsetEncoder.java
index 5c4d3b3..9217bba 100644
--- a/luni/src/main/java/java/nio/charset/CharsetEncoder.java
+++ b/luni/src/main/java/java/nio/charset/CharsetEncoder.java
@@ -76,25 +76,22 @@ import java.util.Arrays;
* @see java.nio.charset.CharsetDecoder
*/
public abstract class CharsetEncoder {
- private static final int READY = 0;
- private static final int ONGOING = 1;
- private static final int END = 2;
- private static final int FLUSH = 3;
- private static final int INIT = 4;
+ private static final String RESET = "RESET";
+ private static final String ONGOING = "ONGOING";
+ private static final String END_OF_INPUT = "END_OF_INPUT";
+ private static final String FLUSHED = "FLUSHED";
- private final Charset cs;
+ private final Charset charset;
private final float averageBytesPerChar;
private final float maxBytesPerChar;
private byte[] replacementBytes;
- private int status;
- // internal status indicates encode(CharBuffer) operation is finished
- private boolean finished;
+ private String state = RESET;
- private CodingErrorAction malformedInputAction;
- private CodingErrorAction unmappableCharacterAction;
+ private CodingErrorAction malformedInputAction = CodingErrorAction.REPORT;
+ private CodingErrorAction unmappableCharacterAction = CodingErrorAction.REPORT;
// decoder instance for this encoder's charset, used for replacement value checking
private CharsetDecoder decoder;
@@ -139,12 +136,9 @@ public abstract class CharsetEncoder {
if (averageBytesPerChar > maxBytesPerChar) {
throw new IllegalArgumentException("averageBytesPerChar is greater than maxBytesPerChar");
}
- this.cs = cs;
+ this.charset = cs;
this.averageBytesPerChar = averageBytesPerChar;
this.maxBytesPerChar = maxBytesPerChar;
- status = INIT;
- malformedInputAction = CodingErrorAction.REPORT;
- unmappableCharacterAction = CodingErrorAction.REPORT;
if (trusted) {
// The RI enforces unnecessary restrictions on the replacement bytes. We trust ICU to
// know what it's doing. Doing so lets us support ICU's EUC-JP, SCSU, and Shift_JIS.
@@ -165,7 +159,7 @@ public abstract class CharsetEncoder {
/**
* Tests whether the given character can be encoded by this encoder.
*
- * <p>Note that this method may change the internal status of this encoder, so
+ * <p>Note that this method may change the internal state of this encoder, so
* it should not be called when another encoding process is ongoing,
* otherwise it will throw an <code>IllegalStateException</code>.
*
@@ -179,7 +173,7 @@ public abstract class CharsetEncoder {
* Tests whether the given <code>CharSequence</code> can be encoded by this
* encoder.
*
- * <p>Note that this method may change the internal status of this encoder, so
+ * <p>Note that this method may change the internal state of this encoder, so
* it should not be called when another encode process is ongoing, otherwise
* it will throw an <code>IllegalStateException</code>.
*
@@ -193,12 +187,13 @@ public abstract class CharsetEncoder {
cb = CharBuffer.wrap(sequence);
}
- if (status == FLUSH || status == INIT) {
- status = READY;
+ if (state == FLUSHED) {
+ reset();
}
- if (status != READY) {
- throw new IllegalStateException();
+ if (state != RESET) {
+ throw illegalStateException();
}
+
CodingErrorAction originalMalformedInputAction = malformedInputAction;
CodingErrorAction originalUnmappableCharacterAction = unmappableCharacterAction;
onMalformedInput(CodingErrorAction.REPORT);
@@ -219,7 +214,7 @@ public abstract class CharsetEncoder {
* Returns the {@link Charset} which this encoder uses.
*/
public final Charset charset() {
- return cs;
+ return charset;
}
/**
@@ -256,37 +251,27 @@ public abstract class CharsetEncoder {
public final ByteBuffer encode(CharBuffer in) throws CharacterCodingException {
int length = (int) (in.remaining() * averageBytesPerChar);
ByteBuffer out = ByteBuffer.allocate(length);
- if (in.hasRemaining() == false) {
- return out;
- }
reset();
- while (in.hasRemaining()) {
+ while (state != FLUSHED) {
CoderResult result = encode(in, out, true);
- if (result == CoderResult.UNDERFLOW) {
- break;
- } else if (result == CoderResult.OVERFLOW) {
+ if (result == CoderResult.OVERFLOW) {
out = allocateMore(out);
- continue;
+ continue; // No point trying to flush to an already-full buffer.
} else {
checkCoderResult(result);
}
result = flush(out);
- if (result == CoderResult.UNDERFLOW) {
- break;
- } else if (result == CoderResult.OVERFLOW) {
+ if (result == CoderResult.OVERFLOW) {
out = allocateMore(out);
- continue;
} else {
checkCoderResult(result);
}
}
out.flip();
- status = READY;
- finished = true;
return out;
}
@@ -371,26 +356,22 @@ public abstract class CharsetEncoder {
* <code>BufferUnderflowException</code>.
*/
public final CoderResult encode(CharBuffer in, ByteBuffer out, boolean endOfInput) {
- // If the previous step is encode(CharBuffer), then no more input is needed
- // thus endOfInput should not be false
- if (status == READY && finished && !endOfInput) {
- throw new IllegalStateException();
- }
- if (status == FLUSH || (!endOfInput && status == END)) {
- throw new IllegalStateException();
+ if (state != RESET && state != ONGOING && !(endOfInput && state == END_OF_INPUT)) {
+ throw illegalStateException();
}
- status = endOfInput ? END : ONGOING;
+ state = endOfInput ? END_OF_INPUT : ONGOING;
while (true) {
CoderResult result;
try {
result = encodeLoop(in, out);
- } catch (BufferOverflowException e) {
- throw new CoderMalfunctionError(e);
- } catch (BufferUnderflowException e) {
- throw new CoderMalfunctionError(e);
+ } catch (BufferOverflowException ex) {
+ throw new CoderMalfunctionError(ex);
+ } catch (BufferUnderflowException ex) {
+ throw new CoderMalfunctionError(ex);
}
+
if (result == CoderResult.UNDERFLOW) {
if (endOfInput && in.hasRemaining()) {
result = CoderResult.malformedForLength(in.remaining());
@@ -400,12 +381,13 @@ public abstract class CharsetEncoder {
} else if (result == CoderResult.OVERFLOW) {
return result;
}
+
+ // We have a real error, so do what the appropriate action tells us what to do...
CodingErrorAction action =
result.isUnmappable() ? unmappableCharacterAction : malformedInputAction;
if (action == CodingErrorAction.REPORT) {
return result;
- }
- if (action == CodingErrorAction.REPLACE) {
+ } else if (action == CodingErrorAction.REPLACE) {
if (out.remaining() < replacementBytes.length) {
return CoderResult.OVERFLOW;
}
@@ -473,20 +455,15 @@ public abstract class CharsetEncoder {
* @return <code>CoderResult.UNDERFLOW</code> or
* <code>CoderResult.OVERFLOW</code>.
* @throws IllegalStateException
- * if this encoder hasn't read all input characters during one
- * encoding process, which means neither after calling
- * {@link #encode(CharBuffer) encode(CharBuffer)} nor after
- * calling {@link #encode(CharBuffer, ByteBuffer, boolean)
- * encode(CharBuffer, ByteBuffer, boolean)} with {@code true}
- * for the last boolean parameter.
+ * if this encoder isn't already flushed or at end of input.
*/
public final CoderResult flush(ByteBuffer out) {
- if (status != END && status != READY) {
- throw new IllegalStateException();
+ if (state != FLUSHED && state != END_OF_INPUT) {
+ throw illegalStateException();
}
CoderResult result = implFlush(out);
if (result == CoderResult.UNDERFLOW) {
- status = FLUSH;
+ state = FLUSHED;
}
return result;
}
@@ -555,7 +532,7 @@ public abstract class CharsetEncoder {
*/
public boolean isLegalReplacement(byte[] replacement) {
if (decoder == null) {
- decoder = cs.newDecoder();
+ decoder = charset.newDecoder();
decoder.onMalformedInput(CodingErrorAction.REPORT);
decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
}
@@ -671,14 +648,12 @@ public abstract class CharsetEncoder {
}
/**
- * Resets this encoder. This method will reset the internal status and then
- * calls <code>implReset()</code> to reset any status related to the
+ * Resets this encoder. This method will reset the internal state and then
+ * calls {@link #implReset} to reset any state related to the
* specific charset.
- *
- * @return this encoder.
*/
public final CharsetEncoder reset() {
- status = INIT;
+ state = RESET;
implReset();
return this;
}
@@ -690,4 +665,8 @@ public abstract class CharsetEncoder {
public CodingErrorAction unmappableCharacterAction() {
return unmappableCharacterAction;
}
+
+ private IllegalStateException illegalStateException() {
+ throw new IllegalStateException("State: " + state);
+ }
}