/* * 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.ignite.internal.util.io; import java.io.ByteArrayInputStream; import java.io.InputStream; import org.apache.ignite.internal.util.typedef.internal.S; import org.apache.ignite.internal.util.typedef.internal.U; /** * This class defines input stream backed by byte array. * It is identical to {@link ByteArrayInputStream} with no synchronization. */ public class GridByteArrayInputStream extends InputStream { /** */ private byte buf[]; /** */ private int pos; /** */ private int mark; /** */ private int cnt; /** * @param buf The input buffer. */ public GridByteArrayInputStream(byte buf[]) { this.buf = buf; pos = 0; cnt = buf.length; } /** * @param buf The input buffer. * @param off The offset in the buffer of the first byte to read. * @param len The maximum number of bytes to read from the buffer. */ public GridByteArrayInputStream(byte buf[], int off, int len) { this.buf = buf; pos = off; cnt = Math.min(off + len, buf.length); mark = off; } /** * Reads the next byte of data from this input stream. The value * byte is returned as an {@code int} in the range * {@code 0} to {@code 255}. If no byte is available * because the end of the stream has been reached, the value * {@code -1} is returned. * <p> * This method cannot block. * * @return The next byte of data, or {@code -1} if the end of the * stream has been reached. */ @Override public int read() { return (pos < cnt) ? (buf[pos++] & 0xff) : -1; } /** * Reads up to {@code len} bytes of data into an array of bytes from this input stream. * If {@code pos} equals {@code count}, then {@code -1} is returned to indicate * end of file. Otherwise, the number {@code k} of bytes read is equal to the smaller of * {@code len} and {@code count-pos}. If {@code k} is positive, then bytes * {@code buf[pos]} through {@code buf[pos+k-1]} are copied into {@code b[off]} through * {@code b[off+k-1]} in the manner performed by {@code System.arraycopy}. The value * {@code k} is added into {@code pos} and {@code k} is returned. * <p> * This {@code read} method cannot block. * * @param b The buffer into which the data is read. * @param off The start offset in the destination array {@code b} * @param len The maximum number of bytes read. * @return The total number of bytes read into the buffer, or * {@code -1} if there is no more data because the end of * the stream has been reached. * @throws NullPointerException If {@code b} is {@code null}. * @throws IndexOutOfBoundsException If {@code off} is negative, * {@code len} is negative, or {@code len} is greater than {@code b.length - off} */ @Override public int read(byte b[], int off, int len) { if (b == null) throw new NullPointerException(); else if (off < 0 || len < 0 || len > b.length - off) throw new IndexOutOfBoundsException(); if (pos >= cnt) return -1; if (pos + len > cnt) len = cnt - pos; if (len <= 0) return 0; U.arrayCopy(buf, pos, b, off, len); pos += len; return len; } /** * Skips {@code n} bytes of input from this input stream. Fewer * bytes might be skipped if the end of the input stream is reached. * The actual number {@code k} * of bytes to be skipped is equal to the smaller * of {@code n} and {@code count-pos}. * The value {@code k} is added into {@code pos} * and {@code k} is returned. * * @param n The number of bytes to be skipped. * @return The actual number of bytes skipped. */ @Override public long skip(long n) { if (pos + n > cnt) n = cnt - pos; if (n < 0) return 0; pos += n; return n; } /** * Returns the number of remaining bytes that can be read (or skipped over) * from this input stream. * <p> * The value returned is {@code count - pos}, which is the number of bytes * remaining to be read from the input buffer. * * @return The number of remaining bytes that can be read (or skipped * over) from this input stream without blocking. */ @Override public int available() { return cnt - pos; } /** * Tests if this {@code InputStream} supports mark/reset. * <p> * This method always returns {@code true}. */ @Override public boolean markSupported() { return true; } /** * Set the current marked position in the stream. * ByteArrayInputStream objects are marked at position zero by * default when constructed. They may be marked at another * position within the buffer by this method. * <p> * If no mark has been set, then the value of the mark is the * offset passed to the constructor (or 0 if the offset was not * supplied). * * <p> * Note: The {@code readAheadLimit} for this class has no meaning. */ @SuppressWarnings("NonSynchronizedMethodOverridesSynchronizedMethod") @Override public void mark(int readAheadLimit) { mark = pos; } /** * Resets the buffer to the marked position. The marked position * is 0 unless another position was marked or an offset was specified * in the constructor. */ @SuppressWarnings("NonSynchronizedMethodOverridesSynchronizedMethod") @Override public void reset() { pos = mark; } /** * Closing of this stream has no effect. */ @Override public void close() { // No-op. } /** {@inheritDoc} */ @Override public String toString() { return S.toString(GridByteArrayInputStream.class, this); } }