OSDN Git Service

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