OSDN Git Service

6473854456b06bbdaceee491880a7bc7d44c38b3
[pf3gnuchains/gcc-fork.git] / libjava / java / io / BufferedInputStream.java
1 /* Copyright (C) 1998, 1999  Free Software Foundation
2
3    This file is part of libgcj.
4
5 This software is copyrighted work licensed under the terms of the
6 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
7 details.  */
8  
9 package java.io;
10
11 /**
12  * @author Warren Levy <warrenl@cygnus.com>
13  * @date October 8, 1998.
14  */
15 /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
16  * "The Java Language Specification", ISBN 0-201-63451-1
17  * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
18  * Status:  Believed complete and correct.
19  */
20  
21 public class BufferedInputStream extends FilterInputStream
22 {
23   /* Internal buffer array for data. */
24   protected byte[] buf;
25
26   /* Index one greater than the last valid byte in the buffer. */
27   protected int count = 0;
28
29   /* The current position in the buffer. */
30   protected int pos = 0;
31
32   /* The value of pos the last time mark() was called. */
33   protected int markpos = -1;
34
35   /* The maximum read-ahead allowed before calls to reset() fail. */
36   protected int marklimit = 0;
37
38   public BufferedInputStream(InputStream in)
39   {
40     this(in, 2048);
41   }
42
43   public BufferedInputStream(InputStream in, int size)
44   {
45     super(in);
46     if (size <= 0)
47       throw new IllegalArgumentException();
48     buf = new byte[size];
49   }
50
51   public synchronized int available() throws IOException
52   {
53     return count - pos + super.available();
54   }
55
56   public void close() throws IOException
57   {
58     // Free up the array memory.
59     buf = null;
60     super.close();
61   }
62
63   public synchronized void mark(int readlimit)
64   {
65     marklimit = readlimit;
66     markpos = pos;
67   }
68
69   public boolean markSupported()
70   {
71     return true;
72   }
73
74   public synchronized int read() throws IOException
75   {
76     if (pos >= count && !refill())
77       return -1;        // EOF
78
79     if (markpos >= 0 && pos - markpos > marklimit)
80       markpos = -1;
81
82     return ((int) buf[pos++]) & 0xFF;
83   }
84
85   public synchronized int read(byte[] b, int off, int len) throws IOException
86   {
87     if (off < 0 || len < 0 || off + len > b.length)
88       throw new ArrayIndexOutOfBoundsException();
89
90     if (pos >= count && !refill())
91       return -1;                // No bytes were read before EOF.
92
93     int remain = Math.min(count - pos, len);
94     System.arraycopy(buf, pos, b, off, remain);
95     pos += remain;
96
97     if (markpos >= 0 && pos - markpos > marklimit)
98       markpos = -1;
99
100     return remain;
101   }
102
103   public synchronized void reset() throws IOException
104   {
105     if (markpos < 0)
106       throw new IOException();
107
108     pos = markpos;
109   }
110
111   public synchronized long skip(long n) throws IOException
112   {
113     final long origN = n;
114
115     while (n > 0L)
116       {
117         if (pos >= count && !refill())
118           if (n < origN)
119             break;
120           else
121             return -1;  // No bytes were read before EOF.
122
123         int numread = (int) Math.min((long) (count - pos), n);
124         pos += numread;
125         n -= numread;
126
127         if (markpos >= 0 && pos - markpos > marklimit)
128           markpos = -1;
129       }
130
131     return origN - n;
132   }
133
134   private boolean refill() throws IOException
135   {
136     if (markpos < 0)
137       count = pos = 0;
138     else if (markpos > 0)
139       {
140         // Shift the marked bytes (if any) to the beginning of the array
141         // but don't grow it.  This saves space in case a reset is done
142         // before we reach the max capacity of this array.
143         System.arraycopy(buf, markpos, buf, 0, count - markpos);
144         count -= markpos;
145         pos -= markpos;
146         markpos = 0;
147       }
148     else if (marklimit >= buf.length)   // BTW, markpos == 0
149       {
150         // Need to grow the buffer now to have room for marklimit bytes.
151         // Note that the new buffer is one greater than marklimit.
152         // This is so that there will be one byte past marklimit to be read
153         // before having to call refill again, thus allowing marklimit to be
154         // invalidated.  That way refill doesn't have to check marklimit.
155         byte[] newbuf = new byte[marklimit + 1];
156         System.arraycopy(buf, 0, newbuf, 0, count);
157         buf = newbuf;
158       }
159
160     int numread = super.read(buf, count, buf.length - count);
161
162     if (numread < 0)    // EOF
163       return false;
164
165     count += numread;
166     return true;
167   }
168 }