All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.dubbo.remoting.buffer.ChannelBuffer Maven / Gradle / Ivy

There is a newer version: 3.3.2
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.dubbo.remoting.buffer;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;

/**
 * A random and sequential accessible sequence of zero or more bytes (octets).
 * This interface provides an abstract view for one or more primitive byte
 * arrays ({@code byte[]}) and {@linkplain ByteBuffer NIO buffers}.
 * 

*

Creation of a buffer

*

* It is recommended to create a new buffer using the helper methods in {@link * ChannelBuffers} rather than calling an individual implementation's * constructor. *

*

Random Access Indexing

*

* Just like an ordinary primitive byte array, {@link ChannelBuffer} uses zero-based * indexing. It means the index of the first byte is always {@code 0} and * the index of the last byte is always {@link #capacity() capacity - 1}. For * example, to iterate all bytes of a buffer, you can do the following, * regardless of its internal implementation: *

*

 * {@link ChannelBuffer} buffer = ...;
 * for (int i = 0; i < buffer.capacity(); i ++) {
 *     byte b = buffer.getByte(i);
 *     System.out.println((char) b);
 * }
 * 
*

*

Sequential Access Indexing

*

* {@link ChannelBuffer} provides two pointer variables to support sequential * read and write operations - {@link #readerIndex() readerIndex} for a read * operation and {@link #writerIndex() writerIndex} for a write operation * respectively. The following diagram shows how a buffer is segmented into * three areas by the two pointers: *

*

 *      +-------------------+------------------+------------------+
 *      | discardable bytes |  readable bytes  |  writable bytes  |
 *      |                   |     (CONTENT)    |                  |
 *      +-------------------+------------------+------------------+
 *      |                   |                  |                  |
 *      0      <=      readerIndex   <=   writerIndex    <=    capacity
 * 
*

*

Readable bytes (the actual content)

*

* This segment is where the actual data is stored. Any operation whose name * starts with {@code read} or {@code skip} will get or skip the data at the * current {@link #readerIndex() readerIndex} and increase it by the number of * read bytes. If the argument of the read operation is also a {@link * ChannelBuffer} and no destination index is specified, the specified buffer's * {@link #readerIndex() readerIndex} is increased together. *

* If there's not enough content left, {@link IndexOutOfBoundsException} is * raised. The default value of newly allocated, wrapped or copied buffer's * {@link #readerIndex() readerIndex} is {@code 0}. *

*

 * // Iterates the readable bytes of a buffer.
 * {@link ChannelBuffer} buffer = ...;
 * while (buffer.readable()) {
 *     System.out.println(buffer.readByte());
 * }
 * 
*

*

Writable bytes

*

* This segment is a undefined space which needs to be filled. Any operation * whose name ends with {@code write} will write the data at the current {@link * #writerIndex() writerIndex} and increase it by the number of written bytes. * If the argument of the write operation is also a {@link ChannelBuffer}, and * no source index is specified, the specified buffer's {@link #readerIndex() * readerIndex} is increased together. *

* If there's not enough writable bytes left, {@link IndexOutOfBoundsException} * is raised. The default value of newly allocated buffer's {@link * #writerIndex() writerIndex} is {@code 0}. The default value of wrapped or * copied buffer's {@link #writerIndex() writerIndex} is the {@link #capacity() * capacity} of the buffer. *

*

 * // Fills the writable bytes of a buffer with random integers.
 * {@link ChannelBuffer} buffer = ...;
 * while (buffer.writableBytes() >= 4) {
 *     buffer.writeInt(random.nextInt());
 * }
 * 
*

*

Discardable bytes

*

* This segment contains the bytes which were read already by a read operation. * Initially, the size of this segment is {@code 0}, but its size increases up * to the {@link #writerIndex() writerIndex} as read operations are executed. * The read bytes can be discarded by calling {@link #discardReadBytes()} to * reclaim unused area as depicted by the following diagram: *

*

 *  BEFORE discardReadBytes()
 *
 *      +-------------------+------------------+------------------+
 *      | discardable bytes |  readable bytes  |  writable bytes  |
 *      +-------------------+------------------+------------------+
 *      |                   |                  |                  |
 *      0      <=      readerIndex   <=   writerIndex    <=    capacity
 *
 *
 *  AFTER discardReadBytes()
 *
 *      +------------------+--------------------------------------+
 *      |  readable bytes  |    writable bytes (got more space)   |
 *      +------------------+--------------------------------------+
 *      |                  |                                      |
 * readerIndex (0) <= writerIndex (decreased)        <=        capacity
 * 
*

* Please note that there is no guarantee about the content of writable bytes * after calling {@link #discardReadBytes()}. The writable bytes will not be * moved in most cases and could even be filled with completely different data * depending on the underlying buffer implementation. *

*

Clearing the buffer indexes

*

* You can set both {@link #readerIndex() readerIndex} and {@link #writerIndex() * writerIndex} to {@code 0} by calling {@link #clear()}. It does not clear the * buffer content (e.g. filling with {@code 0}) but just clears the two * pointers. Please also note that the semantic of this operation is different * from {@link ByteBuffer#clear()}. *

*

 *  BEFORE clear()
 *
 *      +-------------------+------------------+------------------+
 *      | discardable bytes |  readable bytes  |  writable bytes  |
 *      +-------------------+------------------+------------------+
 *      |                   |                  |                  |
 *      0      <=      readerIndex   <=   writerIndex    <=    capacity
 *
 *
 *  AFTER clear()
 *
 *      +---------------------------------------------------------+
 *      |             writable bytes (got more space)             |
 *      +---------------------------------------------------------+
 *      |                                                         |
 *      0 = readerIndex = writerIndex            <=            capacity
 * 
*

*

Mark and reset

*

* There are two marker indexes in every buffer. One is for storing {@link * #readerIndex() readerIndex} and the other is for storing {@link * #writerIndex() writerIndex}. You can always reposition one of the two * indexes by calling a reset method. It works in a similar fashion to the mark * and reset methods in {@link InputStream} except that there's no {@code * readlimit}. *

*

Conversion to existing JDK types

*

*

Byte array

*

* If a {@link ChannelBuffer} is backed by a byte array (i.e. {@code byte[]}), * you can access it directly via the {@link #array()} method. To determine if * a buffer is backed by a byte array, {@link #hasArray()} should be used. *

*

NIO Buffers

*

* Various {@link #toByteBuffer()} methods convert a {@link ChannelBuffer} into * one or more NIO buffers. These methods avoid buffer allocation and memory * copy whenever possible, but there's no guarantee that memory copy will not be * involved. *

*

I/O Streams

*

* Please refer to {@link ChannelBufferInputStream} and {@link * ChannelBufferOutputStream}. * * */ public interface ChannelBuffer extends Comparable { /** * Returns the number of bytes (octets) this buffer can contain. */ int capacity(); /** * Sets the {@code readerIndex} and {@code writerIndex} of this buffer to * {@code 0}. This method is identical to {@link #setIndex(int, int) * setIndex(0, 0)}. *

* Please note that the behavior of this method is different from that of * NIO buffer, which sets the {@code limit} to the {@code capacity} of the * buffer. */ void clear(); /** * Returns a copy of this buffer's readable bytes. Modifying the content of * the returned buffer or this buffer does not affect each other at all. * This method is identical to {@code buf.copy(buf.readerIndex(), * buf.readableBytes())}. This method does not modify {@code readerIndex} or * {@code writerIndex} of this buffer. */ ChannelBuffer copy(); /** * Returns a copy of this buffer's sub-region. Modifying the content of the * returned buffer or this buffer does not affect each other at all. This * method does not modify {@code readerIndex} or {@code writerIndex} of this * buffer. */ ChannelBuffer copy(int index, int length); /** * Discards the bytes between the 0th index and {@code readerIndex}. It * moves the bytes between {@code readerIndex} and {@code writerIndex} to * the 0th index, and sets {@code readerIndex} and {@code writerIndex} to * {@code 0} and {@code oldWriterIndex - oldReaderIndex} respectively. *

* Please refer to the class documentation for more detailed explanation. */ void discardReadBytes(); /** * Makes sure the number of {@linkplain #writableBytes() the writable bytes} * is equal to or greater than the specified value. If there is enough * writable bytes in this buffer, this method returns with no side effect. * Otherwise:

  • a non-dynamic buffer will throw an {@link * IndexOutOfBoundsException}.
  • a dynamic buffer will expand its * capacity so that the number of the {@link #writableBytes() writable * bytes} becomes equal to or greater than the specified value. The * expansion involves the reallocation of the internal buffer and * consequently memory copy.
* * @param writableBytes the expected minimum number of writable bytes * @throws IndexOutOfBoundsException if {@linkplain #writableBytes() the * writable bytes} of this buffer is less * than the specified value and if this * buffer is not a dynamic buffer */ void ensureWritableBytes(int writableBytes); /** * Determines if the content of the specified buffer is identical to the * content of this array. 'Identical' here means:
  • the size of the * contents of the two buffers are same and
  • every single byte of * the content of the two buffers are same.
Please note that it * does not compare {@link #readerIndex()} nor {@link #writerIndex()}. This * method also returns {@code false} for {@code null} and an object which is * not an instance of {@link ChannelBuffer} type. */ @Override boolean equals(Object o); /** * Returns the factory which creates a {@link ChannelBuffer} whose type and * default {@link java.nio.ByteOrder} are same with this buffer. */ ChannelBufferFactory factory(); /** * Gets a byte at the specified absolute {@code index} in this buffer. This * method does not modify {@code readerIndex} or {@code writerIndex} of this * buffer. * * @throws IndexOutOfBoundsException if the specified {@code index} is less * than {@code 0} or {@code index + 1} is * greater than {@code this.capacity} */ byte getByte(int index); /** * Transfers this buffer's data to the specified destination starting at the * specified absolute {@code index}. This method does not modify {@code * readerIndex} or {@code writerIndex} of this buffer * * @throws IndexOutOfBoundsException if the specified {@code index} is less * than {@code 0} or if {@code index + * dst.length} is greater than {@code * this.capacity} */ void getBytes(int index, byte[] dst); /** * Transfers this buffer's data to the specified destination starting at the * specified absolute {@code index}. This method does not modify {@code * readerIndex} or {@code writerIndex} of this buffer. * * @param dstIndex the first index of the destination * @param length the number of bytes to transfer * @throws IndexOutOfBoundsException if the specified {@code index} is less * than {@code 0}, if the specified {@code * dstIndex} is less than {@code 0}, if * {@code index + length} is greater than * {@code this.capacity}, or if {@code * dstIndex + length} is greater than * {@code dst.length} */ void getBytes(int index, byte[] dst, int dstIndex, int length); /** * Transfers this buffer's data to the specified destination starting at the * specified absolute {@code index} until the destination's position reaches * its limit. This method does not modify {@code readerIndex} or {@code * writerIndex} of this buffer while the destination's {@code position} will * be increased. * * @throws IndexOutOfBoundsException if the specified {@code index} is less * than {@code 0} or if {@code index + * dst.remaining()} is greater than {@code * this.capacity} */ void getBytes(int index, ByteBuffer dst); /** * Transfers this buffer's data to the specified destination starting at the * specified absolute {@code index} until the destination becomes * non-writable. This method is basically same with {@link #getBytes(int, * ChannelBuffer, int, int)}, except that this method increases the {@code * writerIndex} of the destination by the number of the transferred bytes * while {@link #getBytes(int, ChannelBuffer, int, int)} does not. This * method does not modify {@code readerIndex} or {@code writerIndex} of the * source buffer (i.e. {@code this}). * * @throws IndexOutOfBoundsException if the specified {@code index} is less * than {@code 0} or if {@code index + * dst.writableBytes} is greater than * {@code this.capacity} */ void getBytes(int index, ChannelBuffer dst); /** * Transfers this buffer's data to the specified destination starting at the * specified absolute {@code index}. This method is basically same with * {@link #getBytes(int, ChannelBuffer, int, int)}, except that this method * increases the {@code writerIndex} of the destination by the number of the * transferred bytes while {@link #getBytes(int, ChannelBuffer, int, int)} * does not. This method does not modify {@code readerIndex} or {@code * writerIndex} of the source buffer (i.e. {@code this}). * * @param length the number of bytes to transfer * @throws IndexOutOfBoundsException if the specified {@code index} is less * than {@code 0}, if {@code index + * length} is greater than {@code * this.capacity}, or if {@code length} is * greater than {@code dst.writableBytes} */ void getBytes(int index, ChannelBuffer dst, int length); /** * Transfers this buffer's data to the specified destination starting at the * specified absolute {@code index}. This method does not modify {@code * readerIndex} or {@code writerIndex} of both the source (i.e. {@code * this}) and the destination. * * @param dstIndex the first index of the destination * @param length the number of bytes to transfer * @throws IndexOutOfBoundsException if the specified {@code index} is less * than {@code 0}, if the specified {@code * dstIndex} is less than {@code 0}, if * {@code index + length} is greater than * {@code this.capacity}, or if {@code * dstIndex + length} is greater than * {@code dst.capacity} */ void getBytes(int index, ChannelBuffer dst, int dstIndex, int length); /** * Transfers this buffer's data to the specified stream starting at the * specified absolute {@code index}. This method does not modify {@code * readerIndex} or {@code writerIndex} of this buffer. * * @param length the number of bytes to transfer * @throws IndexOutOfBoundsException if the specified {@code index} is less * than {@code 0} or if {@code index + * length} is greater than {@code * this.capacity} * @throws IOException if the specified stream threw an * exception during I/O */ void getBytes(int index, OutputStream dst, int length) throws IOException; /** * Returns {@code true} if and only if this buffer is backed by an NIO * direct buffer. */ boolean isDirect(); /** * Marks the current {@code readerIndex} in this buffer. You can reposition * the current {@code readerIndex} to the marked {@code readerIndex} by * calling {@link #resetReaderIndex()}. The initial value of the marked * {@code readerIndex} is {@code 0}. */ void markReaderIndex(); /** * Marks the current {@code writerIndex} in this buffer. You can reposition * the current {@code writerIndex} to the marked {@code writerIndex} by * calling {@link #resetWriterIndex()}. The initial value of the marked * {@code writerIndex} is {@code 0}. */ void markWriterIndex(); /** * Returns {@code true} if and only if {@code (this.writerIndex - * this.readerIndex)} is greater than {@code 0}. */ boolean readable(); /** * Returns the number of readable bytes which is equal to {@code * (this.writerIndex - this.readerIndex)}. */ int readableBytes(); /** * Gets a byte at the current {@code readerIndex} and increases the {@code * readerIndex} by {@code 1} in this buffer. * * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less * than {@code 1} */ byte readByte(); /** * Transfers this buffer's data to the specified destination starting at the * current {@code readerIndex} and increases the {@code readerIndex} by the * number of the transferred bytes (= {@code dst.length}). * * @throws IndexOutOfBoundsException if {@code dst.length} is greater than * {@code this.readableBytes} */ void readBytes(byte[] dst); /** * Transfers this buffer's data to the specified destination starting at the * current {@code readerIndex} and increases the {@code readerIndex} by the * number of the transferred bytes (= {@code length}). * * @param dstIndex the first index of the destination * @param length the number of bytes to transfer * @throws IndexOutOfBoundsException if the specified {@code dstIndex} is * less than {@code 0}, if {@code length} * is greater than {@code this.readableBytes}, * or if {@code dstIndex + length} is * greater than {@code dst.length} */ void readBytes(byte[] dst, int dstIndex, int length); /** * Transfers this buffer's data to the specified destination starting at the * current {@code readerIndex} until the destination's position reaches its * limit, and increases the {@code readerIndex} by the number of the * transferred bytes. * * @throws IndexOutOfBoundsException if {@code dst.remaining()} is greater * than {@code this.readableBytes} */ void readBytes(ByteBuffer dst); /** * Transfers this buffer's data to the specified destination starting at the * current {@code readerIndex} until the destination becomes non-writable, * and increases the {@code readerIndex} by the number of the transferred * bytes. This method is basically same with {@link * #readBytes(ChannelBuffer, int, int)}, except that this method increases * the {@code writerIndex} of the destination by the number of the * transferred bytes while {@link #readBytes(ChannelBuffer, int, int)} does * not. * * @throws IndexOutOfBoundsException if {@code dst.writableBytes} is greater * than {@code this.readableBytes} */ void readBytes(ChannelBuffer dst); /** * Transfers this buffer's data to the specified destination starting at the * current {@code readerIndex} and increases the {@code readerIndex} by the * number of the transferred bytes (= {@code length}). This method is * basically same with {@link #readBytes(ChannelBuffer, int, int)}, except * that this method increases the {@code writerIndex} of the destination by * the number of the transferred bytes (= {@code length}) while {@link * #readBytes(ChannelBuffer, int, int)} does not. * * @throws IndexOutOfBoundsException if {@code length} is greater than * {@code this.readableBytes} or if {@code * length} is greater than {@code * dst.writableBytes} */ void readBytes(ChannelBuffer dst, int length); /** * Transfers this buffer's data to the specified destination starting at the * current {@code readerIndex} and increases the {@code readerIndex} by the * number of the transferred bytes (= {@code length}). * * @param dstIndex the first index of the destination * @param length the number of bytes to transfer * @throws IndexOutOfBoundsException if the specified {@code dstIndex} is * less than {@code 0}, if {@code length} * is greater than {@code this.readableBytes}, * or if {@code dstIndex + length} is * greater than {@code dst.capacity} */ void readBytes(ChannelBuffer dst, int dstIndex, int length); /** * Transfers this buffer's data to a newly created buffer starting at the * current {@code readerIndex} and increases the {@code readerIndex} by the * number of the transferred bytes (= {@code length}). The returned buffer's * {@code readerIndex} and {@code writerIndex} are {@code 0} and {@code * length} respectively. * * @param length the number of bytes to transfer * @return the newly created buffer which contains the transferred bytes * @throws IndexOutOfBoundsException if {@code length} is greater than * {@code this.readableBytes} */ ChannelBuffer readBytes(int length); /** * Repositions the current {@code readerIndex} to the marked {@code * readerIndex} in this buffer. * * @throws IndexOutOfBoundsException if the current {@code writerIndex} is * less than the marked {@code * readerIndex} */ void resetReaderIndex(); /** * Marks the current {@code writerIndex} in this buffer. You can reposition * the current {@code writerIndex} to the marked {@code writerIndex} by * calling {@link #resetWriterIndex()}. The initial value of the marked * {@code writerIndex} is {@code 0}. */ void resetWriterIndex(); /** * Returns the {@code readerIndex} of this buffer. */ int readerIndex(); /** * Sets the {@code readerIndex} of this buffer. * * @throws IndexOutOfBoundsException if the specified {@code readerIndex} is * less than {@code 0} or greater than * {@code this.writerIndex} */ void readerIndex(int readerIndex); /** * Transfers this buffer's data to the specified stream starting at the * current {@code readerIndex}. * * @param length the number of bytes to transfer * @throws IndexOutOfBoundsException if {@code length} is greater than * {@code this.readableBytes} * @throws IOException if the specified stream threw an * exception during I/O */ void readBytes(OutputStream dst, int length) throws IOException; /** * Sets the specified byte at the specified absolute {@code index} in this * buffer. The 24 high-order bits of the specified value are ignored. This * method does not modify {@code readerIndex} or {@code writerIndex} of this * buffer. * * @throws IndexOutOfBoundsException if the specified {@code index} is less * than {@code 0} or {@code index + 1} is * greater than {@code this.capacity} */ void setByte(int index, int value); /** * Transfers the specified source array's data to this buffer starting at * the specified absolute {@code index}. This method does not modify {@code * readerIndex} or {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException if the specified {@code index} is less * than {@code 0} or if {@code index + * src.length} is greater than {@code * this.capacity} */ void setBytes(int index, byte[] src); /** * Transfers the specified source array's data to this buffer starting at * the specified absolute {@code index}. This method does not modify {@code * readerIndex} or {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException if the specified {@code index} is less * than {@code 0}, if the specified {@code * srcIndex} is less than {@code 0}, if * {@code index + length} is greater than * {@code this.capacity}, or if {@code * srcIndex + length} is greater than * {@code src.length} */ void setBytes(int index, byte[] src, int srcIndex, int length); /** * Transfers the specified source buffer's data to this buffer starting at * the specified absolute {@code index} until the source buffer's position * reaches its limit. This method does not modify {@code readerIndex} or * {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException if the specified {@code index} is less * than {@code 0} or if {@code index + * src.remaining()} is greater than {@code * this.capacity} */ void setBytes(int index, ByteBuffer src); /** * Transfers the specified source buffer's data to this buffer starting at * the specified absolute {@code index} until the source buffer becomes * unreadable. This method is basically same with {@link #setBytes(int, * ChannelBuffer, int, int)}, except that this method increases the {@code * readerIndex} of the source buffer by the number of the transferred bytes * while {@link #setBytes(int, ChannelBuffer, int, int)} does not. This * method does not modify {@code readerIndex} or {@code writerIndex} of the * source buffer (i.e. {@code this}). * * @throws IndexOutOfBoundsException if the specified {@code index} is less * than {@code 0} or if {@code index + * src.readableBytes} is greater than * {@code this.capacity} */ void setBytes(int index, ChannelBuffer src); /** * Transfers the specified source buffer's data to this buffer starting at * the specified absolute {@code index}. This method is basically same with * {@link #setBytes(int, ChannelBuffer, int, int)}, except that this method * increases the {@code readerIndex} of the source buffer by the number of * the transferred bytes while {@link #setBytes(int, ChannelBuffer, int, * int)} does not. This method does not modify {@code readerIndex} or {@code * writerIndex} of the source buffer (i.e. {@code this}). * * @param length the number of bytes to transfer * @throws IndexOutOfBoundsException if the specified {@code index} is less * than {@code 0}, if {@code index + * length} is greater than {@code * this.capacity}, or if {@code length} is * greater than {@code src.readableBytes} */ void setBytes(int index, ChannelBuffer src, int length); /** * Transfers the specified source buffer's data to this buffer starting at * the specified absolute {@code index}. This method does not modify {@code * readerIndex} or {@code writerIndex} of both the source (i.e. {@code * this}) and the destination. * * @param srcIndex the first index of the source * @param length the number of bytes to transfer * @throws IndexOutOfBoundsException if the specified {@code index} is less * than {@code 0}, if the specified {@code * srcIndex} is less than {@code 0}, if * {@code index + length} is greater than * {@code this.capacity}, or if {@code * srcIndex + length} is greater than * {@code src.capacity} */ void setBytes(int index, ChannelBuffer src, int srcIndex, int length); /** * Transfers the content of the specified source stream to this buffer * starting at the specified absolute {@code index}. This method does not * modify {@code readerIndex} or {@code writerIndex} of this buffer. * * @param length the number of bytes to transfer * @return the actual number of bytes read in from the specified channel. * {@code -1} if the specified channel is closed. * @throws IndexOutOfBoundsException if the specified {@code index} is less * than {@code 0} or if {@code index + * length} is greater than {@code * this.capacity} * @throws IOException if the specified stream threw an * exception during I/O */ int setBytes(int index, InputStream src, int length) throws IOException; /** * Sets the {@code readerIndex} and {@code writerIndex} of this buffer in * one shot. This method is useful when you have to worry about the * invocation order of {@link #readerIndex(int)} and {@link * #writerIndex(int)} methods. For example, the following code will fail: *

*

     * // Create a buffer whose readerIndex, writerIndex and capacity are
     * // 0, 0 and 8 respectively.
     * {@link ChannelBuffer} buf = {@link ChannelBuffers}.buffer(8);
     *
     * // IndexOutOfBoundsException is thrown because the specified
     * // readerIndex (2) cannot be greater than the current writerIndex (0).
     * buf.readerIndex(2);
     * buf.writerIndex(4);
     * 
*

* The following code will also fail: *

*

     * // Create a buffer whose readerIndex, writerIndex and capacity are
     * // 0, 8 and 8 respectively.
     * {@link ChannelBuffer} buf = {@link ChannelBuffers}.wrappedBuffer(new
     * byte[8]);
     *
     * // readerIndex becomes 8.
     * buf.readLong();
     *
     * // IndexOutOfBoundsException is thrown because the specified
     * // writerIndex (4) cannot be less than the current readerIndex (8).
     * buf.writerIndex(4);
     * buf.readerIndex(2);
     * 
*

* By contrast, {@link #setIndex(int, int)} guarantees that it never throws * an {@link IndexOutOfBoundsException} as long as the specified indexes * meet basic constraints, regardless what the current index values of the * buffer are: *

*

     * // No matter what the current state of the buffer is, the following
     * // call always succeeds as long as the capacity of the buffer is not
     * // less than 4.
     * buf.setIndex(2, 4);
     * 
* * @throws IndexOutOfBoundsException if the specified {@code readerIndex} is * less than 0, if the specified {@code * writerIndex} is less than the specified * {@code readerIndex} or if the specified * {@code writerIndex} is greater than * {@code this.capacity} */ void setIndex(int readerIndex, int writerIndex); /** * Increases the current {@code readerIndex} by the specified {@code length} * in this buffer. * * @throws IndexOutOfBoundsException if {@code length} is greater than * {@code this.readableBytes} */ void skipBytes(int length); /** * Converts this buffer's readable bytes into a NIO buffer. The returned * buffer might or might not share the content with this buffer, while they * have separate indexes and marks. This method is identical to {@code * buf.toByteBuffer(buf.readerIndex(), buf.readableBytes())}. This method * does not modify {@code readerIndex} or {@code writerIndex} of this * buffer. */ ByteBuffer toByteBuffer(); /** * Converts this buffer's sub-region into a NIO buffer. The returned buffer * might or might not share the content with this buffer, while they have * separate indexes and marks. This method does not modify {@code * readerIndex} or {@code writerIndex} of this buffer. */ ByteBuffer toByteBuffer(int index, int length); /** * Returns {@code true} if and only if {@code (this.capacity - * this.writerIndex)} is greater than {@code 0}. */ boolean writable(); /** * Returns the number of writable bytes which is equal to {@code * (this.capacity - this.writerIndex)}. */ int writableBytes(); /** * Sets the specified byte at the current {@code writerIndex} and increases * the {@code writerIndex} by {@code 1} in this buffer. The 24 high-order * bits of the specified value are ignored. * * @throws IndexOutOfBoundsException if {@code this.writableBytes} is less * than {@code 1} */ void writeByte(int value); /** * Transfers the specified source array's data to this buffer starting at * the current {@code writerIndex} and increases the {@code writerIndex} by * the number of the transferred bytes (= {@code src.length}). * * @throws IndexOutOfBoundsException if {@code src.length} is greater than * {@code this.writableBytes} */ void writeBytes(byte[] src); /** * Transfers the specified source array's data to this buffer starting at * the current {@code writerIndex} and increases the {@code writerIndex} by * the number of the transferred bytes (= {@code length}). * * @param index the first index of the source * @param length the number of bytes to transfer * @throws IndexOutOfBoundsException if the specified {@code srcIndex} is * less than {@code 0}, if {@code srcIndex * + length} is greater than {@code * src.length}, or if {@code length} is * greater than {@code this.writableBytes} */ void writeBytes(byte[] src, int index, int length); /** * Transfers the specified source buffer's data to this buffer starting at * the current {@code writerIndex} until the source buffer's position * reaches its limit, and increases the {@code writerIndex} by the number of * the transferred bytes. * * @throws IndexOutOfBoundsException if {@code src.remaining()} is greater * than {@code this.writableBytes} */ void writeBytes(ByteBuffer src); /** * Transfers the specified source buffer's data to this buffer starting at * the current {@code writerIndex} until the source buffer becomes * unreadable, and increases the {@code writerIndex} by the number of the * transferred bytes. This method is basically same with {@link * #writeBytes(ChannelBuffer, int, int)}, except that this method increases * the {@code readerIndex} of the source buffer by the number of the * transferred bytes while {@link #writeBytes(ChannelBuffer, int, int)} does * not. * * @throws IndexOutOfBoundsException if {@code src.readableBytes} is greater * than {@code this.writableBytes} */ void writeBytes(ChannelBuffer src); /** * Transfers the specified source buffer's data to this buffer starting at * the current {@code writerIndex} and increases the {@code writerIndex} by * the number of the transferred bytes (= {@code length}). This method is * basically same with {@link #writeBytes(ChannelBuffer, int, int)}, except * that this method increases the {@code readerIndex} of the source buffer * by the number of the transferred bytes (= {@code length}) while {@link * #writeBytes(ChannelBuffer, int, int)} does not. * * @param length the number of bytes to transfer * @throws IndexOutOfBoundsException if {@code length} is greater than * {@code this.writableBytes} or if {@code * length} is greater then {@code * src.readableBytes} */ void writeBytes(ChannelBuffer src, int length); /** * Transfers the specified source buffer's data to this buffer starting at * the current {@code writerIndex} and increases the {@code writerIndex} by * the number of the transferred bytes (= {@code length}). * * @param srcIndex the first index of the source * @param length the number of bytes to transfer * @throws IndexOutOfBoundsException if the specified {@code srcIndex} is * less than {@code 0}, if {@code srcIndex * + length} is greater than {@code * src.capacity}, or if {@code length} is * greater than {@code this.writableBytes} */ void writeBytes(ChannelBuffer src, int srcIndex, int length); /** * Transfers the content of the specified stream to this buffer starting at * the current {@code writerIndex} and increases the {@code writerIndex} by * the number of the transferred bytes. * * @param length the number of bytes to transfer * @return the actual number of bytes read in from the specified stream * @throws IndexOutOfBoundsException if {@code length} is greater than * {@code this.writableBytes} * @throws IOException if the specified stream threw an * exception during I/O */ int writeBytes(InputStream src, int length) throws IOException; /** * Returns the {@code writerIndex} of this buffer. */ int writerIndex(); /** * Sets the {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException if the specified {@code writerIndex} is * less than {@code this.readerIndex} or * greater than {@code this.capacity} */ void writerIndex(int writerIndex); /** * Returns the backing byte array of this buffer. * * @throws UnsupportedOperationException if there is no accessible backing byte * array */ byte[] array(); /** * Returns {@code true} if and only if this buffer has a backing byte array. * If this method returns true, you can safely call {@link #array()} and * {@link #arrayOffset()}. */ boolean hasArray(); /** * Returns the offset of the first byte within the backing byte array of * this buffer. * * @throws UnsupportedOperationException if there is no accessible backing byte * array */ int arrayOffset(); /** * If this buffer is backed by an NIO direct buffer, * in some scenarios it may be necessary to manually release. */ default void release() {} }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy