151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. 351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it 651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as 751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation. Oracle designates this 851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided 951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code. 1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT 1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that 1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code). 1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version 1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation, 1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any 2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions. 2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.io; 2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.concurrent.atomic.AtomicReferenceFieldUpdater; 2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/** 3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A <code>BufferedInputStream</code> adds 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * functionality to another input stream-namely, 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the ability to buffer the input and to 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * support the <code>mark</code> and <code>reset</code> 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * methods. When the <code>BufferedInputStream</code> 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is created, an internal buffer array is 3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * created. As bytes from the stream are read 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or skipped, the internal buffer is refilled 3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * as necessary from the contained input stream, 3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * many bytes at a time. The <code>mark</code> 4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * operation remembers a point in the input 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream and the <code>reset</code> operation 4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * causes all the bytes read since the most 4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * recent <code>mark</code> operation to be 4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * reread before new bytes are taken from 4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the contained input stream. 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Arthur van Hoff 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since JDK1.0 4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic 5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiclass BufferedInputStream extends FilterInputStream { 5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static int defaultBufferSize = 8192; 5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The internal buffer array where the data is stored. When necessary, 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * it may be replaced by another array of 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * a different size. 5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected volatile byte buf[]; 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Atomic updater to provide compareAndSet for buf. This is 6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * necessary because closes can be asynchronous. We use nullness 6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of buf[] as primary indicator that this stream is closed. (The 6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * "in" field is also nulled out on close.) 6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final 6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski AtomicReferenceFieldUpdater<BufferedInputStream, byte[]> bufUpdater = 7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski AtomicReferenceFieldUpdater.newUpdater 7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski (BufferedInputStream.class, byte[].class, "buf"); 7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The index one greater than the index of the last valid byte in 7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the buffer. 7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This value is always 7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * in the range <code>0</code> through <code>buf.length</code>; 7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * elements <code>buf[0]</code> through <code>buf[count-1] 7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </code>contain buffered input data obtained 8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * from the underlying input stream. 8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected int count; 8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The current position in the buffer. This is the index of the next 8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * character to be read from the <code>buf</code> array. 8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This value is always in the range <code>0</code> 8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * through <code>count</code>. If it is less 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * than <code>count</code>, then <code>buf[pos]</code> 9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is the next byte to be supplied as input; 9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * if it is equal to <code>count</code>, then 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the next <code>read</code> or <code>skip</code> 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * operation will require more bytes to be 9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * read from the contained input stream. 9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.BufferedInputStream#buf 9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected int pos; 10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The value of the <code>pos</code> field at the time the last 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>mark</code> method was called. 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This value is always 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * in the range <code>-1</code> through <code>pos</code>. 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If there is no marked position in the input 10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream, this field is <code>-1</code>. If 10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * there is a marked position in the input 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream, then <code>buf[markpos]</code> 11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is the first byte to be supplied as input 11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * after a <code>reset</code> operation. If 11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>markpos</code> is not <code>-1</code>, 11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * then all bytes from positions <code>buf[markpos]</code> 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * through <code>buf[pos-1]</code> must remain 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * in the buffer array (though they may be 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * moved to another place in the buffer array, 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * with suitable adjustments to the values 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of <code>count</code>, <code>pos</code>, 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and <code>markpos</code>); they may not 12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * be discarded unless and until the difference 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * between <code>pos</code> and <code>markpos</code> 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * exceeds <code>marklimit</code>. 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.BufferedInputStream#mark(int) 12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.BufferedInputStream#pos 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected int markpos = -1; 12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The maximum read ahead allowed after a call to the 13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>mark</code> method before subsequent calls to the 13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>reset</code> method fail. 13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Whenever the difference between <code>pos</code> 13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and <code>markpos</code> exceeds <code>marklimit</code>, 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * then the mark may be dropped by setting 13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>markpos</code> to <code>-1</code>. 13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.BufferedInputStream#mark(int) 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.BufferedInputStream#reset() 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected int marklimit; 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Check to make sure that underlying input stream has not been 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * nulled out due to close; if not return it; 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private InputStream getInIfOpen() throws IOException { 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski InputStream input = in; 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (input == null) 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Stream closed"); 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return input; 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Check to make sure that buffer has not been nulled out due to 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * close; if not return it; 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private byte[] getBufIfOpen() throws IOException { 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] buffer = buf; 16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer == null) 16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Stream closed"); 16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer; 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Creates a <code>BufferedInputStream</code> 16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and saves its argument, the input stream 16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>in</code>, for later use. An internal 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * buffer array is created and stored in <code>buf</code>. 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param in the underlying input stream. 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public BufferedInputStream(InputStream in) { 17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this(in, defaultBufferSize); 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Creates a <code>BufferedInputStream</code> 18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * with the specified buffer size, 18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and saves its argument, the input stream 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>in</code>, for later use. An internal 18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * buffer array of length <code>size</code> 18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is created and stored in <code>buf</code>. 18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param in the underlying input stream. 18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param size the buffer size. 18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IllegalArgumentException if size <= 0. 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public BufferedInputStream(InputStream in, int size) { 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski super(in); 19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (size <= 0) { 19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("Buffer size <= 0"); 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf = new byte[size]; 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Fills the buffer with more data, taking into account 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * shuffling and other tricks for dealing with marks. 20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Assumes that it is being called by a synchronized method. 20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This method also assumes that all data has already been read in, 20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * hence pos > count. 20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void fill() throws IOException { 20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] buffer = getBufIfOpen(); 20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (markpos < 0) 20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos = 0; /* no mark: throw away the buffer */ 20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else if (pos >= buffer.length) /* no room left in buffer */ 21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (markpos > 0) { /* can throw away early part of the buffer */ 21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int sz = pos - markpos; 21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski System.arraycopy(buffer, markpos, buffer, 0, sz); 21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos = sz; 21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski markpos = 0; 21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (buffer.length >= marklimit) { 21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski markpos = -1; /* buffer got too big, invalidate mark */ 21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos = 0; /* drop buffer contents */ 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { /* grow buffer */ 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int nsz = pos * 2; 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (nsz > marklimit) 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski nsz = marklimit; 22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte nbuf[] = new byte[nsz]; 22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski System.arraycopy(buffer, 0, nbuf, 0, pos); 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!bufUpdater.compareAndSet(this, buffer, nbuf)) { 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Can't replace buf if there was an async close. 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Note: This would need to be changed if fill() 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // is ever made accessible to multiple threads. 22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // But for now, the only way CAS can fail is via close. 22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // assert buf == null; 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Stream closed"); 23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer = nbuf; 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski count = pos; 23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int n = getInIfOpen().read(buffer, pos, buffer.length - pos); 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (n > 0) 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski count = n + pos; 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * See 24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the general contract of the <code>read</code> 24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * method of <code>InputStream</code>. 24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the next byte of data, or <code>-1</code> if the end of the 24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream is reached. 24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IOException if this input stream has been closed by 24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * invoking its {@link #close()} method, 24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or an I/O error occurs. 25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.FilterInputStream#in 25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public synchronized int read() throws IOException { 25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos >= count) { 25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski fill(); 25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos >= count) 25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return -1; 25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return getBufIfOpen()[pos++] & 0xff; 25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read characters into a portion of an array, reading from the underlying 26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream at most once if necessary. 26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int read1(byte[] b, int off, int len) throws IOException { 26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int avail = count - pos; 26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (avail <= 0) { 26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* If the requested length is at least as large as the buffer, and 26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if there is no mark/reset activity, do not bother to copy the 27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bytes into the local buffer. In this way buffered streams will 27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cascade harmlessly. */ 27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len >= getBufIfOpen().length && markpos < 0) { 27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return getInIfOpen().read(b, off, len); 27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski fill(); 27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski avail = count - pos; 27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (avail <= 0) return -1; 27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int cnt = (avail < len) ? avail : len; 28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski System.arraycopy(getBufIfOpen(), pos, b, off, cnt); 28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos += cnt; 28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return cnt; 28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Reads bytes from this byte-input stream into the specified byte array, 28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * starting at the given offset. 28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> This method implements the general contract of the corresponding 29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>{@link InputStream#read(byte[], int, int) read}</code> method of 29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the <code>{@link InputStream}</code> class. As an additional 29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * convenience, it attempts to read as many bytes as possible by repeatedly 29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * invoking the <code>read</code> method of the underlying stream. This 29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * iterated <code>read</code> continues until one of the following 29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * conditions becomes true: <ul> 29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li> The specified number of bytes have been read, 29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li> The <code>read</code> method of the underlying stream returns 30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>-1</code>, indicating end-of-file, or 30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li> The <code>available</code> method of the underlying stream 30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * returns zero, indicating that further input requests would block. 30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </ul> If the first <code>read</code> on the underlying stream returns 30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>-1</code> to indicate end-of-file then this method returns 30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>-1</code>. Otherwise this method returns the number of bytes 30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * actually read. 30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> Subclasses of this class are encouraged, but not required, to 31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * attempt to read as many bytes as possible in the same fashion. 31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param b destination buffer. 31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param off offset at which to start storing bytes. 31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param len maximum number of bytes to read. 31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the number of bytes read, or <code>-1</code> if the end of 31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the stream has been reached. 31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IOException if this input stream has been closed by 31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * invoking its {@link #close()} method, 32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or an I/O error occurs. 32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public synchronized int read(byte b[], int off, int len) 32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException 32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski getBufIfOpen(); // Check for closed stream 32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((off | len | (off + len) | (b.length - (off + len))) < 0) { 32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IndexOutOfBoundsException(); 32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (len == 0) { 32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return 0; 33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int n = 0; 33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (;;) { 33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int nread = read1(b, off + n, len - n); 33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (nread <= 0) 33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (n == 0) ? nread : n; 33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski n += nread; 33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (n >= len) 33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return n; 34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // if not closed but no bytes available, return 34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski InputStream input = in; 34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (input != null && input.available() <= 0) 34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return n; 34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * See the general contract of the <code>skip</code> 34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * method of <code>InputStream</code>. 35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IOException if the stream does not support seek, 35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or if this input stream has been closed by 35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * invoking its {@link #close()} method, or an 35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * I/O error occurs. 35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public synchronized long skip(long n) throws IOException { 35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski getBufIfOpen(); // Check for closed stream 35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (n <= 0) { 35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return 0; 36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski long avail = count - pos; 36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (avail <= 0) { 36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // If no mark position set then don't keep in buffer 36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (markpos <0) 36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return getInIfOpen().skip(n); 36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Fill in buffer to save bytes for reset 36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski fill(); 37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski avail = count - pos; 37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (avail <= 0) 37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return 0; 37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski long skipped = (avail < n) ? avail : n; 37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos += skipped; 37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return skipped; 37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns an estimate of the number of bytes that can be read (or 38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * skipped over) from this input stream without blocking by the next 38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * invocation of a method for this input stream. The next invocation might be 38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the same thread or another thread. A single read or skip of this 38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * many bytes will not block, but may read or skip fewer bytes. 38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This method returns the sum of the number of bytes remaining to be read in 38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the buffer (<code>count - pos</code>) and the result of calling the 38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link java.io.FilterInputStream#in in}.available(). 39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return an estimate of the number of bytes that can be read (or skipped 39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * over) from this input stream without blocking. 39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IOException if this input stream has been closed by 39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * invoking its {@link #close()} method, 39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or an I/O error occurs. 39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public synchronized int available() throws IOException { 39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int n = count - pos; 39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int avail = getInIfOpen().available(); 40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return n > (Integer.MAX_VALUE - avail) 40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ? Integer.MAX_VALUE 40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski : n + avail; 40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * See the general contract of the <code>mark</code> 40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * method of <code>InputStream</code>. 40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param readlimit the maximum limit of bytes that can be read before 41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the mark position becomes invalid. 41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.BufferedInputStream#reset() 41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public synchronized void mark(int readlimit) { 41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski marklimit = readlimit; 41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski markpos = pos; 41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * See the general contract of the <code>reset</code> 42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * method of <code>InputStream</code>. 42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If <code>markpos</code> is <code>-1</code> 42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (no mark has been set or the mark has been 42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * invalidated), an <code>IOException</code> 42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is thrown. Otherwise, <code>pos</code> is 42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * set equal to <code>markpos</code>. 42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IOException if this stream has not been marked or, 42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * if the mark has been invalidated, or the stream 43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * has been closed by invoking its {@link #close()} 43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * method, or an I/O error occurs. 43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.BufferedInputStream#mark(int) 43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public synchronized void reset() throws IOException { 43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski getBufIfOpen(); // Cause exception if closed 43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (markpos < 0) 43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Resetting to invalid mark"); 43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos = markpos; 43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Tests if this input stream supports the <code>mark</code> 44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and <code>reset</code> methods. The <code>markSupported</code> 44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * method of <code>BufferedInputStream</code> returns 44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>true</code>. 44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a <code>boolean</code> indicating if this stream type supports 44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the <code>mark</code> and <code>reset</code> methods. 44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.InputStream#mark(int) 45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.InputStream#reset() 45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean markSupported() { 45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return true; 45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Closes this input stream and releases any system resources 45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * associated with the stream. 45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Once the stream has been closed, further read(), available(), reset(), 46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or skip() invocations will throw an IOException. 46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Closing a previously closed stream has no effect. 46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IOException if an I/O error occurs. 46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void close() throws IOException { 46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] buffer; 46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while ( (buffer = buf) != null) { 46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (bufUpdater.compareAndSet(this, buffer, null)) { 46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski InputStream input = in; 47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski in = null; 47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (input != null) 47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski input.close(); 47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 47451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Else retry in case a new buf was CASed in fill() 47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 479