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