/[classpath]/classpath/java/io/LineNumberInputStream.java
ViewVC logotype

Diff of /classpath/java/io/LineNumberInputStream.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.6 by mark, Tue Jan 22 22:26:59 2002 UTC revision 1.7 by tromey, Mon Jun 17 03:49:21 2002 UTC
# Line 1  Line 1 
1  /* LineNumberInputStream.java -- An input stream which counts line numbers  /* LineNumberInputStream.java -- An input stream which counts line numbers
2     Copyright (C) 1998 Free Software Foundation, Inc.     Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc.
3    
4  This file is part of GNU Classpath.  This file is part of GNU Classpath.
5    
# Line 39  exception statement from your version. * Line 39  exception statement from your version. *
39  package java.io;  package java.io;
40    
41  /**  /**
42    * This class functions like a standard <code>InputStream</code> except that it   * This class functions like a standard <code>InputStream</code>
43    * counts line numbers, and canonicalizes newline characters.  As data   * except that it counts line numbers, and canonicalizes newline
44    * is read, whenever the byte sequences "\r", "\n", or "\r\n" are encountered,   * characters.  As data is read, whenever the byte sequences "\r",
45    * the running line count is incremeted by one.  Additionally, the whatever   * "\n", or "\r\n" are encountered, the running line count is
46    * line termination sequence was encountered will be converted to a "\n"   * incremeted by one.  Additionally, the whatever line termination
47    * byte.  Note that this class numbers lines from 0.  When the first   * sequence was encountered will be converted to a "\n" byte.  Note
48    * line terminator is encountered, the line number is incremented to 1, and   * that this class numbers lines from 0.  When the first line
49    * so on.   * terminator is encountered, the line number is incremented to 1, and
50    * <p>   * so on.
51    * This class counts only line termination characters.  If the last line   * <p>
52    * read from the stream does not end in a line termination sequence, it   * This class counts only line termination characters.  If the last line
53    * will not be counted as a line.   * read from the stream does not end in a line termination sequence, it
54    * <p>   * will not be counted as a line.
55    * Note that since this class operates as a filter on an underlying stream,   * <p>
56    * it has the same mark/reset functionality as the underlying stream.  The   * Note that since this class operates as a filter on an underlying
57    * <code>mark()</code> and <code>reset()</code> methods in this class handle line numbers   * stream, it has the same mark/reset functionality as the underlying
58    * correctly.  Calling @code{reset()} resets the line number to the point   * stream.  The <code>mark()</code> and <code>reset()</code> methods
59    * at which <code>mark()</code> was called if the subordinate stream supports   * in this class handle line numbers correctly.  Calling
60    * that functionality.   * @code{reset()} resets the line number to the point at which
61    * <p>   * <code>mark()</code> was called if the subordinate stream supports
62    * This class is deprecated in favor if <code>LineNumberReader</code> because   * that functionality.
63    * it operates on ASCII bytes instead of an encoded character stream.  This   * <p>
64    * class is for backward compatibility only and should not be used in   * @deprecated This class is deprecated in favor if
65    * new applications.   * <code>LineNumberReader</code> because it operates on ASCII bytes
66    *   * instead of an encoded character stream.  This class is for backward
67    * @deprecated   * compatibility only and should not be used in new applications.
68    *   *
69    * @version 0.0   * @author Aaron M. Renn (arenn@urbanophile.com)
70    *   * @author Warren Levy <warrenl@cygnus.com>
   * @author Aaron M. Renn (arenn@urbanophile.com)  
   */  
 public class LineNumberInputStream extends FilterInputStream  
 {  
   
 /*************************************************************************/  
   
 /*  
  * Instance Variables  
71   */   */
72    public class LineNumberInputStream extends FilterInputStream
 /**  
   * This variable is used to keep track of the current line number  
   */  
 private int line_number;  
   
 /**  
   * This variable is used to keep track of the line number that was  
   * current when the <code>mark()</code> method was called.  
   */  
 private int marked_line_number;  
   
 /*************************************************************************/  
   
 /*  
  * Constructors  
  */  
   
 /**  
   * Create a new <code>LineNumberInputStream</code> that reads from the  
   * specified subordinate <code>InputStream</code>  
   *  
   * @param in The subordinate <code>InputStream</code> to read from  
   */  
 public  
 LineNumberInputStream(InputStream in)  
 {  
   super(in);  
   
   // Override this.in with another filter  
   this.in = new PushbackInputStream(in);  
 }  
   
 /*************************************************************************/  
   
 /*  
  * Instance Methods  
  */  
   
 /**  
   * This method returns the current line number  
   *  
   * @returns The current line number  
   */  
 public int  
 getLineNumber()  
 {  
   return(line_number);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * This method sets the current line number to the specified value.  
   *  
   * @param line_number The new line number  
   */  
 public void  
 setLineNumber(int line_number)  
 {  
   this.line_number = line_number;  
 }  
   
 /*************************************************************************/  
   
 /**  
   * This method returns the number of bytes that can be read from the  
   * stream before the stream can block.  This method is tricky because  
   * the subordinate <code>InputStream</code> might return only "\r\n" characters,  
   * which are replaced by a single "\n" character by the <code>read()</code> method  
   * of this class.  So this method can only guarantee that  
   * <code>in.available() / 2</code> bytes can actually be read before blocking.  
   * In practice, considerably more bytes might be read before blocking  
   * <p>  
   * Note that the stream may not block if additional bytes beyond the count  
   * returned by this method are read.  
   *  
   * @return The number of bytes that can be read before blocking could occur  
   *  
   * @exception IOException If an error occurs  
   */  
 public int  
 available() throws IOException  
 {  
   return(in.available() / 2);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * This method marks a position in the input to which the stream can be  
   * "reset" byte calling the <code>reset()</code> method.  The parameter  
   * <code>readlimit</code> is the number of bytes that can be read from the  
   * stream after setting the mark before the mark becomes invalid.   For  
   * example, if <code>mark()</code> is called with a read limit of 10, then when  
   * 11 bytes of data are read from the stream before the <code>reset()</code>  
   * method is called, then the mark is invalid and the stream object  
   * instance is not required to remember the mark.  
   * <p>  
   * In this class, this method will remember the current line number as well  
   * as the current position in the stream.  When the <code>reset()</code> method  
   * is called, the line number will be restored to the saved line number in  
   * addition to the stream position.  
   * <p>  
   * This method only works if the subordinate stream supports mark/reset  
   * functionality.  
   *  
   * @param readlimit The number of bytes that can be read before the mark becomes invalid  
   */  
 public synchronized void  
 mark(int readlimit)  
 {  
   in.mark(readlimit);  
   
   marked_line_number = line_number;  
 }  
   
 /*************************************************************************/  
   
 /**  
   * This method resets a stream to the point where the <code>mark()</code> method  
   * was called.  Any bytes that were read after the mark point was set will  
   * be re-read during subsequent reads.  
   * <p>  
   * In this class, this method will also restore the line number that was  
   * current when the <code>mark()</code> method was called.  
   *  <p>  
   * This method only works if the subordinate stream supports mark/reset  
   * functionality.  
   *  
   * @exception IOException If an error occurs  
   */  
 public synchronized void  
 reset() throws IOException  
 {  
   in.reset();  
   
   line_number = marked_line_number;  
 }  
   
 /*************************************************************************/  
   
 /**  
   * This method reads an unsigned byte from the input stream and returns it  
   * as an int in the range of 0-255.  This method will return -1 if the  
   * end of the stream has been reached.  
   * <p>  
   * Note that if a line termination sequence is encountered (ie, "\r",  
   * "\n", or "\r\n") then that line termination sequence is converted to  
   * a single "\n" value which is returned from this method.  This means  
   * that it is possible this method reads two bytes from the subordinate  
   * stream instead of just one.  
   * <p>  
   * Note that this method will block until a byte of data is available  
   * to be read.  
   *  
   * @return The byte read or -1 if end of stream  
   *  
   * @exception IOException If an error occurs  
   */  
 public synchronized int  
 read() throws IOException  
 {  
   int byte_read = in.read();  
   
   if (byte_read == '\n')  
     ++line_number;  
   
   if (byte_read == '\r')  
     {  
       int extra_byte_read = in.read();  
   
       if ((extra_byte_read != '\n') && (extra_byte_read != -1))  
         ((PushbackInputStream)in).unread(extra_byte_read);  
   
       byte_read = '\n';  
       ++line_number;  
     }  
   
   return(byte_read);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * This method reads bytes from a stream and stores them into a caller  
   * supplied buffer.  It starts storing data at index <code>offset</code> into  
   * the buffer and attemps to read <code>len</code> bytes.  This method can  
   * return before reading the number of bytes requested.  The actual number  
   * of bytes read is returned as an int.  A -1 is returned to indicated the  
   * end of the stream.  
   * <p>  
   * This method will block until some data can be read.  
   * <p>  
   * Note that if a line termination sequence is encountered (ie, "\r",  
   * "\n", or "\r\n") then that line termination sequence is converted to  
   * a single "\n" value which is stored in the buffer.  Only a single  
   * byte is counted towards the number of bytes read in this case.  
   *  
   * @param buf The array into which the bytes read should be stored  
   * @param offset The offset into the array to start storing bytes  
   * @param len The requested number of bytes to read  
   *  
   * @return The actual number of bytes read, or -1 if end of stream  
   *  
   * @exception IOException If an error occurs.  
   */  
 public synchronized int  
 read(byte[] buf, int offset, int len) throws IOException  
73  {  {
74    if (len == 0)    /** The current line number. */
75      return(0);    private int lineNumber = 0;
76    
77    // Read the first byte here in order to allow IOException's to    /** The line number when the stream was marked. */
78    // propagate up    private int markLineNumber = 0;
   int byte_read = read();  
   if (byte_read == -1)  
     return(-1);  
   buf[offset] = (byte)byte_read;  
   
   int total_read = 1;  
   
   // Read the rest of the bytes.  We do this in a single read() loop  
   // like a raw InputStream. That's ok in my book since this class is  
   // deprecated anyway.  
   try  
     {  
       for (int i = 1; i < len; i++)  
         {  
           byte_read = read();  
           if (byte_read == -1)  
             return(total_read);  
   
           buf[offset + i] = (byte)byte_read;  
             
           ++total_read;    
         }  
     }  
   catch (IOException e)  
     {  
       return(total_read);  
     }  
   
   return(total_read);  
 }  
79    
80  /*************************************************************************/    /** Flag to indicate a '\r' was just read so that an immediately
81       * subsequent '\n' can be ignored. */
82      private boolean justReadReturnChar = false;
83    
84      /**
85       * Create a new <code>LineNumberInputStream</code> that reads from the
86       * specified subordinate <code>InputStream</code>
87       *
88       * @param in The subordinate <code>InputStream</code> to read from
89       */
90      public LineNumberInputStream(InputStream in)
91      {
92        super(in);
93      }
94    
95      /**
96       * This method returns the number of bytes that can be read from the
97       * stream before the stream can block.  This method is tricky
98       * because the subordinate <code>InputStream</code> might return
99       * only "\r\n" characters, which are replaced by a single "\n"
100       * character by the <code>read()</code> method of this class.  So
101       * this method can only guarantee that <code>in.available() /
102       * 2</code> bytes can actually be read before blocking.  In
103       * practice, considerably more bytes might be read before blocking
104       * <p>
105       * Note that the stream may not block if additional bytes beyond the count
106       * returned by this method are read.
107       *
108       * @return The number of bytes that can be read before blocking could occur
109       *
110       * @exception IOException If an error occurs
111       */
112      public int available() throws IOException
113      {
114        // We can only guarantee half the characters that might be available
115        // without blocking because "\r\n" is treated as a single character.
116        return in.available() / 2;
117      }
118    
119      /**
120       * This method returns the current line number
121       *
122       * @returns The current line number
123       */
124      public int getLineNumber()
125      {
126        return lineNumber;
127      }
128    
129      /**
130       * This method marks a position in the input to which the stream can
131       * be "reset" byte calling the <code>reset()</code> method.  The
132       * parameter <code>readlimit</code> is the number of bytes that can
133       * be read from the stream after setting the mark before the mark
134       * becomes invalid.  For example, if <code>mark()</code> is called
135       * with a read limit of 10, then when 11 bytes of data are read from
136       * the stream before the <code>reset()</code> method is called, then
137       * the mark is invalid and the stream object instance is not
138       * required to remember the mark.
139       * <p>
140       * In this class, this method will remember the current line number
141       * as well as the current position in the stream.  When the
142       * <code>reset()</code> method is called, the line number will be
143       * restored to the saved line number in addition to the stream
144       * position.
145       * <p>
146       * This method only works if the subordinate stream supports mark/reset
147       * functionality.
148       *
149       * @param readlimit The number of bytes that can be read before the
150       * mark becomes invalid
151       */
152      public void mark(int readlimit)
153      {
154        in.mark(readlimit);
155        markLineNumber = lineNumber;
156      }
157    
158      /**
159       * This method reads an unsigned byte from the input stream and returns it
160       * as an int in the range of 0-255.  This method will return -1 if the
161       * end of the stream has been reached.
162       * <p>
163       * Note that if a line termination sequence is encountered (ie, "\r",
164       * "\n", or "\r\n") then that line termination sequence is converted to
165       * a single "\n" value which is returned from this method.  This means
166       * that it is possible this method reads two bytes from the subordinate
167       * stream instead of just one.
168       * <p>
169       * Note that this method will block until a byte of data is available
170       * to be read.
171       *
172       * @return The byte read or -1 if end of stream
173       *
174       * @exception IOException If an error occurs
175       */
176      public int read() throws IOException
177      {
178        // Treat "\r\n" as a single character.  A '\r' may have been read by
179        // a previous call to read so we keep an internal flag to avoid having
180        // to read ahead.
181    
182        int ch = in.read();
183    
184        if (ch == '\n')
185          if (justReadReturnChar)
186            {
187              ch = in.read();
188              justReadReturnChar = false;
189            }
190          else
191            lineNumber++;
192        else if (ch == '\r')
193          {
194            ch = '\n';
195            justReadReturnChar = true;
196            lineNumber++;
197          }
198        else
199          justReadReturnChar = false;
200    
201        return ch;
202      }
203    
204      /**
205       * This method reads bytes from a stream and stores them into a caller
206       * supplied buffer.  It starts storing data at index <code>offset</code> into
207       * the buffer and attemps to read <code>len</code> bytes.  This method can
208       * return before reading the number of bytes requested.  The actual number
209       * of bytes read is returned as an int.  A -1 is returned to indicated the
210       * end of the stream.
211       * <p>
212       * This method will block until some data can be read.
213       * <p>
214       * Note that if a line termination sequence is encountered (ie, "\r",
215       * "\n", or "\r\n") then that line termination sequence is converted to
216       * a single "\n" value which is stored in the buffer.  Only a single
217       * byte is counted towards the number of bytes read in this case.
218       *
219       * @param buf The array into which the bytes read should be stored
220       * @param offset The offset into the array to start storing bytes
221       * @param len The requested number of bytes to read
222       *
223       * @return The actual number of bytes read, or -1 if end of stream
224       *
225       * @exception IOException If an error occurs.
226       */
227      public int read(byte[] b, int off, int len) throws IOException
228      {
229        if (off < 0 || len < 0 || off + len > b.length)
230          throw new ArrayIndexOutOfBoundsException();
231    
232        // This case always succeeds.
233        if (len == 0)
234          return 0;
235    
236        // The simplest, though not necessarily the most time efficient thing
237        // to do is simply call read(void) len times.  Since this is a deprecated
238        // class, that should be ok.
239        final int origOff = off;
240        while (len-- > 0)
241          {
242            int ch = read();
243            if (ch < 0)
244              break;
245    
246            b[off++] = (byte) ch;
247          }
248    
249        // This is safe since we already know that some bytes were
250        // actually requested.
251        return off == origOff ? -1 : off - origOff;
252      }
253    
254      /**
255       * This method resets a stream to the point where the
256       * <code>mark()</code> method was called.  Any bytes that were read
257       * after the mark point was set will be re-read during subsequent
258       * reads.
259       * <p>
260       * In this class, this method will also restore the line number that was
261       * current when the <code>mark()</code> method was called.
262       *  <p>
263       * This method only works if the subordinate stream supports mark/reset
264       * functionality.
265       *
266       * @exception IOException If an error occurs
267       */
268      public void reset() throws IOException
269      {
270        in.reset();
271        lineNumber = markLineNumber;
272        justReadReturnChar = false;
273      }
274    
275      /**
276       * This method sets the current line number to the specified value.
277       *
278       * @param lineNumber The new line number
279       */
280      public void setLineNumber(int lineNumber)
281      {
282        this.lineNumber = lineNumber;
283      }
284    
285      /**
286       * This method skips up to the requested number of bytes in the
287       * input stream.  The actual number of bytes skipped is returned.  If the
288       * desired number of bytes to skip is negative, no bytes are skipped.
289       *
290       * @param n requested number of bytes to skip.
291       *
292       * @return The actual number of bytes skipped.
293       *
294       * @exception IOException If an error occurs.
295       */
296      public long skip(long n) throws IOException
297      {
298        if (n <= 0)
299          return 0L;
300    
301        final long origN = n;
302    
303        do
304          {
305            int ch = read();
306            if (ch < 0)
307              break;
308            if (ch == '\n' || ch == '\r')
309              lineNumber++;
310          }
311        while (--n > 0);
312    
313  /**      return origN - n;
314    * This method skips up to the requested number of bytes in the    }
   * input stream.  The actual number of bytes skipped is returned.  If the  
   * desired number of bytes to skip is negative, no bytes are skipped.  
   *  
   * @param num_byte The requested number of bytes to skip.  
   *  
   * @return The actual number of bytes skipped.  
   *  
   * @exception IOException If an error occurs.  
   */  
 public long  
 skip(long num_bytes) throws IOException  
 {  
   return(super.skip(num_bytes));  
315  }  }
   
 } // class LineNumberInputStream  
   

Legend:
Removed from v.1.6  
changed lines
  Added in v.1.7

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26