241 lines
6.7 KiB
Java
241 lines
6.7 KiB
Java
/*
|
|
* JBoss, Home of Professional Open Source
|
|
*
|
|
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
|
|
* by the @author tags. See the COPYRIGHT.txt in the distribution for a
|
|
* full listing of individual contributors.
|
|
*
|
|
* This is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Lesser General Public License as
|
|
* published by the Free Software Foundation; either version 2.1 of
|
|
* the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this software; if not, write to the Free
|
|
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
|
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
|
*/
|
|
package org.jboss.netty.buffer;
|
|
|
|
import java.io.DataInput;
|
|
import java.io.DataInputStream;
|
|
import java.io.EOFException;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
|
|
/**
|
|
* An {@link InputStream} which reads data from a {@link ChannelBuffer}.
|
|
* <p>
|
|
* A read operation against this stream will occur at the {@code readerIndex}
|
|
* of its underlying buffer and the {@code readerIndex} will increase during
|
|
* the read operation.
|
|
* <p>
|
|
* This stream implements {@link DataInput} for your convenience.
|
|
* The endianness of the stream is not always big endian but depends on
|
|
* the endianness of the underlying buffer.
|
|
*
|
|
* @author The Netty Project (netty-dev@lists.jboss.org)
|
|
* @author Trustin Lee (tlee@redhat.com)
|
|
*
|
|
* @version $Rev$, $Date$
|
|
*
|
|
* @see ChannelBufferOutputStream
|
|
* @apiviz.uses org.jboss.netty.buffer.ChannelBuffer
|
|
*/
|
|
public class ChannelBufferInputStream extends InputStream implements DataInput {
|
|
|
|
private final ChannelBuffer buffer;
|
|
private final int startIndex;
|
|
private final int endIndex;
|
|
|
|
/**
|
|
* Creates a new stream which reads data from the specified {@code buffer}
|
|
* starting at the current {@code readerIndex} and ending at the current
|
|
* {@code writerIndex}.
|
|
*/
|
|
public ChannelBufferInputStream(ChannelBuffer buffer) {
|
|
this(buffer, buffer.readableBytes());
|
|
}
|
|
|
|
/**
|
|
* Creates a new stream which reads data from the specified {@code buffer}
|
|
* starting at the current {@code readerIndex} and ending at
|
|
* {@code readerIndex + length}.
|
|
*
|
|
* @throws IndexOutOfBoundsException
|
|
* if {@code readerIndex + length} is greater than
|
|
* {@code writerIndex}
|
|
*/
|
|
public ChannelBufferInputStream(ChannelBuffer buffer, int length) {
|
|
if (buffer == null) {
|
|
throw new NullPointerException("buffer");
|
|
}
|
|
if (length < 0) {
|
|
throw new IllegalArgumentException("length: " + length);
|
|
}
|
|
if (length > buffer.readableBytes()) {
|
|
throw new IndexOutOfBoundsException();
|
|
}
|
|
|
|
this.buffer = buffer;
|
|
startIndex = buffer.readerIndex();
|
|
endIndex = startIndex + length;
|
|
buffer.markReaderIndex();
|
|
}
|
|
|
|
/**
|
|
* Returns the number of read bytes by this stream so far.
|
|
*/
|
|
public int readBytes() {
|
|
return buffer.readerIndex() - startIndex;
|
|
}
|
|
|
|
@Override
|
|
public int available() throws IOException {
|
|
return endIndex - buffer.readerIndex();
|
|
}
|
|
|
|
@Override
|
|
public void mark(int readlimit) {
|
|
buffer.markReaderIndex();
|
|
}
|
|
|
|
@Override
|
|
public boolean markSupported() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public int read() throws IOException {
|
|
if (!buffer.readable()) {
|
|
return -1;
|
|
}
|
|
return buffer.readByte() & 0xff;
|
|
}
|
|
|
|
@Override
|
|
public int read(byte[] b, int off, int len) throws IOException {
|
|
int available = available();
|
|
if (available == 0) {
|
|
return -1;
|
|
}
|
|
|
|
len = Math.min(available, len);
|
|
buffer.readBytes(b, off, len);
|
|
return len;
|
|
}
|
|
|
|
@Override
|
|
public void reset() throws IOException {
|
|
buffer.resetReaderIndex();
|
|
}
|
|
|
|
@Override
|
|
public long skip(long n) throws IOException {
|
|
if (n > Integer.MAX_VALUE) {
|
|
return skipBytes(Integer.MAX_VALUE);
|
|
} else {
|
|
return skipBytes((int) n);
|
|
}
|
|
}
|
|
|
|
public boolean readBoolean() throws IOException {
|
|
checkAvailable(1);
|
|
return read() != 0;
|
|
}
|
|
|
|
public byte readByte() throws IOException {
|
|
if (!buffer.readable()) {
|
|
throw new EOFException();
|
|
}
|
|
return buffer.readByte();
|
|
}
|
|
|
|
public char readChar() throws IOException {
|
|
return (char) readShort();
|
|
}
|
|
|
|
public double readDouble() throws IOException {
|
|
return Double.longBitsToDouble(readLong());
|
|
}
|
|
|
|
public float readFloat() throws IOException {
|
|
return Float.intBitsToFloat(readInt());
|
|
}
|
|
|
|
public void readFully(byte[] b) throws IOException {
|
|
readFully(b, 0, b.length);
|
|
}
|
|
|
|
public void readFully(byte[] b, int off, int len) throws IOException {
|
|
checkAvailable(len);
|
|
buffer.readBytes(b, off, len);
|
|
}
|
|
|
|
public int readInt() throws IOException {
|
|
checkAvailable(4);
|
|
return buffer.readInt();
|
|
}
|
|
|
|
private final StringBuilder lineBuf = new StringBuilder();
|
|
|
|
public String readLine() throws IOException {
|
|
lineBuf.setLength(0);
|
|
for (;;) {
|
|
int b = read();
|
|
if (b < 0 || b == '\n') {
|
|
break;
|
|
}
|
|
|
|
lineBuf.append((char) b);
|
|
}
|
|
|
|
while (lineBuf.charAt(lineBuf.length() - 1) == '\r') {
|
|
lineBuf.setLength(lineBuf.length() - 1);
|
|
}
|
|
|
|
return lineBuf.toString();
|
|
}
|
|
|
|
public long readLong() throws IOException {
|
|
checkAvailable(8);
|
|
return buffer.readLong();
|
|
}
|
|
|
|
public short readShort() throws IOException {
|
|
checkAvailable(2);
|
|
return buffer.readShort();
|
|
}
|
|
|
|
public String readUTF() throws IOException {
|
|
return DataInputStream.readUTF(this);
|
|
}
|
|
|
|
public int readUnsignedByte() throws IOException {
|
|
return readByte() & 0xff;
|
|
}
|
|
|
|
public int readUnsignedShort() throws IOException {
|
|
return readShort() & 0xffff;
|
|
}
|
|
|
|
public int skipBytes(int n) throws IOException {
|
|
int nBytes = Math.min(available(), n);
|
|
buffer.skipBytes(nBytes);
|
|
return nBytes;
|
|
}
|
|
|
|
private void checkAvailable(int fieldSize) throws IOException {
|
|
if (fieldSize < 0) {
|
|
throw new IndexOutOfBoundsException();
|
|
}
|
|
if (fieldSize > available()) {
|
|
throw new EOFException();
|
|
}
|
|
}
|
|
} |