Initial revision
[gcc.git] / libjava / java / io / DataInputStream.java
1 /* Copyright (C) 1998, 1999 Cygnus Solutions
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 20, 1998.
14 */
15
16 /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
17 * "The Java Language Specification", ISBN 0-201-63451-1
18 * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
19 * Status: Believed complete and correct.
20 */
21
22 public class DataInputStream extends FilterInputStream implements DataInput
23 {
24 public DataInputStream(InputStream in)
25 {
26 super(in);
27 }
28
29 public final int read(byte[] b) throws IOException
30 {
31 return super.read(b, 0, b.length);
32 }
33
34 public final int read(byte[] b, int off, int len) throws IOException
35 {
36 if (off < 0 || len < 0 || off + len > b.length)
37 throw new ArrayIndexOutOfBoundsException();
38
39 return super.read(b, off, len);
40 }
41
42 public final boolean readBoolean() throws IOException
43 {
44 return (readByte() != 0);
45 }
46
47 public final byte readByte() throws IOException
48 {
49 int i = read();
50 if (i < 0)
51 throw new EOFException();
52
53 return (byte) i;
54 }
55
56 public final char readChar() throws IOException
57 {
58 return (char) ((readByte() << 8) | readUnsignedByte());
59 }
60
61 public final double readDouble() throws IOException
62 {
63 return Double.longBitsToDouble(readLong());
64 }
65
66 public final float readFloat() throws IOException
67 {
68 return Float.intBitsToFloat(readInt());
69 }
70
71 public final void readFully(byte[] b) throws IOException
72 {
73 readFully(b, 0, b.length);
74 }
75
76 public final void readFully(byte[] b, int off, int len) throws IOException
77 {
78 if (off < 0 || len < 0 || off + len > b.length)
79 throw new ArrayIndexOutOfBoundsException();
80
81 while (len > 0)
82 {
83 // super.read will block until some data is available.
84 int numread = super.read(b, off, len);
85 if (numread < 0)
86 throw new EOFException();
87 len -= numread;
88 off += numread;
89 }
90 }
91
92 public final int readInt() throws IOException
93 {
94 int retval = 0;
95 for (int i = 0; i < 4; i++)
96 retval |= readUnsignedByte() << (24 - i * 8);
97
98 return retval;
99 }
100
101 // Deprecated as of JDK 1.1
102 public final String readLine() throws IOException
103 {
104 StringBuffer strb = new StringBuffer();
105
106 while (true)
107 {
108 char ch = (char) read();
109 if (ch < 0 || (ch &= 0xFF) == '\n')
110 break;
111 if (ch == '\r')
112 {
113 // FIXME: The following code tries to adjust the stream back one
114 // character if the next char read is '\n'. As a last resort,
115 // it tries to mark the position before reading but the bottom
116 // line is that it is possible that this method will not properly
117 // deal with a '\r' '\n' combination thus not fulfilling the
118 // DataInput contract for readLine. It's not a particularly
119 // safe approach threadwise since it is unsynchronized and
120 // since it might mark an input stream behind the users back.
121 // Along the same vein it could try the same thing for
122 // ByteArrayInputStream and PushbackInputStream, but that is
123 // probably overkill since this is deprecated & BufferedInputStream
124 // is the most likely type of input stream.
125 //
126 // The alternative is to somehow push back the next byte if it
127 // isn't a '\n' or to have the reading methods of this class
128 // keep track of whether the last byte read was '\r' by readLine
129 // and then skip the very next byte if it is '\n'. Either way,
130 // this would increase the complexity of the non-deprecated methods
131 // and since it is undesirable to make non-deprecated methods
132 // less efficient, the following seems like the most reasonable
133 // approach.
134 if (in instanceof BufferedInputStream && (read() & 0xFF) != '\n')
135 {
136 BufferedInputStream bin = (BufferedInputStream) in;
137 if (bin.pos > 0)
138 bin.pos--;
139 }
140 else if (markSupported())
141 {
142 mark(1);
143 if ((read() & 0xFF) != '\n')
144 reset();
145 }
146 break;
147 }
148 strb.append(ch);
149 }
150
151 return strb.length() > 0 ? strb.toString() : null;
152 }
153
154 public final long readLong() throws IOException
155 {
156 long retval = 0L;
157 for (int i = 0; i < 8; i++)
158 retval |= (long) readUnsignedByte() << (56 - i * 8);
159
160 return retval;
161 }
162
163 public final short readShort() throws IOException
164 {
165 return (short) ((readByte() << 8) | readUnsignedByte());
166 }
167
168 public final int readUnsignedByte() throws IOException
169 {
170 int i = read();
171 if (i < 0)
172 throw new EOFException();
173
174 return (i & 0xFF);
175 }
176
177 public final int readUnsignedShort() throws IOException
178 {
179 return (readUnsignedByte() << 8) | readUnsignedByte();
180 }
181
182 public final String readUTF() throws IOException
183 {
184 return readUTF(this);
185 }
186
187 public final static String readUTF(DataInput in) throws IOException
188 {
189 final int UTFlen = in.readUnsignedShort();
190 byte[] buf = new byte[UTFlen];
191 StringBuffer strbuf = new StringBuffer();
192
193 // This blocks until the entire string is available rather than
194 // doing partial processing on the bytes that are available and then
195 // blocking. An advantage of the latter is that Exceptions
196 // could be thrown earlier. The former is a bit cleaner.
197 in.readFully(buf, 0, UTFlen);
198 for (int i = 0; i < UTFlen; )
199 {
200 if ((buf[i] & 0x80) == 0) // bit pattern 0xxxxxxx
201 strbuf.append((char) (buf[i++] & 0xFF));
202 else if ((buf[i] & 0xE0) == 0xC0) // bit pattern 110xxxxx
203 {
204 if (i + 1 >= UTFlen || (buf[i+1] & 0xC0) != 0x80)
205 throw new UTFDataFormatException();
206
207 strbuf.append((char) (((buf[i++] & 0x1F) << 6) |
208 (buf[i++] & 0x3F)));
209 }
210 else if ((buf[i] & 0xF0) == 0xE0) // bit pattern 1110xxxx
211 {
212 if (i + 2 >= UTFlen ||
213 (buf[i+1] & 0xC0) != 0x80 || (buf[i+2] & 0xC0) != 0x80)
214 throw new UTFDataFormatException();
215
216 strbuf.append((char) (((buf[i++] & 0x0F) << 12) |
217 ((buf[i++] & 0x3F) << 6) |
218 (buf[i++] & 0x3F)));
219 }
220 else // must be ((buf[i] & 0xF0) == 0xF0 || (buf[i] & 0xC0) == 0x80)
221 throw new UTFDataFormatException(); // bit patterns 1111xxxx or
222 // 10xxxxxx
223 }
224
225 return strbuf.toString();
226 }
227
228 public final int skipBytes(int n) throws IOException
229 {
230 // The contract in the Java Lang. Spec. says that this never
231 // throws an EOFException and infers that it doesn't block (since
232 // it may skip less than the requested number of bytes).
233 // BUT, the JCL book specifically says that this method blocks
234 // and can throw an EOFException. Finally, the Java 1.2 online
235 // doc simply refers to the general contract. As such, we will
236 // stick to the contract and assume for now that the JCL book
237 // is incorrect.
238
239 // Since we're only skipping at most an int number of bytes, the cast
240 // of return value to an int is fine.
241 if (n > 0)
242 {
243 n = Math.min(n, available());
244 return (int) super.skip((long) n);
245 }
246
247 return 0;
248 }
249 }