OSDN Git Service

Normalise whitespace in GNU Classpath.
[pf3gnuchains/gcc-fork.git] / libjava / classpath / gnu / java / net / LineInputStream.java
1 /* LineInputStream.java --
2    Copyright (C) 2002, 2003, 2004, 2005, 2006  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
39 package gnu.java.net;
40
41 import java.io.BufferedInputStream;
42 import java.io.ByteArrayOutputStream;
43 import java.io.IOException;
44 import java.io.InputStream;
45
46 /**
47  * An input stream that can read lines of input.
48  *
49  * @author Chris Burdess (dog@gnu.org)
50  */
51 public class LineInputStream
52   extends InputStream
53 {
54
55   /**
56    * The underlying input stream.
57    */
58   protected InputStream in;
59
60   /*
61    * Line buffer.
62    */
63   private ByteArrayOutputStream buf;
64
65   /*
66    * Encoding to use when translating bytes to characters.
67    */
68   private String encoding;
69
70   /*
71    * End-of-stream flag.
72    */
73   private boolean eof;
74
75   /**
76    * Whether we can use block reads.
77    */
78   private final boolean blockReads;
79
80   /**
81    * Constructor using the US-ASCII character encoding.
82    * @param in the underlying input stream
83    */
84   public LineInputStream(InputStream in)
85   {
86     this(in, "US-ASCII");
87   }
88
89   /**
90    * Constructor.
91    * @param in the underlying input stream
92    * @param encoding the character encoding to use
93    */
94   public LineInputStream(InputStream in, String encoding)
95   {
96     this.in = in;
97     buf = new ByteArrayOutputStream();
98     this.encoding = encoding;
99     eof = false;
100     // If it is already buffered, additional buffering gains nothing.
101     blockReads = !(in instanceof BufferedInputStream) && in.markSupported();
102   }
103
104   public int read()
105     throws IOException
106   {
107     return in.read();
108   }
109
110   public int read(byte[] buf)
111     throws IOException
112   {
113     return in.read(buf);
114   }
115
116   public int read(byte[] buf, int off, int len)
117     throws IOException
118   {
119     return in.read(buf, off, len);
120   }
121
122   /**
123    * Read a line of input.
124    */
125   public String readLine()
126     throws IOException
127   {
128     if (eof)
129       {
130         return null;
131       }
132     do
133       {
134         if (blockReads)
135           {
136             // Use mark and reset to read chunks of bytes
137             final int MAX_LENGTH = 1024;
138             int len, pos;
139
140             len = in.available();
141             if (len == 0 || len > MAX_LENGTH)
142               len = MAX_LENGTH;
143             byte[] b = new byte[len];
144             in.mark(len);
145             // Read into buffer b
146             len = in.read(b, 0, len);
147             // Handle EOF
148             if (len == -1)
149               {
150                 eof = true;
151                 if (buf.size() == 0)
152                   {
153                     return null;
154                   }
155                 else
156                   {
157                     // We don't care about resetting buf
158                     return buf.toString(encoding);
159                   }
160               }
161             // Get index of LF in b
162             pos = indexOf(b, len, (byte) 0x0a);
163             if (pos != -1)
164               {
165                 // Write pos bytes to buf
166                 buf.write(b, 0, pos);
167                 // Reset stream, and read pos + 1 bytes
168                 in.reset();
169                 pos += 1;
170                 while (pos > 0)
171                   {
172                     len = in.read(b, 0, pos);
173                     pos = (len == -1) ? -1 : pos - len;
174                   }
175                 // Return line
176                 String ret = buf.toString(encoding);
177                 buf.reset();
178                 return ret;
179               }
180             else
181               {
182                 // Append everything to buf and fall through to re-read.
183                 buf.write(b, 0, len);
184               }
185           }
186         else
187           {
188             // We must use character reads in order not to read too much
189             // from the underlying stream.
190             int c = in.read();
191             switch (c)
192               {
193               case -1:
194                 eof = true;
195                 if (buf.size() == 0)
196                   {
197                     return null;
198                   }
199                 // Fall through and return contents of buffer.
200               case 0x0a:                // LF
201                 String ret = buf.toString(encoding);
202                 buf.reset();
203                 return ret;
204               default:
205                 buf.write(c);
206               }
207           }
208       }
209     while (true);
210   }
211
212   private int indexOf(byte[] b, int len, byte c)
213   {
214     for (int pos = 0; pos < len; pos++)
215       {
216         if (b[pos] == c)
217           {
218             return pos;
219           }
220       }
221     return -1;
222   }
223 }