1 /***
2 * Redistribution and use in source and binary forms, with or without
3 * modification, are permitted provided that the following conditions are
4 * met :
5 *
6 * . Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 *
9 * . Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * . The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $Id$
29 */
30
31 package palmed.edit.text;
32
33 import java.io.IOException;
34 import java.io.InputStream;
35
36 /***
37 * This class reads a stream and builds the corresponding text.
38 *
39 * @author Mathieu Champlon
40 * @version $Revision$ $Date$
41 */
42 public final class TextReader
43 {
44 /***
45 * The carriage return character.
46 */
47 private static final char CR = '\r';
48 /***
49 * The line feed character.
50 */
51 private static final char LF = '\n';
52 /***
53 * The stream to read from.
54 */
55 private final InputStream stream_;
56 /***
57 * The text builder.
58 */
59 private final ITextBuilder builder_;
60 /***
61 * Whether the previous read byte was a carriage return or not.
62 */
63 private boolean wasCarriageReturn_;
64
65 /***
66 * Create a text reader.
67 *
68 * @param stream the stream to read from
69 * @param builder the text builder
70 */
71 public TextReader( final InputStream stream, final ITextBuilder builder )
72 {
73 if( stream == null )
74 throw new IllegalArgumentException( "parameter 'stream' is null" );
75 if( builder == null )
76 throw new IllegalArgumentException( "parameter 'builder' is null" );
77 stream_ = stream;
78 builder_ = builder;
79 wasCarriageReturn_ = false;
80 }
81
82 /***
83 * Read into the buffer and trigger builder callbacks.
84 *
85 * @param buffer the buffer
86 * @return the number of bytes read
87 * @throws IOException an io exception occurs
88 */
89 public int read( final byte[] buffer ) throws IOException
90 {
91 final int size = stream_.read( buffer );
92 if( size != -1 )
93 {
94 int start = 0;
95 for( int i = 0; i < size; ++i )
96 start = handle( buffer, start, i );
97 if( start != size )
98 builder_.append( buffer, start, size - start );
99 }
100 return size;
101 }
102
103 private int handle( final byte[] buffer, final int start, final int position )
104 {
105 if( buffer[position] != LF && buffer[position] != CR )
106 return start;
107 if( start != position )
108 builder_.append( buffer, start, position - start );
109 if( !wasCarriageReturn_ || buffer[position] != LF )
110 builder_.appendNewLine();
111 wasCarriageReturn_ = (buffer[position] == CR);
112 return position + 1;
113 }
114 }