Polishing DataBuffer::write(CharSequence, Charset)

See gh-29943
This commit is contained in:
Arjen Poutsma 2023-02-13 16:29:54 +01:00
parent 026be04b75
commit 79a1fcb099
1 changed files with 19 additions and 22 deletions

View File

@ -19,10 +19,8 @@ package org.springframework.core.io.buffer;
import java.io.Closeable; import java.io.Closeable;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.CharBuffer; import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder; import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult; import java.nio.charset.CoderResult;
@ -265,32 +263,31 @@ public interface DataBuffer {
default DataBuffer write(CharSequence charSequence, Charset charset) { default DataBuffer write(CharSequence charSequence, Charset charset) {
Assert.notNull(charSequence, "CharSequence must not be null"); Assert.notNull(charSequence, "CharSequence must not be null");
Assert.notNull(charset, "Charset must not be null"); Assert.notNull(charset, "Charset must not be null");
if (charSequence.length() != 0) { if (charSequence.length() > 0) {
CharsetEncoder charsetEncoder = charset.newEncoder() CharsetEncoder encoder = charset.newEncoder()
.onMalformedInput(CodingErrorAction.REPLACE) .onMalformedInput(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE); .onUnmappableCharacter(CodingErrorAction.REPLACE);
CharBuffer src = CharBuffer.wrap(charSequence); CharBuffer src = CharBuffer.wrap(charSequence);
int length = (int) (src.remaining() * charsetEncoder.maxBytesPerChar()); int cap = (int) (src.remaining() * encoder.averageBytesPerChar());
ensureWritable(length); while (true) {
try (ByteBufferIterator iterator = writableByteBuffers()) { ensureWritable(cap);
Assert.state(iterator.hasNext(), "No ByteBuffer available"); CoderResult cr;
ByteBuffer dest = iterator.next(); try (ByteBufferIterator iterator = writableByteBuffers()) {
int pos = dest.position(); Assert.state(iterator.hasNext(), "No ByteBuffer available");
CoderResult cr = charsetEncoder.encode(src, dest, true); ByteBuffer dest = iterator.next();
if (!cr.isUnderflow()) { cr = encoder.encode(src, dest, true);
cr.throwException(); if (cr.isUnderflow()) {
cr = encoder.flush(dest);
}
writePosition(dest.position());
} }
cr = charsetEncoder.flush(dest); if (cr.isUnderflow()) {
if (!cr.isUnderflow()) { break;
cr.throwException(); }
if (cr.isOverflow()) {
cap = 2 * cap + 1;
} }
length = dest.position() - pos;
} }
catch (CharacterCodingException ex) {
// should not happen, because the encoder uses action REPLACE
throw new UncheckedIOException(ex);
}
writePosition(writePosition() + length);
} }
return this; return this;
} }