OSDN Git Service

2005-01-11 Michael Koch <konqueror@gmx.de>
[pf3gnuchains/gcc-fork.git] / libjava / gnu / java / net / LineInputStream.java
1 /* LineInputStream.java --
2    Copyright (C) 2002, 2003, 2004  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., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 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.ByteArrayOutputStream;
42 import java.io.FilterInputStream;
43 import java.io.InputStream;
44 import java.io.IOException;
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 FilterInputStream
53 {
54   /*
55    * Line buffer.
56    */
57   private ByteArrayOutputStream buf;
58
59   /*
60    * Encoding to use when translating bytes to characters.
61    */
62   private String encoding;
63
64   /*
65    * End-of-stream flag.
66    */
67   private boolean eof;
68
69   /**
70    * Whether we can use block reads.
71    */
72   private final boolean blockReads;
73
74   /**
75    * Constructor using the US-ASCII character encoding.
76    * @param in the underlying input stream
77    */
78   public LineInputStream(InputStream in)
79   {
80     this(in, "US-ASCII");
81   }
82
83   /**
84    * Constructor.
85    * @param in the underlying input stream
86    * @param encoding the character encoding to use
87    */
88   public LineInputStream(InputStream in, String encoding)
89   {
90     super(in);
91     buf = new ByteArrayOutputStream();
92     this.encoding = encoding;
93     eof = false;
94     blockReads = in.markSupported();
95   }
96
97   /**
98    * Read a line of input.
99    */
100   public String readLine()
101     throws IOException
102   {
103     if (eof)
104       {
105         return null;
106       }
107     do
108       {
109         if (blockReads)
110           {
111             // Use mark and reset to read chunks of bytes
112             final int MIN_LENGTH = 1024;
113             int len, pos;
114             
115             len = in.available();
116             len = (len < MIN_LENGTH) ? MIN_LENGTH : len;
117             byte[] b = new byte[len];
118             in.mark(len);
119             // Read into buffer b
120             len = in.read(b, 0, len);
121             // Handle EOF
122             if (len == -1)
123               {
124                 eof = true;
125                 if (buf.size() == 0)
126                   {
127                     return null;
128                   }
129                 else
130                   {
131                     // We don't care about resetting buf
132                     return buf.toString(encoding);
133                   }
134               }
135             // Get index of LF in b
136             pos = indexOf(b, len, (byte) 0x0a);
137             if (pos != -1)
138               {
139                 // Write pos bytes to buf
140                 buf.write(b, 0, pos);
141                 // Reset stream, and read pos + 1 bytes
142                 in.reset();
143                 pos += 1;
144                 while (pos > 0)
145                   {
146                     len = in.read(b, 0, pos);
147                     pos = (len == -1) ? -1 : pos - len;
148                   }
149                 // Return line
150                 String ret = buf.toString(encoding);
151                 buf.reset();
152                 return ret;
153               }
154             else
155               {
156                 // Append everything to buf and fall through to re-read.
157                 buf.write(b, 0, len);
158               }
159           }
160         else
161           {
162             // We must use character reads in order not to read too much
163             // from the underlying stream.
164             int c = in.read();
165             switch (c)
166               {
167               case -1:
168                 eof = true;
169                 if (buf.size() == 0)
170                   {
171                     return null;
172                   }
173                 // Fall through and return contents of buffer.
174               case 0x0a:                // LF
175                 String ret = buf.toString(encoding);
176                 buf.reset();
177                 return ret;
178               default:
179                 buf.write(c);
180               }
181           }
182       }
183     while (true);
184   }
185
186   private int indexOf(byte[] b, int len, byte c)
187   {
188     for (int pos = 0; pos < len; pos++)
189       {
190         if (b[pos] == c)
191           {
192             return pos;
193           }
194       }
195     return -1;
196   }
197 }
198