1 /* BufferedReader.java -- 2 Copyright (C) 2005 Free Software Foundation, Inc. 3 4 This file is part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 package gnu.xml.stream; 39 40 import java.io.IOException; 41 import java.io.Reader; 42 43 /** 44 * A mark-capable buffered reader. 45 * 46 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a> 47 */ 48 class BufferedReader 49 extends Reader 50 { 51 52 static final int DEFAULT_BUFFER_SIZE = 4096; 53 54 final Reader in; 55 char[] buf; 56 int pos, count, markpos, marklimit, bufferSize; 57 BufferedReader(Reader in)58 BufferedReader(Reader in) 59 { 60 this(in, DEFAULT_BUFFER_SIZE); 61 } 62 BufferedReader(Reader in, int bufferSize)63 BufferedReader(Reader in, int bufferSize) 64 { 65 if (bufferSize < 1) 66 throw new IllegalArgumentException(); 67 this.in = in; 68 this.bufferSize = bufferSize; 69 buf = new char[bufferSize]; 70 pos = count = bufferSize; 71 } 72 close()73 public void close() 74 throws IOException 75 { 76 buf = null; 77 pos = count = 0; 78 markpos = -1; 79 in.close(); 80 } 81 mark(int readlimit)82 public void mark(int readlimit) 83 throws IOException 84 { 85 marklimit = readlimit; 86 markpos = pos; 87 } 88 markSupported()89 public boolean markSupported() 90 { 91 return true; 92 } 93 read()94 public int read() 95 throws IOException 96 { 97 if (pos >= count && !refill()) 98 return -1; 99 return (int) buf[pos++]; 100 } 101 read(char[] b)102 public int read(char[] b) 103 throws IOException 104 { 105 return read(b, 0, b.length); 106 } 107 read(char[] b, int off, int len)108 public int read(char[] b, int off, int len) 109 throws IOException 110 { 111 if (off < 0 || len < 0 || b.length - off < len) 112 throw new IndexOutOfBoundsException(); 113 114 if (len == 0) 115 return 0; 116 117 if (pos >= count && !refill()) 118 return -1; 119 120 int ret = Math.min(count - pos, len); 121 System.arraycopy(buf, pos, b, off, ret); 122 pos += ret; 123 off += ret; 124 len -= ret; 125 126 while (len > 0 && refill()) 127 { 128 int remain = Math.min(count - pos, len); 129 System.arraycopy(buf, pos, b, off, remain); 130 pos += remain; 131 off += remain; 132 len -= remain; 133 ret += remain; 134 } 135 136 return ret; 137 } 138 reset()139 public void reset() 140 throws IOException 141 { 142 if (markpos == -1) 143 throw new IOException(buf == null ? "Stream closed." : "Invalid mark."); 144 pos = markpos; 145 } 146 skip(long n)147 public long skip(long n) 148 throws IOException 149 { 150 if (buf == null) 151 throw new IOException("Stream closed."); 152 final long origN = n; 153 while (n > 0L) 154 { 155 if (pos >= count && !refill()) 156 break; 157 int numread = (int) Math.min((long) (count - pos), n); 158 pos += numread; 159 n -= numread; 160 } 161 return origN - n; 162 } 163 refill()164 private boolean refill() 165 throws IOException 166 { 167 if (buf == null) 168 throw new IOException("Stream closed."); 169 170 int markcount = count - markpos; 171 if (markpos == -1 || markcount >= marklimit) 172 { 173 markpos = -1; 174 pos = count = 0; 175 } 176 else 177 { 178 char[] newbuf = buf; 179 if (markpos < bufferSize) 180 { 181 newbuf = new char[count - markpos + bufferSize]; 182 } 183 System.arraycopy(buf, markpos, newbuf, 0, markcount); 184 buf = newbuf; 185 count = markcount; 186 pos -= markpos; 187 markpos = 0; 188 } 189 190 int numread = in.read(buf, count, bufferSize); 191 if (numread <= 0) 192 return false; 193 194 count += numread; 195 return true; 196 } 197 198 } 199