Optimized CompositeChannelBuffer creation
This commit is contained in:
parent
ec80daae01
commit
5eb56831e8
@ -19,6 +19,8 @@ import java.io.UnsupportedEncodingException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.UnsupportedCharsetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
@ -338,16 +340,34 @@ public class ChannelBuffers {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ChannelBuffer[] wrappedBuffers = new ChannelBuffer[arrays.length];
|
||||
for (int i = 0; i < arrays.length; i ++) {
|
||||
wrappedBuffers[i] = wrappedBuffer(endianness, arrays[i]);
|
||||
// Get the list of the component, while guessing the byte order.
|
||||
final List<ChannelBuffer> components = new ArrayList<ChannelBuffer>(arrays.length);
|
||||
for (byte[] a: arrays) {
|
||||
if (a == null) {
|
||||
break;
|
||||
}
|
||||
if (a.length > 0) {
|
||||
components.add(wrappedBuffer(endianness, a));
|
||||
}
|
||||
}
|
||||
return wrappedBuffer(wrappedBuffers);
|
||||
return compositeBuffer(endianness, components);
|
||||
}
|
||||
|
||||
return EMPTY_BUFFER;
|
||||
}
|
||||
|
||||
private static ChannelBuffer compositeBuffer(
|
||||
ByteOrder endianness, List<ChannelBuffer> components) {
|
||||
switch (components.size()) {
|
||||
case 0:
|
||||
return EMPTY_BUFFER;
|
||||
case 1:
|
||||
return components.get(0);
|
||||
default:
|
||||
return new CompositeChannelBuffer(endianness, components);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new composite buffer which wraps the readable bytes of the
|
||||
* specified buffers without copying them. A modification on the content
|
||||
@ -367,11 +387,33 @@ public class ChannelBuffers {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
for (ChannelBuffer b: buffers) {
|
||||
if (b.readable()) {
|
||||
return new CompositeChannelBuffer(buffers);
|
||||
ByteOrder order = null;
|
||||
final List<ChannelBuffer> components = new ArrayList<ChannelBuffer>(buffers.length);
|
||||
for (ChannelBuffer c: buffers) {
|
||||
if (c == null) {
|
||||
break;
|
||||
}
|
||||
if (c.readable()) {
|
||||
if (order != null) {
|
||||
if (!order.equals(c.order())) {
|
||||
throw new IllegalArgumentException(
|
||||
"inconsistent byte order");
|
||||
}
|
||||
} else {
|
||||
order = c.order();
|
||||
}
|
||||
if (c instanceof CompositeChannelBuffer) {
|
||||
// Expand nested composition.
|
||||
components.addAll(
|
||||
((CompositeChannelBuffer) c).decompose(
|
||||
c.readerIndex(), c.readableBytes()));
|
||||
} else {
|
||||
// An ordinary buffer (non-composite)
|
||||
components.add(c.slice());
|
||||
}
|
||||
}
|
||||
}
|
||||
return compositeBuffer(order, components);
|
||||
}
|
||||
return EMPTY_BUFFER;
|
||||
}
|
||||
@ -395,11 +437,25 @@ public class ChannelBuffers {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ChannelBuffer[] wrappedBuffers = new ChannelBuffer[buffers.length];
|
||||
for (int i = 0; i < buffers.length; i ++) {
|
||||
wrappedBuffers[i] = wrappedBuffer(buffers[i]);
|
||||
ByteOrder order = null;
|
||||
final List<ChannelBuffer> components = new ArrayList<ChannelBuffer>(buffers.length);
|
||||
for (ByteBuffer b: buffers) {
|
||||
if (b == null) {
|
||||
break;
|
||||
}
|
||||
if (b.hasRemaining()) {
|
||||
if (order != null) {
|
||||
if (!order.equals(b.order())) {
|
||||
throw new IllegalArgumentException(
|
||||
"inconsistent byte order");
|
||||
}
|
||||
} else {
|
||||
order = b.order();
|
||||
}
|
||||
components.add(wrappedBuffer(b));
|
||||
}
|
||||
}
|
||||
return wrappedBuffer(wrappedBuffers);
|
||||
return compositeBuffer(order, components);
|
||||
}
|
||||
|
||||
return EMPTY_BUFFER;
|
||||
|
@ -48,44 +48,15 @@ public class CompositeChannelBuffer extends AbstractChannelBuffer {
|
||||
private int[] indices;
|
||||
private int lastAccessedComponentId;
|
||||
|
||||
public CompositeChannelBuffer(ChannelBuffer... buffers) {
|
||||
if (buffers.length == 0) {
|
||||
throw new IllegalArgumentException("buffers should not be empty.");
|
||||
}
|
||||
|
||||
// Get the list of the component, while guessing the byte order.
|
||||
ByteOrder expectedEndianness = null;
|
||||
final List<ChannelBuffer> newComponents = new ArrayList<ChannelBuffer>(buffers.length);
|
||||
for (ChannelBuffer c: buffers) {
|
||||
if (c.readableBytes() > 0) {
|
||||
expectedEndianness = c.order();
|
||||
if (c instanceof CompositeChannelBuffer) {
|
||||
// Expand nested composition.
|
||||
newComponents.addAll(
|
||||
((CompositeChannelBuffer) c).slice0(
|
||||
c.readerIndex(), c.readableBytes()));
|
||||
} else {
|
||||
// An ordinary buffer (non-composite)
|
||||
newComponents.add(c.slice());
|
||||
}
|
||||
} else if (c.capacity() != 0) {
|
||||
expectedEndianness = c.order();
|
||||
}
|
||||
}
|
||||
|
||||
if (expectedEndianness == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"buffers have only empty buffers.");
|
||||
}
|
||||
|
||||
order = expectedEndianness;
|
||||
setComponents(newComponents);
|
||||
public CompositeChannelBuffer(ByteOrder endianness, List<ChannelBuffer> buffers) {
|
||||
order = endianness;
|
||||
setComponents(buffers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same with {@link #slice(int, int)} except that this method returns a list.
|
||||
*/
|
||||
private List<ChannelBuffer> slice0(int index, int length) {
|
||||
public List<ChannelBuffer> decompose(int index, int length) {
|
||||
if (length == 0) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@ -556,9 +527,15 @@ public class CompositeChannelBuffer extends AbstractChannelBuffer {
|
||||
return ChannelBuffers.EMPTY_BUFFER;
|
||||
}
|
||||
|
||||
List<ChannelBuffer> listBuffer = slice0(index, length);
|
||||
ChannelBuffer[] buffers = listBuffer.toArray(new ChannelBuffer[listBuffer.size()]);
|
||||
return new CompositeChannelBuffer(buffers);
|
||||
List<ChannelBuffer> components = decompose(index, length);
|
||||
switch (components.size()) {
|
||||
case 0:
|
||||
return ChannelBuffers.EMPTY_BUFFER;
|
||||
case 1:
|
||||
return components.get(0);
|
||||
default:
|
||||
return new CompositeChannelBuffer(order(), components);
|
||||
}
|
||||
}
|
||||
|
||||
public ByteBuffer toByteBuffer(int index, int length) {
|
||||
@ -667,7 +644,7 @@ public class CompositeChannelBuffer extends AbstractChannelBuffer {
|
||||
int localWriterIndex = this.writerIndex();
|
||||
|
||||
final int bytesToMove = capacity() - localReaderIndex;
|
||||
List<ChannelBuffer> list = slice0(localReaderIndex, bytesToMove);
|
||||
List<ChannelBuffer> list = decompose(localReaderIndex, bytesToMove);
|
||||
|
||||
// Add a new buffer so that the capacity of this composite buffer does
|
||||
// not decrease due to the discarded components.
|
||||
|
Loading…
Reference in New Issue
Block a user