You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2023/06/03 13:33:41 UTC

[commons-io] branch master updated: Add CharSequenceInputStream.Builder.setCharsetEncoder(CharsetEncoder)

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 <ga...@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&lt;CharsetEncoder&gt;).
       </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()) {