From 79a1fcb099fc01754b91a2baec5bddafea47eddc Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Mon, 13 Feb 2023 16:29:54 +0100 Subject: [PATCH] Polishing DataBuffer::write(CharSequence, Charset) See gh-29943 --- .../core/io/buffer/DataBuffer.java | 41 +++++++++---------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/io/buffer/DataBuffer.java b/spring-core/src/main/java/org/springframework/core/io/buffer/DataBuffer.java index 5d3e44f15f..6829c93a9e 100644 --- a/spring-core/src/main/java/org/springframework/core/io/buffer/DataBuffer.java +++ b/spring-core/src/main/java/org/springframework/core/io/buffer/DataBuffer.java @@ -19,10 +19,8 @@ package org.springframework.core.io.buffer; import java.io.Closeable; import java.io.InputStream; import java.io.OutputStream; -import java.io.UncheckedIOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; -import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; @@ -265,32 +263,31 @@ public interface DataBuffer { default DataBuffer write(CharSequence charSequence, Charset charset) { Assert.notNull(charSequence, "CharSequence must not be null"); Assert.notNull(charset, "Charset must not be null"); - if (charSequence.length() != 0) { - CharsetEncoder charsetEncoder = charset.newEncoder() + if (charSequence.length() > 0) { + CharsetEncoder encoder = charset.newEncoder() .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE); CharBuffer src = CharBuffer.wrap(charSequence); - int length = (int) (src.remaining() * charsetEncoder.maxBytesPerChar()); - ensureWritable(length); - try (ByteBufferIterator iterator = writableByteBuffers()) { - Assert.state(iterator.hasNext(), "No ByteBuffer available"); - ByteBuffer dest = iterator.next(); - int pos = dest.position(); - CoderResult cr = charsetEncoder.encode(src, dest, true); - if (!cr.isUnderflow()) { - cr.throwException(); + int cap = (int) (src.remaining() * encoder.averageBytesPerChar()); + while (true) { + ensureWritable(cap); + CoderResult cr; + try (ByteBufferIterator iterator = writableByteBuffers()) { + Assert.state(iterator.hasNext(), "No ByteBuffer available"); + ByteBuffer dest = iterator.next(); + cr = encoder.encode(src, dest, true); + if (cr.isUnderflow()) { + cr = encoder.flush(dest); + } + writePosition(dest.position()); } - cr = charsetEncoder.flush(dest); - if (!cr.isUnderflow()) { - cr.throwException(); + if (cr.isUnderflow()) { + break; + } + 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; }