This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-io.git
The following commit(s) were added to refs/heads/master by this push: new 117e2195 Add CharSequenceInputStream.Builder.setCharsetEncoder(CharsetEncoder) 117e2195 is described below commit 117e21958322bbeeef73c37cc3210317abb4bf3f Author: Gary Gregory <garydgreg...@gmail.com> AuthorDate: Sat Jun 3 09:33:36 2023 -0400 Add CharSequenceInputStream.Builder.setCharsetEncoder(CharsetEncoder) Add CharsetEncoders.toCharsetEncoder(CharsetEncoder, Supplier<CharsetEncoder>) --- src/changes/changes.xml | 8 ++- .../apache/commons/io/charset/CharsetEncoders.java | 15 ++++- .../commons/io/input/CharSequenceInputStream.java | 66 ++++++++++++++++++---- .../apache/commons/io/input/ReaderInputStream.java | 22 +++++--- .../io/input/CharSequenceInputStreamTest.java | 17 ++++++ 5 files changed, 109 insertions(+), 19 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index ba1ddaea..b08cd669 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -99,7 +99,13 @@ The <action> type attribute can be add,update,fix,remove. Add AbstractOrigin.size(). </action> <action dev="ggregory" type="add" due-to="Gary Gregory"> - PathUtils.EMPTY_FILE_ATTRIBUTE_ARRAY. + Add PathUtils.EMPTY_FILE_ATTRIBUTE_ARRAY. + </action> + <action dev="ggregory" type="add" due-to="Gary Gregory"> + Add CharSequenceInputStream.Builder.setCharsetEncoder(CharsetEncoder). + </action> + <action dev="ggregory" type="add" due-to="Gary Gregory"> + Add CharsetEncoders.toCharsetEncoder(CharsetEncoder, Supplier<CharsetEncoder>). </action> <!-- UPDATE --> <action dev="ggregory" type="update" due-to="Gary Gregory, Dependabot"> diff --git a/src/main/java/org/apache/commons/io/charset/CharsetEncoders.java b/src/main/java/org/apache/commons/io/charset/CharsetEncoders.java index 8c426edd..fe8c4c27 100644 --- a/src/main/java/org/apache/commons/io/charset/CharsetEncoders.java +++ b/src/main/java/org/apache/commons/io/charset/CharsetEncoders.java @@ -19,6 +19,7 @@ package org.apache.commons.io.charset; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; +import java.util.function.Supplier; /** * Works with {@link CharsetEncoder}. @@ -34,7 +35,19 @@ public final class CharsetEncoders { * @return the given non-null CharsetEncoder or a new default CharsetEncoder. */ public static CharsetEncoder toCharsetEncoder(final CharsetEncoder charsetEncoder) { - return charsetEncoder != null ? charsetEncoder : Charset.defaultCharset().newEncoder(); + return toCharsetEncoder(charsetEncoder, () -> Charset.defaultCharset().newEncoder()); + } + + /** + * Returns the given non-null CharsetEncoder or a new default CharsetEncoder. + * + * @param charsetEncoder The CharsetEncoder to test. + * @param defaultSupplier The CharsetEncoder supplier to get when charsetEncoder is null. + * @return the given non-null CharsetEncoder or a new default CharsetEncoder. + * @since 2.13.0 + */ + public static CharsetEncoder toCharsetEncoder(final CharsetEncoder charsetEncoder, final Supplier<CharsetEncoder> defaultSupplier) { + return charsetEncoder != null ? charsetEncoder : defaultSupplier.get(); } /** No instances. */ diff --git a/src/main/java/org/apache/commons/io/input/CharSequenceInputStream.java b/src/main/java/org/apache/commons/io/input/CharSequenceInputStream.java index 41ed2552..a87d08c1 100644 --- a/src/main/java/org/apache/commons/io/input/CharSequenceInputStream.java +++ b/src/main/java/org/apache/commons/io/input/CharSequenceInputStream.java @@ -33,6 +33,7 @@ import java.util.Objects; import org.apache.commons.io.Charsets; import org.apache.commons.io.IOUtils; import org.apache.commons.io.build.AbstractStreamBuilder; +import org.apache.commons.io.charset.CharsetEncoders; import org.apache.commons.io.function.Uncheck; /** @@ -50,12 +51,22 @@ public class CharSequenceInputStream extends InputStream { * <p> * For example: * </p> - * + * <h2>Using a Charset</h2> + * <pre>{@code + * CharSequenceInputStream s = CharSequenceInputStream.builder() + * .setBufferSize(8192) + * .setCharSequence("String") + * .setCharset(Charset.defaultCharset()) + * .get();} + * </pre> + * <h2>Using a CharsetEncoder</h2> * <pre>{@code * CharSequenceInputStream s = CharSequenceInputStream.builder() * .setBufferSize(8192) * .setCharSequence("String") - * .setCharsetEncoder(Charset.defaultCharset()) + * .setCharsetEncoder(Charset.defaultCharset().newEncoder() + * .onMalformedInput(CodingErrorAction.REPLACE) + * .onUnmappableCharacter(CodingErrorAction.REPLACE)) * .get();} * </pre> * @@ -63,6 +74,8 @@ public class CharSequenceInputStream extends InputStream { */ public static class Builder extends AbstractStreamBuilder<CharSequenceInputStream, Builder> { + private CharsetEncoder charsetEncoder = newEncoder(getCharset()); + /** * Constructs a new instance. * <p> @@ -74,7 +87,31 @@ public class CharSequenceInputStream extends InputStream { */ @Override public CharSequenceInputStream get() { - return Uncheck.get(() -> new CharSequenceInputStream(getCharSequence(), getCharset(), getBufferSize())); + return Uncheck.get(() -> new CharSequenceInputStream(getCharSequence(), getBufferSize(), charsetEncoder)); + } + + CharsetEncoder getCharsetEncoder() { + return charsetEncoder; + } + + @Override + public Builder setCharset(final Charset charset) { + super.setCharset(charset); + charsetEncoder = newEncoder(getCharset()); + return this; + } + + /** + * Sets the charset encoder. Assumes that the caller has configured the encoder. + * + * @param newEncoder the charset encoder. + * @return this + * @since 2.13.0 + */ + public Builder setCharsetEncoder(final CharsetEncoder newEncoder) { + charsetEncoder = CharsetEncoders.toCharsetEncoder(newEncoder, () -> newEncoder(getCharsetDefault())); + super.setCharset(charsetEncoder.charset()); + return this; } } @@ -91,12 +128,19 @@ public class CharSequenceInputStream extends InputStream { return new Builder(); } - private final CharsetEncoder charsetEncoder; - private final CharBuffer cBuf; - private final ByteBuffer bBuf; + private static CharsetEncoder newEncoder(final Charset charset) { + // @formatter:off + return Charsets.toCharset(charset).newEncoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); + // @formatter:on + } - private int cBufMark; // position in cBuf + private final ByteBuffer bBuf; private int bBufMark; // position in bBuf + private final CharBuffer cBuf; + private int cBufMark; // position in cBuf + private final CharsetEncoder charsetEncoder; /** * Constructs a new instance with a buffer size of {@link IOUtils#DEFAULT_BUFFER_SIZE}. @@ -123,10 +167,12 @@ public class CharSequenceInputStream extends InputStream { @Deprecated public CharSequenceInputStream(final CharSequence cs, final Charset charset, final int bufferSize) { // @formatter:off - this.charsetEncoder = Charsets.toCharset(charset).newEncoder() - .onMalformedInput(CodingErrorAction.REPLACE) - .onUnmappableCharacter(CodingErrorAction.REPLACE); + this(cs, bufferSize, newEncoder(charset)); // @formatter:on + } + + private CharSequenceInputStream(final CharSequence cs, final int bufferSize, final CharsetEncoder charsetEncoder) { + this.charsetEncoder = charsetEncoder; // Ensure that buffer is long enough to hold a complete character this.bBuf = ByteBuffer.allocate(ReaderInputStream.checkMinBufferSize(charsetEncoder, bufferSize)); this.bBuf.flip(); diff --git a/src/main/java/org/apache/commons/io/input/ReaderInputStream.java b/src/main/java/org/apache/commons/io/input/ReaderInputStream.java index 69e0042a..0933079e 100644 --- a/src/main/java/org/apache/commons/io/input/ReaderInputStream.java +++ b/src/main/java/org/apache/commons/io/input/ReaderInputStream.java @@ -100,7 +100,7 @@ public class ReaderInputStream extends InputStream { */ public static class Builder extends AbstractStreamBuilder<ReaderInputStream, Builder> { - private CharsetEncoder charsetEncoder = super.getCharset().newEncoder(); + private CharsetEncoder charsetEncoder = newEncoder(getCharset()); /** * Constructs a new instance. @@ -130,24 +130,32 @@ public class ReaderInputStream extends InputStream { @Override public Builder setCharset(final Charset charset) { super.setCharset(charset); - charsetEncoder = getCharset().newEncoder(); + charsetEncoder = newEncoder(getCharset()); return this; } /** - * Sets the charset encoder. + * Sets the charset encoder. Assumes that the caller has configured the encoder. * - * @param charsetEncoder the charset encoder, null resets to a default encoder. + * @param newEncoder the charset encoder, null resets to a default encoder. * @return this */ - public Builder setCharsetEncoder(final CharsetEncoder charsetEncoder) { - this.charsetEncoder = CharsetEncoders.toCharsetEncoder(charsetEncoder); - super.setCharset(this.charsetEncoder.charset()); + public Builder setCharsetEncoder(final CharsetEncoder newEncoder) { + charsetEncoder = CharsetEncoders.toCharsetEncoder(newEncoder, () -> newEncoder(getCharsetDefault())); + super.setCharset(charsetEncoder.charset()); return this; } } + private static CharsetEncoder newEncoder(final Charset charset) { + // @formatter:off + return Charsets.toCharset(charset).newEncoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); + // @formatter:on + } + /** * Constructs a new {@link Builder}. * diff --git a/src/test/java/org/apache/commons/io/input/CharSequenceInputStreamTest.java b/src/test/java/org/apache/commons/io/input/CharSequenceInputStreamTest.java index 06620357..97c3f1d3 100644 --- a/src/test/java/org/apache/commons/io/input/CharSequenceInputStreamTest.java +++ b/src/test/java/org/apache/commons/io/input/CharSequenceInputStreamTest.java @@ -19,11 +19,13 @@ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.io.InputStream; +import java.io.StringReader; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Random; @@ -436,6 +438,21 @@ public class CharSequenceInputStreamTest { } } + @Test + public void testResetCharset() { + assertNotNull(CharSequenceInputStream.builder().setReader(new StringReader("\uD800")).setCharset((Charset) null).getCharset()); + } + + @Test + public void testResetCharsetEncoder() { + assertNotNull(CharSequenceInputStream.builder().setReader(new StringReader("\uD800")).setCharsetEncoder(null).getCharsetEncoder()); + } + + @Test + public void testResetCharsetName() { + assertNotNull(CharSequenceInputStream.builder().setReader(new StringReader("\uD800")).setCharset((String) null).getCharset()); + } + @Test public void testSingleByteRead_RequiredCharsets() throws IOException { for (final String csName : getRequiredCharsetNames()) {