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 
22 package com.sun.org.apache.xerces.internal.impl.io;
23 
24 import java.io.InputStream;
25 import java.io.IOException;
26 import java.io.Reader;
27 import java.util.Locale;
28 import com.sun.org.apache.xerces.internal.util.MessageFormatter;
29 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
30 
31 import com.sun.xml.internal.stream.util.BufferAllocator;
32 import 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  */
43 public 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      */
ASCIIReader(InputStream inputStream, MessageFormatter messageFormatter, Locale locale)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      */
ASCIIReader(InputStream inputStream, int size, MessageFormatter messageFormatter, Locale locale)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      */
read()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      */
read(char ch[], int offset, int length)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      */
skip(long n)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      */
ready()189     public boolean ready() throws IOException {
190             return false;
191     } // ready()
192 
193     /**
194      * Tell whether this stream supports the mark() operation.
195      */
markSupported()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      */
mark(int readAheadLimit)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      */
reset()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      */
close()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