1/*
2 * reserved comment block
3 * DO NOT REMOVE OR ALTER!
4 */
5/*
6 * Licensed to the Apache Software Foundation (ASF) under one or more
7 * contributor license agreements.  See the NOTICE file distributed with
8 * this work for additional information regarding copyright ownership.
9 * The ASF licenses this file to You under the Apache License, Version 2.0
10 * (the "License"); you may not use this file except in compliance with
11 * the License.  You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 */
21
22package com.sun.org.apache.xerces.internal.impl.io;
23
24import java.io.InputStream;
25import java.io.IOException;
26import java.io.Reader;
27import java.util.Locale;
28import com.sun.org.apache.xerces.internal.util.MessageFormatter;
29import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
30
31import com.sun.xml.internal.stream.util.BufferAllocator;
32import com.sun.xml.internal.stream.util.ThreadLocalBufferAllocator;
33
34/**
35 * A simple ASCII byte reader. This is an optimized reader for reading
36 * byte streams that only contain 7-bit ASCII characters.
37 *
38 * @xerces.internal
39 *
40 * @author Andy Clark, IBM
41 *
42 */
43public class ASCIIReader
44    extends Reader {
45
46    //
47    // Constants
48    //
49
50    /** Default byte buffer size (2048). */
51    public static final int DEFAULT_BUFFER_SIZE = 2048;
52
53    //
54    // Data
55    //
56
57    /** Input stream. */
58    protected InputStream fInputStream;
59
60    /** Byte buffer. */
61    protected byte[] fBuffer;
62
63    // message formatter; used to produce localized
64    // exception messages
65    private MessageFormatter fFormatter = null;
66
67    //Locale to use for messages
68    private Locale fLocale = null;
69
70    //
71    // Constructors
72    //
73
74    /**
75     * Constructs an ASCII reader from the specified input stream
76     * using the default buffer size.
77     *
78     * @param inputStream The input stream.
79     * @param messageFormatter  the MessageFormatter to use to message reporting.
80     * @param locale    the Locale for which messages are to be reported
81     */
82    public ASCIIReader(InputStream inputStream, MessageFormatter messageFormatter,
83            Locale locale) {
84        this(inputStream, DEFAULT_BUFFER_SIZE, messageFormatter, locale);
85    } // <init>(InputStream, MessageFormatter, Locale)
86
87    /**
88     * Constructs an ASCII reader from the specified input stream
89     * and buffer size.
90     *
91     * @param inputStream The input stream.
92     * @param size        The initial buffer size.
93     * @param messageFormatter  the MessageFormatter to use to message reporting.
94     * @param locale    the Locale for which messages are to be reported
95     */
96    public ASCIIReader(InputStream inputStream, int size,
97            MessageFormatter messageFormatter, Locale locale) {
98        fInputStream = inputStream;
99        BufferAllocator ba = ThreadLocalBufferAllocator.getBufferAllocator();
100        fBuffer = ba.getByteBuffer(size);
101        if (fBuffer == null) {
102            fBuffer = new byte[size];
103        }
104        fFormatter = messageFormatter;
105        fLocale = locale;
106    } // <init>(InputStream,int, MessageFormatter, Locale)
107
108    //
109    // Reader methods
110    //
111
112    /**
113     * Read a single character.  This method will block until a character is
114     * available, an I/O error occurs, or the end of the stream is reached.
115     *
116     * <p> Subclasses that intend to support efficient single-character input
117     * should override this method.
118     *
119     * @return     The character read, as an integer in the range 0 to 127
120     *             (<tt>0x00-0x7f</tt>), or -1 if the end of the stream has
121     *             been reached
122     *
123     * @exception  IOException  If an I/O error occurs
124     */
125    public int read() throws IOException {
126        int b0 = fInputStream.read();
127        if (b0 >= 0x80) {
128            throw new MalformedByteSequenceException(fFormatter,
129                fLocale, XMLMessageFormatter.XML_DOMAIN,
130                "InvalidASCII", new Object [] {Integer.toString(b0)});
131        }
132        return b0;
133    } // read():int
134
135    /**
136     * Read characters into a portion of an array.  This method will block
137     * until some input is available, an I/O error occurs, or the end of the
138     * stream is reached.
139     *
140     * @param      ch     Destination buffer
141     * @param      offset Offset at which to start storing characters
142     * @param      length Maximum number of characters to read
143     *
144     * @return     The number of characters read, or -1 if the end of the
145     *             stream has been reached
146     *
147     * @exception  IOException  If an I/O error occurs
148     */
149    public int read(char ch[], int offset, int length) throws IOException {
150        if (length > fBuffer.length) {
151            length = fBuffer.length;
152        }
153        int count = fInputStream.read(fBuffer, 0, length);
154        for (int i = 0; i < count; i++) {
155            int b0 = fBuffer[i];
156            if (b0 < 0) {
157                throw new MalformedByteSequenceException(fFormatter,
158                    fLocale, XMLMessageFormatter.XML_DOMAIN,
159                    "InvalidASCII", new Object [] {Integer.toString(b0 & 0x0FF)});
160            }
161            ch[offset + i] = (char)b0;
162        }
163        return count;
164    } // read(char[],int,int)
165
166    /**
167     * Skip characters.  This method will block until some characters are
168     * available, an I/O error occurs, or the end of the stream is reached.
169     *
170     * @param  n  The number of characters to skip
171     *
172     * @return    The number of characters actually skipped
173     *
174     * @exception  IOException  If an I/O error occurs
175     */
176    public long skip(long n) throws IOException {
177        return fInputStream.skip(n);
178    } // skip(long):long
179
180    /**
181     * Tell whether this stream is ready to be read.
182     *
183     * @return True if the next read() is guaranteed not to block for input,
184     * false otherwise.  Note that returning false does not guarantee that the
185     * next read will block.
186     *
187     * @exception  IOException  If an I/O error occurs
188     */
189    public boolean ready() throws IOException {
190            return false;
191    } // ready()
192
193    /**
194     * Tell whether this stream supports the mark() operation.
195     */
196    public boolean markSupported() {
197            return fInputStream.markSupported();
198    } // markSupported()
199
200    /**
201     * Mark the present position in the stream.  Subsequent calls to reset()
202     * will attempt to reposition the stream to this point.  Not all
203     * character-input streams support the mark() operation.
204     *
205     * @param  readAheadLimit  Limit on the number of characters that may be
206     *                         read while still preserving the mark.  After
207     *                         reading this many characters, attempting to
208     *                         reset the stream may fail.
209     *
210     * @exception  IOException  If the stream does not support mark(),
211     *                          or if some other I/O error occurs
212     */
213    public void mark(int readAheadLimit) throws IOException {
214            fInputStream.mark(readAheadLimit);
215    } // mark(int)
216
217    /**
218     * Reset the stream.  If the stream has been marked, then attempt to
219     * reposition it at the mark.  If the stream has not been marked, then
220     * attempt to reset it in some way appropriate to the particular stream,
221     * for example by repositioning it to its starting point.  Not all
222     * character-input streams support the reset() operation, and some support
223     * reset() without supporting mark().
224     *
225     * @exception  IOException  If the stream has not been marked,
226     *                          or if the mark has been invalidated,
227     *                          or if the stream does not support reset(),
228     *                          or if some other I/O error occurs
229     */
230    public void reset() throws IOException {
231        fInputStream.reset();
232    } // reset()
233
234    /**
235     * Close the stream.  Once a stream has been closed, further read(),
236     * ready(), mark(), or reset() invocations will throw an IOException.
237     * Closing a previously-closed stream, however, has no effect.
238     *
239     * @exception  IOException  If an I/O error occurs
240     */
241     public void close() throws IOException {
242         BufferAllocator ba = ThreadLocalBufferAllocator.getBufferAllocator();
243         ba.returnByteBuffer(fBuffer);
244         fBuffer = null;
245         fInputStream.close();
246     } // close()
247
248} // class ASCIIReader
249