@Override public void addComponent(int cIndex, ByteBuf buffer) { checkComponentIndex(cIndex); if (buffer == null) { throw new NullPointerException("buffer"); } if (buffer instanceof Iterable) { @SuppressWarnings("unchecked") Iterable<ByteBuf> composite = (Iterable<ByteBuf>) buffer; addComponents(cIndex, composite); return; } int readableBytes = buffer.readableBytes(); if (readableBytes == 0) { return; } // Consolidate if the number of components will exceed the allowed maximum by the current // operation. final int numComponents = components.size(); if (numComponents >= maxNumComponents) { final int capacity = components.get(numComponents - 1).endOffset + readableBytes; ByteBuf consolidated = buffer.unsafe().newBuffer(capacity); for (int i = 0; i < numComponents; i++) { ByteBuf b = components.get(i).buf; consolidated.writeBytes(b); b.unsafe().release(); } consolidated.writeBytes(buffer, buffer.readerIndex(), readableBytes); Component c = new Component(consolidated); c.endOffset = c.length; components.clear(); components.add(c); return; } // No need to consolidate - just add a component to the list. Component c = new Component(buffer.order(ByteOrder.BIG_ENDIAN).slice()); if (cIndex == components.size()) { components.add(c); if (cIndex == 0) { c.endOffset = readableBytes; } else { Component prev = components.get(cIndex - 1); c.offset = prev.endOffset; c.endOffset = c.offset + readableBytes; } } else { components.add(cIndex, c); updateComponentOffsets(cIndex); } }
@Override public ByteBuf copy(int index, int length) { checkIndex(index, length); ByteBuf copy = alloc().directBuffer(length, maxCapacity()); copy.writeBytes(this, index, length); return copy; }
@Test public void testCompositeWrappedBuffer() { ByteBuf header = buffer(12).order(order); ByteBuf payload = buffer(512).order(order); header.writeBytes(new byte[12]); payload.writeBytes(new byte[512]); ByteBuf buffer = wrappedBuffer(header, payload); assertEquals(12, header.readableBytes()); assertEquals(512, payload.readableBytes()); assertEquals(12 + 512, buffer.readableBytes()); assertEquals(2, buffer.nioBufferCount()); }
@Override public ByteBuf copy(int index, int length) { checkIndex(index, length); ByteBuf copy = alloc().heapBuffer(length, maxCapacity()); copy.writeBytes(memory, idx(index), length); return copy; }
/** * Creates a new buffer whose content is a copy of the specified {@code buffer}'s readable bytes. * The new buffer's {@code readerIndex} and {@code writerIndex} are {@code 0} and {@code * buffer.readableBytes} respectively. */ public static ByteBuf copiedBuffer(ByteBuf buffer) { int readable = buffer.readableBytes(); if (readable > 0) { ByteBuf copy = buffer(readable); copy.writeBytes(buffer, buffer.readerIndex(), readable); return copy; } else { return EMPTY_BUFFER; } }
@Test public void testWriteUtf8() { String usAscii = "Some UTF-8 like äÄ∏ŒŒ"; ByteBuf buf = ReferenceCountUtil.releaseLater(Unpooled.buffer(16)); buf.writeBytes(usAscii.getBytes(CharsetUtil.UTF_8)); ByteBuf buf2 = ReferenceCountUtil.releaseLater(Unpooled.buffer(16)); ByteBufUtil.writeUtf8(buf2, usAscii); Assert.assertEquals(buf, buf2); }
@Test public void testWriteUsAsciiString() { AsciiString usAscii = new AsciiString("NettyRocks"); ByteBuf buf = ReferenceCountUtil.releaseLater(Unpooled.buffer(16)); buf.writeBytes(usAscii.toString().getBytes(CharsetUtil.US_ASCII)); ByteBuf buf2 = ReferenceCountUtil.releaseLater(Unpooled.buffer(16)); ByteBufUtil.writeAscii(buf2, usAscii); Assert.assertEquals(buf, buf2); }
@Test public void testWriteUsAsciiWrapped() { String usAscii = "NettyRocks"; ByteBuf buf = Unpooled.unreleasableBuffer(ReferenceCountUtil.releaseLater(Unpooled.buffer(16))); assertWrapped(buf); buf.writeBytes(usAscii.getBytes(CharsetUtil.US_ASCII)); ByteBuf buf2 = Unpooled.unreleasableBuffer(ReferenceCountUtil.releaseLater(Unpooled.buffer(16))); assertWrapped(buf2); ByteBufUtil.writeAscii(buf2, usAscii); Assert.assertEquals(buf, buf2); }
@Override public void consolidate() { final int numComponents = numComponents(); if (numComponents <= 1) { return; } final Component last = components.get(numComponents - 1); final int capacity = last.endOffset; final ByteBuf consolidated = last.buf.unsafe().newBuffer(capacity); for (int i = 0; i < numComponents; i++) { ByteBuf b = components.get(i).buf; consolidated.writeBytes(b); b.unsafe().release(); } components.clear(); components.add(new Component(consolidated)); updateComponentOffsets(0); }
@Override public void consolidate(int cIndex, int numComponents) { checkComponentIndex(cIndex, numComponents); if (numComponents <= 1) { return; } final int endCIndex = cIndex + numComponents; final Component last = components.get(endCIndex - 1); final int capacity = last.endOffset - components.get(cIndex).offset; final ByteBuf consolidated = last.buf.unsafe().newBuffer(capacity); for (int i = cIndex; i < endCIndex; i++) { ByteBuf b = components.get(i).buf; consolidated.writeBytes(b); b.unsafe().release(); } components.subList(cIndex + 1, endCIndex).clear(); components.set(cIndex, new Component(consolidated)); updateComponentOffsets(cIndex); }
/** * This should only be called as last operation from a method as this may adjust the underlying * array of components and so affect the index etc. */ private void consolidateIfNeeded() { // Consolidate if the number of components will exceed the allowed maximum by the current // operation. final int numComponents = components.size(); if (numComponents > maxNumComponents) { final int capacity = components.get(numComponents - 1).endOffset; ByteBuf consolidated = allocBuffer(capacity); // We're not using foreach to avoid creating an iterator. // noinspection ForLoopReplaceableByForEach for (int i = 0; i < numComponents; i++) { Component c = components.get(i); ByteBuf b = c.buf; consolidated.writeBytes(b); c.freeIfNecessary(); } Component c = new Component(consolidated, true); c.endOffset = c.length; components.clear(); components.add(c); } }
@Override public CompositeByteBuf consolidate() { assert !freed; final int numComponents = numComponents(); if (numComponents <= 1) { return this; } final Component last = components.get(numComponents - 1); final int capacity = last.endOffset; final ByteBuf consolidated = allocBuffer(capacity); for (int i = 0; i < numComponents; i++) { Component c = components.get(i); ByteBuf b = c.buf; consolidated.writeBytes(b); c.freeIfNecessary(); } components.clear(); components.add(new Component(consolidated, true)); updateComponentOffsets(0); return this; }
@Override public CompositeByteBuf consolidate(int cIndex, int numComponents) { checkComponentIndex(cIndex, numComponents); if (numComponents <= 1) { return this; } final int endCIndex = cIndex + numComponents; final Component last = components.get(endCIndex - 1); final int capacity = last.endOffset - components.get(cIndex).offset; final ByteBuf consolidated = allocBuffer(capacity); for (int i = cIndex; i < endCIndex; i++) { Component c = components.get(i); ByteBuf b = c.buf; consolidated.writeBytes(b); c.freeIfNecessary(); } components.subList(cIndex + 1, endCIndex).clear(); components.set(cIndex, new Component(consolidated, true)); updateComponentOffsets(cIndex); return this; }
@Override public int writeBytes(ScatteringByteChannel in, int length) throws IOException { return buf.writeBytes(in, length); }
@Override public int writeBytes(InputStream in, int length) throws IOException { return buf.writeBytes(in, length); }
@Override public ByteBuf writeBytes(ByteBuffer src) { buf.writeBytes(src); return this; }
@Override public ByteBuf writeBytes(byte[] src, int srcIndex, int length) { buf.writeBytes(src, srcIndex, length); return this; }
@Override public ByteBuf writeBytes(byte[] src) { buf.writeBytes(src); return this; }
@Override public ByteBuf writeBytes(ByteBuf src, int length) { buf.writeBytes(src, length); return this; }
@Test public void testWrittenBuffersEquals() { // XXX Same tests than testEquals with written AggregateChannelBuffers ByteBuf a, b; // Different length. a = wrappedBuffer(new byte[] {1}).order(order); b = wrappedBuffer(wrappedBuffer(new byte[] {1}, new byte[1]).order(order)); // to enable writeBytes b.writerIndex(b.writerIndex() - 1); b.writeBytes(wrappedBuffer(new byte[] {2}).order(order)); assertFalse(ByteBufUtil.equals(a, b)); // Same content, same firstIndex, short length. a = wrappedBuffer(new byte[] {1, 2, 3}).order(order); b = wrappedBuffer(wrappedBuffer(new byte[] {1}, new byte[2]).order(order)); // to enable writeBytes b.writerIndex(b.writerIndex() - 2); b.writeBytes(wrappedBuffer(new byte[] {2}).order(order)); b.writeBytes(wrappedBuffer(new byte[] {3}).order(order)); assertTrue(ByteBufUtil.equals(a, b)); // Same content, different firstIndex, short length. a = wrappedBuffer(new byte[] {1, 2, 3}).order(order); b = wrappedBuffer(wrappedBuffer(new byte[] {0, 1, 2, 3, 4}, 1, 3).order(order)); // to enable writeBytes b.writerIndex(b.writerIndex() - 1); b.writeBytes(wrappedBuffer(new byte[] {0, 1, 2, 3, 4}, 3, 1).order(order)); assertTrue(ByteBufUtil.equals(a, b)); // Different content, same firstIndex, short length. a = wrappedBuffer(new byte[] {1, 2, 3}).order(order); b = freeLater(wrappedBuffer(wrappedBuffer(new byte[] {1, 2}, new byte[1]).order(order))); // to enable writeBytes b.writerIndex(b.writerIndex() - 1); b.writeBytes(wrappedBuffer(new byte[] {4}).order(order)); assertFalse(ByteBufUtil.equals(a, b)); // Different content, different firstIndex, short length. a = wrappedBuffer(new byte[] {1, 2, 3}).order(order); b = wrappedBuffer(wrappedBuffer(new byte[] {0, 1, 2, 4, 5}, 1, 3).order(order)); // to enable writeBytes b.writerIndex(b.writerIndex() - 1); b.writeBytes(wrappedBuffer(new byte[] {0, 1, 2, 4, 5}, 3, 1).order(order)); assertFalse(ByteBufUtil.equals(a, b)); // Same content, same firstIndex, long length. a = wrappedBuffer(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}).order(order); b = freeLater(wrappedBuffer(wrappedBuffer(new byte[] {1, 2, 3}, new byte[7])).order(order)); // to enable writeBytes b.writerIndex(b.writerIndex() - 7); b.writeBytes(wrappedBuffer(new byte[] {4, 5, 6}).order(order)); b.writeBytes(wrappedBuffer(new byte[] {7, 8, 9, 10}).order(order)); assertTrue(ByteBufUtil.equals(a, b)); // Same content, different firstIndex, long length. a = wrappedBuffer(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}).order(order); b = wrappedBuffer( wrappedBuffer(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 1, 10).order(order)); // to enable writeBytes b.writerIndex(b.writerIndex() - 5); b.writeBytes( wrappedBuffer(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 6, 5).order(order)); assertTrue(ByteBufUtil.equals(a, b)); // Different content, same firstIndex, long length. a = wrappedBuffer(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}).order(order); b = freeLater( wrappedBuffer(wrappedBuffer(new byte[] {1, 2, 3, 4, 6}, new byte[5])).order(order)); // to enable writeBytes b.writerIndex(b.writerIndex() - 5); b.writeBytes(wrappedBuffer(new byte[] {7, 8, 5, 9, 10}).order(order)); assertFalse(ByteBufUtil.equals(a, b)); // Different content, different firstIndex, long length. a = wrappedBuffer(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}).order(order); b = wrappedBuffer( wrappedBuffer(new byte[] {0, 1, 2, 3, 4, 6, 7, 8, 5, 9, 10, 11}, 1, 10).order(order)); // to enable writeBytes b.writerIndex(b.writerIndex() - 5); b.writeBytes( wrappedBuffer(new byte[] {0, 1, 2, 3, 4, 6, 7, 8, 5, 9, 10, 11}, 6, 5).order(order)); assertFalse(ByteBufUtil.equals(a, b)); }
@Override public void addComponents(int cIndex, ByteBuf... buffers) { checkComponentIndex(cIndex); if (buffers == null) { throw new NullPointerException("buffers"); } ByteBuf lastBuf = null; int cnt = 0; int readableBytes = 0; for (ByteBuf b : buffers) { if (b == null) { break; } lastBuf = b; cnt++; readableBytes += b.readableBytes(); } if (readableBytes == 0) { return; } // Consolidate if the number of components will exceed the maximum by this operation. final int numComponents = components.size(); if (numComponents + cnt > maxNumComponents) { final ByteBuf consolidated; if (numComponents != 0) { final int capacity = components.get(numComponents - 1).endOffset + readableBytes; consolidated = lastBuf.unsafe().newBuffer(capacity); for (int i = 0; i < cIndex; i++) { ByteBuf b = components.get(i).buf; consolidated.writeBytes(b); b.unsafe().release(); } for (ByteBuf b : buffers) { if (b == null) { break; } consolidated.writeBytes(b, b.readerIndex(), b.readableBytes()); } for (int i = cIndex; i < numComponents; i++) { ByteBuf b = components.get(i).buf; consolidated.writeBytes(b); b.unsafe().release(); } } else { consolidated = lastBuf.unsafe().newBuffer(readableBytes); for (ByteBuf b : buffers) { if (b == null) { break; } consolidated.writeBytes(b, b.readerIndex(), b.readableBytes()); } } Component c = new Component(consolidated); c.endOffset = c.length; components.clear(); components.add(c); updateComponentOffsets(0); return; } // No need for consolidation for (ByteBuf b : buffers) { if (b == null) { break; } if (b.readable()) { addComponent(cIndex++, b); } } }