1 | /* ******************************************************************************* |
2 | * Copyright (C) 2004 Tristan Allwood, * |
3 | * 2004 Matthew Sackman * |
4 | * * |
5 | * This program is free software; you can redistribute it and/or * |
6 | * modify it under the terms of the GNU General Public License * |
7 | * as published by the Free Software Foundation; either version 2 * |
8 | * of the License, or (at your option) any later version. * |
9 | * * |
10 | * This program is distributed in the hope that it will be useful, * |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
13 | * GNU General Public License for more details. * |
14 | * * |
15 | * You should have received a copy of the GNU General Public License * |
16 | * along with this program; if not, write to the Free Software * |
17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
18 | * * |
19 | * The authors can be contacted by email at toa02@doc.ic.ac.uk * |
20 | * ms02@doc.ic.ac.uk * |
21 | * * |
22 | *********************************************************************************/ |
23 | |
24 | /* |
25 | * Created on 01-Jul-2004 |
26 | * |
27 | */ |
28 | package uk.co.zonetora.fj; |
29 | |
30 | import java.io.IOException; |
31 | import java.io.PushbackReader; |
32 | import java.io.Reader; |
33 | import java.util.ArrayList; |
34 | import java.util.List; |
35 | |
36 | /** |
37 | * A subclass of the PushbackReader which automatically expands and contracts |
38 | * its buffer as you read and unread data. |
39 | * |
40 | * @author Matthew Sackman (ms02) |
41 | * @version 1 |
42 | */ |
43 | public class VariablePushbackReader extends PushbackReader { |
44 | |
45 | private final List buffer = new ArrayList(); |
46 | |
47 | public VariablePushbackReader(Reader in) { |
48 | super(in); |
49 | } |
50 | |
51 | public int read() throws IOException { |
52 | synchronized (lock) { |
53 | if (buffer.size() > 0) { |
54 | final int idx = buffer.size() - 1; |
55 | final int read = ((Integer) buffer.get(idx)).intValue(); |
56 | buffer.remove(idx); |
57 | return read; |
58 | } else { |
59 | return super.read(); |
60 | } |
61 | } |
62 | } |
63 | |
64 | /* |
65 | * (non-Javadoc) |
66 | * |
67 | * @see java.io.Reader#read(char[]) |
68 | */ |
69 | public int read(char[] cbuf) throws IOException { |
70 | synchronized (lock) { |
71 | int count = 0; |
72 | for (; count < cbuf.length; count++) { |
73 | cbuf[count] = (char) read(); |
74 | } |
75 | return count; |
76 | } |
77 | } |
78 | |
79 | /* |
80 | * (non-Javadoc) |
81 | * |
82 | * @see java.io.PushbackReader#read(char[], int, int) |
83 | */ |
84 | public int read(char[] cbuf, int off, int len) throws IOException { |
85 | synchronized (lock) { |
86 | int count = 0; |
87 | for (; count < len; count++) { |
88 | cbuf[off + count] = (char) read(); |
89 | } |
90 | return count; |
91 | } |
92 | } |
93 | |
94 | /* |
95 | * (non-Javadoc) |
96 | * |
97 | * @see java.io.PushbackReader#ready() |
98 | */ |
99 | public boolean ready() throws IOException { |
100 | synchronized (lock) { |
101 | return buffer.size() > 0 || super.ready(); |
102 | } |
103 | } |
104 | |
105 | public void mark(int readAheadLimit) throws IOException { |
106 | throw new IOException("mark/reset not supported"); |
107 | } |
108 | |
109 | public void reset() throws IOException { |
110 | throw new IOException("mark/reset not supported"); |
111 | } |
112 | |
113 | public boolean markSupported() { |
114 | return false; |
115 | } |
116 | |
117 | public void close() throws IOException { |
118 | synchronized (lock) { |
119 | buffer.clear(); |
120 | super.close(); |
121 | } |
122 | } |
123 | |
124 | public long skip(long n) throws IOException { |
125 | if (n < 0L) |
126 | throw new IllegalArgumentException("Skip value is negative (" |
127 | + n + ")"); |
128 | if (n == 0) return n; |
129 | int skipped = 0; |
130 | synchronized (lock) { |
131 | while (n > 0 && buffer.size() > 0) { |
132 | buffer.remove(buffer.size() - 1); |
133 | n--; |
134 | skipped++; |
135 | } |
136 | while (n > 0) { |
137 | super.read(); |
138 | n--; |
139 | skipped++; |
140 | } |
141 | return skipped; |
142 | } |
143 | } |
144 | |
145 | public void unread(int c) { |
146 | synchronized (lock) { |
147 | buffer.add(new Integer(c)); |
148 | } |
149 | } |
150 | |
151 | public void unread(char[] cbuf) { |
152 | synchronized (lock) { |
153 | for (int idx = cbuf.length - 1; idx != 0; idx--) |
154 | unread(cbuf[idx]); |
155 | } |
156 | } |
157 | |
158 | public void unread(char[] cbuf, int off, int len) { |
159 | synchronized (lock) { |
160 | for (int idx = len; idx != 0; idx--) |
161 | unread(cbuf[off + idx]); |
162 | } |
163 | } |
164 | } |