/* * Copyright 2011 The Netty Project * * The Netty Project 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.jboss.netty.buffer; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.channels.ClosedChannelException; import java.nio.channels.GatheringByteChannel; import java.nio.channels.ScatteringByteChannel; /** * A skeletal implementation for Java heap buffers. */ public abstract class HeapChannelBuffer extends AbstractChannelBuffer { /** * The underlying heap byte array that this buffer is wrapping. */ protected final byte[] array; /** * Creates a new heap buffer with a newly allocated byte array. * * @param length the length of the new byte array */ public HeapChannelBuffer(int length) { this(new byte[length], 0, 0); } /** * Creates a new heap buffer with an existing byte array. * * @param array the byte array to wrap */ public HeapChannelBuffer(byte[] array) { this(array, 0, array.length); } /** * Creates a new heap buffer with an existing byte array. * * @param array the byte array to wrap * @param readerIndex the initial reader index of this buffer * @param writerIndex the initial writer index of this buffer */ protected HeapChannelBuffer(byte[] array, int readerIndex, int writerIndex) { if (array == null) { throw new NullPointerException("array"); } this.array = array; setIndex(readerIndex, writerIndex); } public boolean isDirect() { return false; } public int capacity() { return array.length; } public boolean hasArray() { return true; } public byte[] array() { return array; } public int arrayOffset() { return 0; } public byte getByte(int index) { return array[index]; } public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) { if (dst instanceof HeapChannelBuffer) { getBytes(index, ((HeapChannelBuffer) dst).array, dstIndex, length); } else { dst.setBytes(dstIndex, array, index, length); } } public void getBytes(int index, byte[] dst, int dstIndex, int length) { System.arraycopy(array, index, dst, dstIndex, length); } public void getBytes(int index, ByteBuffer dst) { dst.put(array, index, Math.min(capacity() - index, dst.remaining())); } public void getBytes(int index, OutputStream out, int length) throws IOException { out.write(array, index, length); } public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { return out.write(ByteBuffer.wrap(array, index, length)); } public void setByte(int index, int value) { array[index] = (byte) value; } public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) { if (src instanceof HeapChannelBuffer) { setBytes(index, ((HeapChannelBuffer) src).array, srcIndex, length); } else { src.getBytes(srcIndex, array, index, length); } } public void setBytes(int index, byte[] src, int srcIndex, int length) { System.arraycopy(src, srcIndex, array, index, length); } public void setBytes(int index, ByteBuffer src) { src.get(array, index, src.remaining()); } public int setBytes(int index, InputStream in, int length) throws IOException { int readBytes = 0; do { int localReadBytes = in.read(array, index, length); if (localReadBytes < 0) { if (readBytes == 0) { return -1; } else { break; } } readBytes += localReadBytes; index += localReadBytes; length -= localReadBytes; } while (length > 0); return readBytes; } public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { ByteBuffer buf = ByteBuffer.wrap(array, index, length); int readBytes = 0; do { int localReadBytes; try { localReadBytes = in.read(buf); } catch (ClosedChannelException e) { localReadBytes = -1; } if (localReadBytes < 0) { if (readBytes == 0) { return -1; } else { break; } } else if (localReadBytes == 0) { break; } readBytes += localReadBytes; } while (readBytes < length); return readBytes; } public ChannelBuffer slice(int index, int length) { if (index == 0) { if (length == 0) { return ChannelBuffers.EMPTY_BUFFER; } if (length == array.length) { ChannelBuffer slice = duplicate(); slice.setIndex(0, length); return slice; } else { return new TruncatedChannelBuffer(this, length); } } else { if (length == 0) { return ChannelBuffers.EMPTY_BUFFER; } return new SlicedChannelBuffer(this, index, length); } } public ByteBuffer toByteBuffer(int index, int length) { return ByteBuffer.wrap(array, index, length).order(order()); } }