//License
/***
* Java Modbus Library (jamod)
* Copyright (c) 2002-2004, jamod development team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the author nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS
* IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
***/
package net.wimpi.modbus.io;
import java.io.IOException;
import java.io.InputStream;
/**
* This class is a clean room implementation
* of the ByteArrayInputStream, with enhancements for
* speed (no synchronization for example).
* <p/>
* The idea for such an implementation was originally
* obtained from Berkeley DB JE, however, this represents a
* clean-room implementation that is <em>NOT</em> derived
* from their implementation for license reasons and differs
* in implementation considerably. For compatibility reasons
* we have tried to conserve the interface as much as possible.
*
* @author Dieter Wimberger (wimpi)
* @version 1.2rc2 (14/04/2014)
*/
public class FastByteArrayInputStream
extends InputStream {
protected int count;
protected int pos;
protected int mark;
protected byte[] buf;
protected int readlimit = -1;
/**
* Creates a new <tt>FastByteArrayInputStream</tt> instance
* that allows to read from the given byte array.
*
* @param buffer the data to be read.
*/
public FastByteArrayInputStream(byte[] buffer) {
buf = buffer;
count = buf.length;
pos = 0;
mark = 0;
}//constructor
/**
* Creates a new <tt>FastByteArrayInputStream</tt> instance
* that allows to read from the given byte array.
*
* @param buffer the data to read.
* @param offset the byte offset at which to begin reading.
* @param length the number of bytes to read.
*/
public FastByteArrayInputStream(byte[] buffer, int offset, int length) {
buf = buffer;
pos = offset;
count = length;
}//constructor
/**
* Reads the next byte of data from this input stream. The value byte
* is returned as an int in the range 0 to 255. If no byte is available
* because the end of the stream has been reached, the value -1 is returned.
* <p/>
* This read method cannot block.
* </p>
*
* @return the next byte of data, or -1 if the end of the stream has been reached.
* @throws IOException
*/
public int read() throws IOException {
if ((pos < count)) {
return (buf[pos++] & 0xff);
} else {
return (-1);
}
}//read
/**
* Reads up to len bytes of data into an array of bytes from this input stream.
* If pos equals count, then -1 is returned to indicate end of file.
* Otherwise, the number k of bytes read is equal to the smaller of
* len and count-pos. If k is positive, then bytes buf[pos] through buf[pos+k-1]
* are copied into b[off] through b[off+k-1] in the manner performed by
* System.arraycopy. The value k is added into pos and k is returned.
*
* @param toBuf the buffer into which the data is read.
* @param offset the start offset of the data.
* @param length the max number of bytes read.
* @return the total number of bytes read into the buffer, or -1 if there is no
* more data because the end of the stream has been reached.
* @throws IOException
*/
public int read(byte[] toBuf, int offset, int length)
throws IOException {
int avail = count - pos;
if (avail <= 0) {
return -1;
}
if (length > avail) {
length = avail;
}
System.arraycopy(buf, pos, toBuf, offset, length);
pos += length;
return length;
}//read
public int read(byte[] toBuf) throws IOException {
return read(toBuf, 0, toBuf.length);
}//read
/**
* Skips over and discards n bytes of data from this input stream.
* The skip method may skip over some smaller number of bytes.
* The actual number of bytes skipped is returned, or a number <=0
* if none was skipped.
* <p/>
* The maximum number of bytes that can be skipped is defined by
* <tt>Integer.MAX_VALUE</tt>.
* </p>
*
* @param n the number of bytes to be skipped.
* @return the actual number of bytes skipped.
*/
public long skip(long n) {
int skip = this.count - this.pos - (int) n;
if (skip > 0) {
pos += skip;
}
return skip;
}//skip
/**
* The close method for this <tt>FastByteArrayInputStream</tt>
* does nothing.
*/
public void close() {
return;
}//close
/**
* Returns the number of bytes that can be read (or skipped over) from this
* <tt>FastByteArrayInputStream</tt>.
*
* @return the number of bytes that can be skipped.
*/
public int available() {
return count - pos;
}//available
/**
* Marks the current position in this <tt>FastByteArrayInputStream</tt>.
* A subsequent call to{@link #reset()} will re-postition this <tt>FastByteArrayInputStream</tt>
* at the last marked position so that subsequent reads re-read the same bytes.
*
* @param limit a read limit that invalidates the mark if passed.
*/
public void mark(int limit) {
mark = pos;
readlimit = limit;
}//mark
/**
* Tests if this <tt>FastByteArrayInputStream</tt>
* supports the mark and reset methods.
*
* @return true if supported, false otherwise.
*/
public boolean markSupported() {
return true;
}//markSupported
/**
* Re-positions this stream to the position at
* the time the mark method was last called this <tt>FastByteArrayInputStream</tt>.
* @throws IOException if the readlimit was exceeded.
*/
public void reset() throws IOException {
if(readlimit <0 || pos > mark+readlimit) {
pos = mark;
readlimit = -1;
} else {
mark = pos;
readlimit = -1;
throw new IOException("Readlimit exceeded.");
}
}//reset
/**
* Returns the underlying data being read.
*
* @return the underlying data.
*/
public byte[] getBuffer() {
return buf;
}//getBuffer
/**
* Returns the offset at which data is being read from the buffer.
*
* @return the offset at which data is being read.
*/
public int getPosition() {
return pos;
}//getPosition
/**
* Returns the size of the buffer being read.
*
* @return the size of the buffer.
*/
public int size() {
return count;
}//size
}//class FastByteArrayInputStream