Skip to content

Commit

Permalink
Writer.of(Appendable)
Browse files Browse the repository at this point in the history
  • Loading branch information
mkarg committed Dec 18, 2024
1 parent 5b703c7 commit 0bf767b
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 11 deletions.
53 changes: 42 additions & 11 deletions src/java.base/share/classes/java/io/StringWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,18 @@
* can be called after the stream has been closed without generating an
* {@code IOException}.
*
* @apiNote
* {@link Writer#of(Appendable)} provides a method to write into any
* {@link Appendable} that may be more efficient than {@code StringWriter}.
*
* @author Mark Reinhold
* @since 1.1
*/

public class StringWriter extends Writer {

private final StringBuffer buf;
private final Writer w;

/**
* Create a new string writer using the default initial string-buffer
Expand All @@ -51,6 +56,7 @@ public class StringWriter extends Writer {
public StringWriter() {
buf = new StringBuffer();
lock = buf;
w = Writer.of(buf);
}

/**
Expand All @@ -70,13 +76,18 @@ public StringWriter(int initialSize) {
}
buf = new StringBuffer(initialSize);
lock = buf;
w = Writer.of(buf);
}

/**
* Write a single character.
*/
public void write(int c) {
buf.append((char) c);
try {
w.write(c);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

/**
Expand All @@ -92,18 +103,22 @@ public void write(int c) {
* of the given array
*/
public void write(char[] cbuf, int off, int len) {
Objects.checkFromIndexSize(off, len, cbuf.length);
if (len == 0) {
return;
try {
w.write(cbuf, off, len);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
buf.append(cbuf, off, len);
}

/**
* Write a string.
*/
public void write(String str) {
buf.append(str);
try {
w.write(str);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

/**
Expand All @@ -119,7 +134,11 @@ public void write(String str) {
* of the given string
*/
public void write(String str, int off, int len) {
buf.append(str, off, off + len);
try {
w.write(str, off, len);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

/**
Expand Down Expand Up @@ -149,7 +168,11 @@ public void write(String str, int off, int len) {
* @since 1.5
*/
public StringWriter append(CharSequence csq) {
write(String.valueOf(csq));
try {
w.append(csq);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
return this;
}

Expand Down Expand Up @@ -188,8 +211,12 @@ public StringWriter append(CharSequence csq) {
* @since 1.5
*/
public StringWriter append(CharSequence csq, int start, int end) {
if (csq == null) csq = "null";
return append(csq.subSequence(start, end));
try {
w.append(csq, start, end);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
return this;
}

/**
Expand All @@ -210,7 +237,11 @@ public StringWriter append(CharSequence csq, int start, int end) {
* @since 1.5
*/
public StringWriter append(char c) {
write(c);
try {
w.append(c);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
return this;
}

Expand Down
113 changes: 113 additions & 0 deletions src/java.base/share/classes/java/io/Writer.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

package java.io;

import java.nio.CharBuffer;
import java.util.Objects;

/**
Expand Down Expand Up @@ -144,6 +145,118 @@ public void close() throws IOException {
};
}

/**
* Returns a {@code Writer} that writes characters into an
* {@code Appendable}. The writer is initially open and writing appends
* after the last character in the builder.
*
* <p> The resulting writer is not safe for use by multiple
* concurrent threads. If the writer is to be used by more than one
* thread it should be controlled by appropriate synchronization.
*
* <p> If the appendable changes while the writer is open, e.g. the length
* changes, the behavior is undefined.
*
* @param a {@code Appendable} consuming the character stream.
* @return a {@code Writer} which writes characters into {@code a}
* @throws NullPointerException if {@code a} is {@code null}
*
* @since 25
*/
public static Writer of(final Appendable a) {
Objects.requireNonNull(a);

return new Writer() {
private boolean isClosed;

/** Check to make sure that the stream has not been closed */
private void ensureOpen() throws IOException {
if (isClosed)
throw new IOException("Stream closed");
}

@Override
public void write(int c) throws IOException {
ensureOpen();
switch (a) {
case Writer w -> w.write(c);
default -> a.append((char) c);
}
}

@Override
public void write(char[] cbuf, int off, int len) throws IOException {
ensureOpen();
Objects.checkFromIndexSize(off, len, cbuf.length);
if (len == 0) {
return;
}
switch (a) {
case StringBuilder sb -> sb.append(cbuf, off, len);
case StringBuffer sb -> sb.append(cbuf, off, len);
case CharBuffer cb -> cb.put(cbuf, off, len);
case Writer w -> w.write(cbuf, off, len);
default -> {
for (int i = 0; i < len; i++)
a.append(cbuf[off + i]);
}
}
}

@Override
public void write(String str) throws IOException {
ensureOpen();
switch (a) {
case StringBuilder sb -> sb.append(str);
case StringBuffer sb -> sb.append(str);
case CharBuffer cb -> cb.put(str);
case Writer w -> w.write(str);
default -> a.append(str);
}
}

@Override
public void write(String str, int off, int len) throws IOException {
ensureOpen();
switch (a) {
case Writer w -> w.write(str, off, len);
default -> a.append(str, off, off + len);
}
}

@Override
public Writer append(CharSequence csq) throws IOException {
ensureOpen();
a.append(csq);
return this;
}

@Override
public Writer append(CharSequence csq, int start, int end) throws IOException {
ensureOpen();
a.append(csq, start, end);
return this;
}

@Override
public Writer append(char c) throws IOException {
ensureOpen();
a.append(c);
return this;
}

@Override
public void flush() throws IOException {
ensureOpen();
}

@Override
public void close() throws IOException {
isClosed = true;
}
};
}

/**
* The object used to synchronize operations on this stream. For
* efficiency, a character-stream object may use an object other than
Expand Down

0 comments on commit 0bf767b

Please sign in to comment.