1/*
2 * Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.io;
27
28/**
29 * This class is an input stream filter that provides the added
30 * functionality of keeping track of the current line number.
31 * <p>
32 * A line is a sequence of bytes ending with a carriage return
33 * character ({@code '\u005Cr'}), a newline character
34 * ({@code '\u005Cn'}), or a carriage return character followed
35 * immediately by a linefeed character. In all three cases, the line
36 * terminating character(s) are returned as a single newline character.
37 * <p>
38 * The line number begins at {@code 0}, and is incremented by
39 * {@code 1} when a {@code read} returns a newline character.
40 *
41 * @author     Arthur van Hoff
42 * @see        java.io.LineNumberReader
43 * @since      JDK1.0
44 * @deprecated This class incorrectly assumes that bytes adequately represent
45 *             characters.  As of JDK&nbsp;1.1, the preferred way to operate on
46 *             character streams is via the new character-stream classes, which
47 *             include a class for counting line numbers.
48 */
49@Deprecated
50public
51class LineNumberInputStream extends FilterInputStream {
52    int pushBack = -1;
53    int lineNumber;
54    int markLineNumber;
55    int markPushBack = -1;
56
57    /**
58     * Constructs a newline number input stream that reads its input
59     * from the specified input stream.
60     *
61     * @param      in   the underlying input stream.
62     */
63    public LineNumberInputStream(InputStream in) {
64        super(in);
65    }
66
67    /**
68     * Reads the next byte of data from this input stream. The value
69     * byte is returned as an {@code int} in the range
70     * {@code 0} to {@code 255}. If no byte is available
71     * because the end of the stream has been reached, the value
72     * {@code -1} is returned. This method blocks until input data
73     * is available, the end of the stream is detected, or an exception
74     * is thrown.
75     * <p>
76     * The {@code read} method of
77     * {@code LineNumberInputStream} calls the {@code read}
78     * method of the underlying input stream. It checks for carriage
79     * returns and newline characters in the input, and modifies the
80     * current line number as appropriate. A carriage-return character or
81     * a carriage return followed by a newline character are both
82     * converted into a single newline character.
83     *
84     * @return     the next byte of data, or {@code -1} if the end of this
85     *             stream is reached.
86     * @exception  IOException  if an I/O error occurs.
87     * @see        java.io.FilterInputStream#in
88     * @see        java.io.LineNumberInputStream#getLineNumber()
89     */
90    @SuppressWarnings("fallthrough")
91    public int read() throws IOException {
92        int c = pushBack;
93
94        if (c != -1) {
95            pushBack = -1;
96        } else {
97            c = in.read();
98        }
99
100        switch (c) {
101          case '\r':
102            pushBack = in.read();
103            if (pushBack == '\n') {
104                pushBack = -1;
105            }
106          case '\n':
107            lineNumber++;
108            return '\n';
109        }
110        return c;
111    }
112
113    /**
114     * Reads up to {@code len} bytes of data from this input stream
115     * into an array of bytes. This method blocks until some input is available.
116     * <p>
117     * The {@code read} method of
118     * {@code LineNumberInputStream} repeatedly calls the
119     * {@code read} method of zero arguments to fill in the byte array.
120     *
121     * @param      b     the buffer into which the data is read.
122     * @param      off   the start offset of the data.
123     * @param      len   the maximum number of bytes read.
124     * @return     the total number of bytes read into the buffer, or
125     *             {@code -1} if there is no more data because the end of
126     *             this stream has been reached.
127     * @exception  IOException  if an I/O error occurs.
128     * @see        java.io.LineNumberInputStream#read()
129     */
130    public int read(byte b[], int off, int len) throws IOException {
131        if (b == null) {
132            throw new NullPointerException();
133        } else if ((off < 0) || (off > b.length) || (len < 0) ||
134                   ((off + len) > b.length) || ((off + len) < 0)) {
135            throw new IndexOutOfBoundsException();
136        } else if (len == 0) {
137            return 0;
138        }
139
140        int c = read();
141        if (c == -1) {
142            return -1;
143        }
144        b[off] = (byte)c;
145
146        int i = 1;
147        try {
148            for (; i < len ; i++) {
149                c = read();
150                if (c == -1) {
151                    break;
152                }
153                if (b != null) {
154                    b[off + i] = (byte)c;
155                }
156            }
157        } catch (IOException ee) {
158        }
159        return i;
160    }
161
162    /**
163     * Skips over and discards {@code n} bytes of data from this
164     * input stream. The {@code skip} method may, for a variety of
165     * reasons, end up skipping over some smaller number of bytes,
166     * possibly {@code 0}. The actual number of bytes skipped is
167     * returned.  If {@code n} is negative, no bytes are skipped.
168     * <p>
169     * The {@code skip} method of {@code LineNumberInputStream} creates
170     * a byte array and then repeatedly reads into it until
171     * {@code n} bytes have been read or the end of the stream has
172     * been reached.
173     *
174     * @param      n   the number of bytes to be skipped.
175     * @return     the actual number of bytes skipped.
176     * @exception  IOException  if an I/O error occurs.
177     * @see        java.io.FilterInputStream#in
178     */
179    public long skip(long n) throws IOException {
180        int chunk = 2048;
181        long remaining = n;
182        byte data[];
183        int nr;
184
185        if (n <= 0) {
186            return 0;
187        }
188
189        data = new byte[chunk];
190        while (remaining > 0) {
191            nr = read(data, 0, (int) Math.min(chunk, remaining));
192            if (nr < 0) {
193                break;
194            }
195            remaining -= nr;
196        }
197
198        return n - remaining;
199    }
200
201    /**
202     * Sets the line number to the specified argument.
203     *
204     * @param      lineNumber   the new line number.
205     * @see #getLineNumber
206     */
207    public void setLineNumber(int lineNumber) {
208        this.lineNumber = lineNumber;
209    }
210
211    /**
212     * Returns the current line number.
213     *
214     * @return     the current line number.
215     * @see #setLineNumber
216     */
217    public int getLineNumber() {
218        return lineNumber;
219    }
220
221
222    /**
223     * Returns the number of bytes that can be read from this input
224     * stream without blocking.
225     * <p>
226     * Note that if the underlying input stream is able to supply
227     * <i>k</i> input characters without blocking, the
228     * {@code LineNumberInputStream} can guarantee only to provide
229     * <i>k</i>/2 characters without blocking, because the
230     * <i>k</i> characters from the underlying input stream might
231     * consist of <i>k</i>/2 pairs of {@code '\u005Cr'} and
232     * {@code '\u005Cn'}, which are converted to just
233     * <i>k</i>/2 {@code '\u005Cn'} characters.
234     *
235     * @return     the number of bytes that can be read from this input stream
236     *             without blocking.
237     * @exception  IOException  if an I/O error occurs.
238     * @see        java.io.FilterInputStream#in
239     */
240    public int available() throws IOException {
241        return (pushBack == -1) ? super.available()/2 : super.available()/2 + 1;
242    }
243
244    /**
245     * Marks the current position in this input stream. A subsequent
246     * call to the {@code reset} method repositions this stream at
247     * the last marked position so that subsequent reads re-read the same bytes.
248     * <p>
249     * The {@code mark} method of
250     * {@code LineNumberInputStream} remembers the current line
251     * number in a private variable, and then calls the {@code mark}
252     * method of the underlying input stream.
253     *
254     * @param   readlimit   the maximum limit of bytes that can be read before
255     *                      the mark position becomes invalid.
256     * @see     java.io.FilterInputStream#in
257     * @see     java.io.LineNumberInputStream#reset()
258     */
259    public void mark(int readlimit) {
260        markLineNumber = lineNumber;
261        markPushBack   = pushBack;
262        in.mark(readlimit);
263    }
264
265    /**
266     * Repositions this stream to the position at the time the
267     * {@code mark} method was last called on this input stream.
268     * <p>
269     * The {@code reset} method of
270     * {@code LineNumberInputStream} resets the line number to be
271     * the line number at the time the {@code mark} method was
272     * called, and then calls the {@code reset} method of the
273     * underlying input stream.
274     * <p>
275     * Stream marks are intended to be used in
276     * situations where you need to read ahead a little to see what's in
277     * the stream. Often this is most easily done by invoking some
278     * general parser. If the stream is of the type handled by the
279     * parser, it just chugs along happily. If the stream is not of
280     * that type, the parser should toss an exception when it fails,
281     * which, if it happens within readlimit bytes, allows the outer
282     * code to reset the stream and try another parser.
283     *
284     * @exception  IOException  if an I/O error occurs.
285     * @see        java.io.FilterInputStream#in
286     * @see        java.io.LineNumberInputStream#mark(int)
287     */
288    public void reset() throws IOException {
289        lineNumber = markLineNumber;
290        pushBack   = markPushBack;
291        in.reset();
292    }
293}
294