* Resolved issue: NETTY-269 (Add ChannelBuffers.copiedBuffer() that accepts char[], CharBuffer, and CharSequence)
* Rewrote toString() and copiedBuffer() implementation * Removed unnecessary methods in CharsetUtil
This commit is contained in:
parent
33766a1f4f
commit
7036654647
@ -18,14 +18,18 @@ package org.jboss.netty.buffer;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
import java.nio.charset.CharacterCodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.UnsupportedCharsetException;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.CoderResult;
|
||||
|
||||
import org.jboss.netty.util.CharsetUtil;
|
||||
|
||||
/**
|
||||
* A NIO {@link ByteBuffer} based buffer. It is recommended to use {@link ChannelBuffers#directBuffer(int)}
|
||||
@ -302,23 +306,31 @@ public class ByteBufferBackedChannelBuffer extends AbstractChannelBuffer {
|
||||
}
|
||||
|
||||
public String toString(int index, int length, Charset charset) {
|
||||
if (!buffer.isReadOnly() && buffer.hasArray()) {
|
||||
if (length == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
final CharsetDecoder decoder = CharsetUtil.getDecoder(charset);
|
||||
final ByteBuffer src =
|
||||
((ByteBuffer) buffer.duplicate().position(
|
||||
index).limit(index + length)).order(order());
|
||||
final CharBuffer dst = CharBuffer.allocate(
|
||||
(int) ((double) length * decoder.maxCharsPerByte()));
|
||||
try {
|
||||
return new String(
|
||||
buffer.array(), index + buffer.arrayOffset(), length,
|
||||
charset.name());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new UnsupportedCharsetException(charset.name());
|
||||
CoderResult cr = decoder.decode(src, dst, true);
|
||||
if (!cr.isUnderflow()) {
|
||||
cr.throwException();
|
||||
}
|
||||
} else {
|
||||
byte[] tmp = new byte[length];
|
||||
((ByteBuffer) buffer.duplicate().position(index)).get(tmp);
|
||||
try {
|
||||
return new String(tmp, charset.name());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new UnsupportedCharsetException(charset.name());
|
||||
cr = decoder.flush(dst);
|
||||
if (!cr.isUnderflow()) {
|
||||
cr.throwException();
|
||||
}
|
||||
} catch (CharacterCodingException x) {
|
||||
throw new IllegalStateException(x);
|
||||
}
|
||||
|
||||
dst.flip();
|
||||
return dst.toString();
|
||||
}
|
||||
|
||||
public ChannelBuffer slice(int index, int length) {
|
||||
|
@ -15,14 +15,18 @@
|
||||
*/
|
||||
package org.jboss.netty.buffer;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.CharacterCodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.UnsupportedCharsetException;
|
||||
import java.nio.charset.CharsetEncoder;
|
||||
import java.nio.charset.CoderResult;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jboss.netty.util.CharsetUtil;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@link ChannelBuffer} by allocating new space or by wrapping
|
||||
@ -660,16 +664,159 @@ public class ChannelBuffers {
|
||||
|
||||
/**
|
||||
* Creates a new big-endian buffer whose content is the specified
|
||||
* {@code string} encoded by the specified {@code charsetName}.
|
||||
* {@code string} encoded in the specified {@code charset}.
|
||||
* The new buffer's {@code readerIndex} and {@code writerIndex} are
|
||||
* {@code 0} and the length of the encoded string respectively.
|
||||
*/
|
||||
public static ChannelBuffer copiedBuffer(String string, Charset charset) {
|
||||
return copiedBuffer(BIG_ENDIAN, string, charset);
|
||||
public static ChannelBuffer copiedBuffer(CharSequence string, Charset charset) {
|
||||
return copiedBuffer(BIG_ENDIAN, string, 0, string.length(), charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #copiedBuffer(String, Charset)} instead.
|
||||
* Creates a new big-endian buffer whose content is a subregion of
|
||||
* the specified {@code string} encoded in the specified {@code charset}.
|
||||
* The new buffer's {@code readerIndex} and {@code writerIndex} are
|
||||
* {@code 0} and the length of the encoded string respectively.
|
||||
*/
|
||||
public static ChannelBuffer copiedBuffer(
|
||||
CharSequence string, int offset, int length, Charset charset) {
|
||||
return copiedBuffer(BIG_ENDIAN, string, offset, length, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new buffer with the specified {@code endianness} whose
|
||||
* content is the specified {@code string} encoded in the specified
|
||||
* {@code charset}. The new buffer's {@code readerIndex} and
|
||||
* {@code writerIndex} are {@code 0} and the length of the encoded string
|
||||
* respectively.
|
||||
*/
|
||||
public static ChannelBuffer copiedBuffer(ByteOrder endianness, CharSequence string, Charset charset) {
|
||||
return copiedBuffer(endianness, string, 0, string.length(), charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new buffer with the specified {@code endianness} whose
|
||||
* content is a subregion of the specified {@code string} encoded in the
|
||||
* specified {@code charset}. The new buffer's {@code readerIndex} and
|
||||
* {@code writerIndex} are {@code 0} and the length of the encoded string
|
||||
* respectively.
|
||||
*/
|
||||
public static ChannelBuffer copiedBuffer(
|
||||
ByteOrder endianness, CharSequence string, int offset, int length, Charset charset) {
|
||||
if (string == null) {
|
||||
throw new NullPointerException("string");
|
||||
}
|
||||
if (length == 0) {
|
||||
return EMPTY_BUFFER;
|
||||
}
|
||||
return copiedBuffer(
|
||||
endianness, CharBuffer.wrap(string, offset, offset + length),
|
||||
charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new big-endian buffer whose content is the specified
|
||||
* {@code array} encoded in the specified {@code charset}.
|
||||
* The new buffer's {@code readerIndex} and {@code writerIndex} are
|
||||
* {@code 0} and the length of the encoded string respectively.
|
||||
*/
|
||||
public static ChannelBuffer copiedBuffer(char[] array, Charset charset) {
|
||||
return copiedBuffer(BIG_ENDIAN, array, 0, array.length, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new big-endian buffer whose content is a subregion of
|
||||
* the specified {@code array} encoded in the specified {@code charset}.
|
||||
* The new buffer's {@code readerIndex} and {@code writerIndex} are
|
||||
* {@code 0} and the length of the encoded string respectively.
|
||||
*/
|
||||
public static ChannelBuffer copiedBuffer(
|
||||
char[] array, int offset, int length, Charset charset) {
|
||||
return copiedBuffer(BIG_ENDIAN, array, offset, length, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new buffer with the specified {@code endianness} whose
|
||||
* content is the specified {@code array} encoded in the specified
|
||||
* {@code charset}. The new buffer's {@code readerIndex} and
|
||||
* {@code writerIndex} are {@code 0} and the length of the encoded string
|
||||
* respectively.
|
||||
*/
|
||||
public static ChannelBuffer copiedBuffer(ByteOrder endianness, char[] array, Charset charset) {
|
||||
return copiedBuffer(endianness, array, 0, array.length, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new buffer with the specified {@code endianness} whose
|
||||
* content is a subregion of the specified {@code array} encoded in the
|
||||
* specified {@code charset}. The new buffer's {@code readerIndex} and
|
||||
* {@code writerIndex} are {@code 0} and the length of the encoded string
|
||||
* respectively.
|
||||
*/
|
||||
public static ChannelBuffer copiedBuffer(
|
||||
ByteOrder endianness, char[] array, int offset, int length, Charset charset) {
|
||||
if (array == null) {
|
||||
throw new NullPointerException("array");
|
||||
}
|
||||
if (length == 0) {
|
||||
return EMPTY_BUFFER;
|
||||
}
|
||||
return copiedBuffer(
|
||||
endianness, CharBuffer.wrap(array, offset, length), charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new big-endian buffer whose content is the specified NIO
|
||||
* {@code buffer} encoded in the specified {@code charset}.
|
||||
* The new buffer's {@code readerIndex} and {@code writerIndex} are
|
||||
* {@code 0} and the length of the encoded string respectively.
|
||||
*/
|
||||
public static ChannelBuffer copiedBuffer(CharBuffer buffer, Charset charset) {
|
||||
return copiedBuffer(BIG_ENDIAN, buffer, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new buffer with the specified {@code endianness} whose
|
||||
* content is the specified {@code string} encoded in the specified
|
||||
* NIO {@code buffer}. The new buffer's {@code readerIndex} and
|
||||
* {@code writerIndex} are {@code 0} and the length of the encoded string
|
||||
* respectively.
|
||||
*/
|
||||
public static ChannelBuffer copiedBuffer(ByteOrder endianness, CharBuffer buffer, Charset charset) {
|
||||
if (endianness == null) {
|
||||
throw new NullPointerException("endianness");
|
||||
}
|
||||
if (buffer == null) {
|
||||
throw new NullPointerException("buffer");
|
||||
}
|
||||
if (!buffer.hasRemaining()) {
|
||||
return EMPTY_BUFFER;
|
||||
}
|
||||
|
||||
CharsetEncoder encoder = CharsetUtil.getEncoder(charset);
|
||||
CharBuffer src = buffer;
|
||||
ByteBuffer dst = ByteBuffer.allocate(
|
||||
(int) ((double) buffer.remaining() * encoder.maxBytesPerChar()));
|
||||
try {
|
||||
CoderResult cr = encoder.encode(src, dst, true);
|
||||
if (!cr.isUnderflow()) {
|
||||
cr.throwException();
|
||||
}
|
||||
cr = encoder.flush(dst);
|
||||
if (!cr.isUnderflow()) {
|
||||
cr.throwException();
|
||||
}
|
||||
} catch (CharacterCodingException x) {
|
||||
throw new IllegalStateException(x);
|
||||
}
|
||||
|
||||
ChannelBuffer result = wrappedBuffer(endianness, dst.array());
|
||||
result.writerIndex(dst.position());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #copiedBuffer(CharSequence, Charset)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static ChannelBuffer copiedBuffer(String string, String charsetName) {
|
||||
@ -677,22 +824,7 @@ public class ChannelBuffers {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new buffer with the specified {@code endianness} whose
|
||||
* content is the specified {@code string} encoded by the specified
|
||||
* {@code charsetName}. The new buffer's {@code readerIndex} and
|
||||
* {@code writerIndex} are {@code 0} and the length of the encoded string
|
||||
* respectively.
|
||||
*/
|
||||
public static ChannelBuffer copiedBuffer(ByteOrder endianness, String string, Charset charset) {
|
||||
try {
|
||||
return wrappedBuffer(endianness, string.getBytes(charset.name()));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new UnsupportedCharsetException(charset.name());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #copiedBuffer(ByteOrder, String, Charset)} instead.
|
||||
* @deprecated Use {@link #copiedBuffer(ByteOrder, CharSequence, Charset)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static ChannelBuffer copiedBuffer(ByteOrder endianness, String string, String charsetName) {
|
||||
|
@ -18,17 +18,21 @@ package org.jboss.netty.buffer;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
import java.nio.charset.CharacterCodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.UnsupportedCharsetException;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.CoderResult;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.jboss.netty.util.CharsetUtil;
|
||||
|
||||
|
||||
/**
|
||||
* A virtual buffer which shows multiple buffers as a single merged buffer. It
|
||||
@ -595,26 +599,45 @@ public class CompositeChannelBuffer extends AbstractChannelBuffer {
|
||||
index - indices[componentId], length, charset);
|
||||
}
|
||||
|
||||
if (length == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
byte[] data = new byte[length];
|
||||
int dataIndex = 0;
|
||||
int i = componentId;
|
||||
|
||||
while (length > 0) {
|
||||
int remaining = length;
|
||||
while (remaining > 0) {
|
||||
ChannelBuffer s = components[i];
|
||||
int adjustment = indices[i];
|
||||
int localLength = Math.min(length, s.capacity() - (index - adjustment));
|
||||
int localLength = Math.min(remaining, s.capacity() - (index - adjustment));
|
||||
s.getBytes(index - adjustment, data, dataIndex, localLength);
|
||||
index += localLength;
|
||||
dataIndex += localLength;
|
||||
length -= localLength;
|
||||
remaining -= localLength;
|
||||
i ++;
|
||||
}
|
||||
|
||||
final CharsetDecoder decoder = CharsetUtil.getDecoder(charset);
|
||||
final ByteBuffer src = ByteBuffer.wrap(data);
|
||||
final CharBuffer dst = CharBuffer.allocate(
|
||||
(int) ((double) length * decoder.maxCharsPerByte()));
|
||||
try {
|
||||
return new String(data, charset.name());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new UnsupportedCharsetException(charset.name());
|
||||
CoderResult cr = decoder.decode(src, dst, true);
|
||||
if (!cr.isUnderflow()) {
|
||||
cr.throwException();
|
||||
}
|
||||
cr = decoder.flush(dst);
|
||||
if (!cr.isUnderflow()) {
|
||||
cr.throwException();
|
||||
}
|
||||
} catch (CharacterCodingException x) {
|
||||
throw new IllegalStateException(x);
|
||||
}
|
||||
|
||||
dst.flip();
|
||||
return dst.toString();
|
||||
}
|
||||
|
||||
private int componentId(int index) {
|
||||
|
@ -18,13 +18,17 @@ package org.jboss.netty.buffer;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
import java.nio.charset.CharacterCodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.UnsupportedCharsetException;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.CoderResult;
|
||||
|
||||
import org.jboss.netty.util.CharsetUtil;
|
||||
|
||||
/**
|
||||
* A skeletal implementation for Java heap buffers.
|
||||
@ -208,10 +212,28 @@ public abstract class HeapChannelBuffer extends AbstractChannelBuffer {
|
||||
}
|
||||
|
||||
public String toString(int index, int length, Charset charset) {
|
||||
try {
|
||||
return new String(array, index, length, charset.name());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new UnsupportedCharsetException(charset.name());
|
||||
if (length == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
final CharsetDecoder decoder = CharsetUtil.getDecoder(charset);
|
||||
final ByteBuffer src = ByteBuffer.wrap(array, index, length);
|
||||
final CharBuffer dst = CharBuffer.allocate(
|
||||
(int) ((double) length * decoder.maxCharsPerByte()));
|
||||
try {
|
||||
CoderResult cr = decoder.decode(src, dst, true);
|
||||
if (!cr.isUnderflow()) {
|
||||
cr.throwException();
|
||||
}
|
||||
cr = decoder.flush(dst);
|
||||
if (!cr.isUnderflow()) {
|
||||
cr.throwException();
|
||||
}
|
||||
} catch (CharacterCodingException x) {
|
||||
throw new IllegalStateException(x);
|
||||
}
|
||||
|
||||
dst.flip();
|
||||
return dst.toString();
|
||||
}
|
||||
}
|
||||
|
@ -80,17 +80,6 @@ public class CharsetUtil {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a cached thread-local {@link CharsetEncoder} for the specified
|
||||
* <tt>charset</tt>.
|
||||
*/
|
||||
public static CharsetEncoder getEncoder(String charset) {
|
||||
if (charset == null) {
|
||||
throw new NullPointerException("charset");
|
||||
}
|
||||
return getEncoder(Charset.forName(charset));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cached thread-local {@link CharsetEncoder} for the specified
|
||||
* <tt>charset</tt>.
|
||||
@ -116,17 +105,6 @@ public class CharsetUtil {
|
||||
return e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cached thread-local {@link CharsetDecoder} for the specified
|
||||
* <tt>charset</tt>.
|
||||
*/
|
||||
public static CharsetDecoder getDecoder(String charset) {
|
||||
if (charset == null) {
|
||||
throw new NullPointerException("charset");
|
||||
}
|
||||
return getDecoder(Charset.forName(charset));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cached thread-local {@link CharsetDecoder} for the specified
|
||||
* <tt>charset</tt>.
|
||||
|
Loading…
Reference in New Issue
Block a user