1 9 package javolution.io; 10 11 import j2me.lang.IllegalStateException; 12 import j2me.io.CharConversionException; 13 14 import java.io.IOException; 15 import java.io.InputStream; 16 import java.io.Reader; 17 18 import javolution.lang.Appendable; 19 import javolution.lang.Reusable; 20 21 49 public final class Utf8StreamReader extends Reader implements Reusable { 50 51 54 private InputStream _inputStream; 55 56 59 private int _start; 60 61 64 private int _end; 65 66 69 private final byte[] _bytes; 70 71 74 public Utf8StreamReader() { 75 _bytes = new byte[2048]; 76 } 77 78 83 public Utf8StreamReader(int capacity) { 84 _bytes = new byte[capacity]; 85 } 86 87 100 public Utf8StreamReader setInputStream(InputStream inStream) { 101 if (_inputStream != null) 102 throw new IllegalStateException("Reader not closed or reset"); 103 _inputStream = inStream; 104 return this; 105 } 106 107 114 public boolean ready() throws IOException { 115 if (_inputStream == null) 116 throw new IOException("Stream closed"); 117 return ((_end - _start) > 0) || (_inputStream.available() != 0); 118 } 119 120 125 public void close() throws IOException { 126 if (_inputStream != null) { 127 _inputStream.close(); 128 reset(); 129 } 130 } 131 132 140 public int read() throws IOException { 141 byte b = _bytes[_start]; 142 return ((b >= 0) && (_start++ < _end)) ? b : read2(); 143 } 144 145 private int read2() throws IOException { 147 if (_start < _end) { 148 byte b = _bytes[_start++]; 149 150 if ((b >= 0) && (_moreBytes == 0)) { 152 return b; 154 } else if (((b & 0xc0) == 0x80) && (_moreBytes != 0)) { 155 _code = (_code << 6) | (b & 0x3f); if (--_moreBytes == 0) { 158 return _code; 159 } else { 160 return read2(); 161 } 162 } else if (((b & 0xe0) == 0xc0) && (_moreBytes == 0)) { 163 _code = b & 0x1f; 165 _moreBytes = 1; 166 return read2(); 167 } else if (((b & 0xf0) == 0xe0) && (_moreBytes == 0)) { 168 _code = b & 0x0f; 170 _moreBytes = 2; 171 return read2(); 172 } else if (((b & 0xf8) == 0xf0) && (_moreBytes == 0)) { 173 _code = b & 0x07; 175 _moreBytes = 3; 176 return read2(); 177 } else if (((b & 0xfc) == 0xf8) && (_moreBytes == 0)) { 178 _code = b & 0x03; 180 _moreBytes = 4; 181 return read2(); 182 } else if (((b & 0xfe) == 0xfc) && (_moreBytes == 0)) { 183 _code = b & 0x01; 185 _moreBytes = 5; 186 return read2(); 187 } else { 188 throw new CharConversionException("Invalid UTF-8 Encoding"); 189 } 190 } else { if (_inputStream == null) 192 throw new IOException("Stream closed"); 193 _start = 0; 194 _end = _inputStream.read(_bytes, 0, _bytes.length); 195 if (_end > 0) { 196 return read2(); } else { if (_moreBytes == 0) { 199 return -1; 200 } else { throw new CharConversionException( 202 "Unexpected end of stream"); 203 } 204 } 205 } 206 } 207 208 private int _code; 209 210 private int _moreBytes; 211 212 227 public int read(char cbuf[], int off, int len) throws IOException { 228 if (_inputStream == null) 229 throw new IOException("Stream closed"); 230 if (_start >= _end) { _start = 0; 232 _end = _inputStream.read(_bytes, 0, _bytes.length); 233 if (_end <= 0) { return _end; 235 } 236 } 237 final int off_plus_len = off + len; 238 for (int i = off; i < off_plus_len;) { 239 byte b = _bytes[_start]; 241 if ((b >= 0) && (++_start < _end)) { 242 cbuf[i++] = (char) b; } else if (b < 0) { 244 if (i < off_plus_len - 1) { int code = read2(); 246 if (code < 0x10000) { 247 cbuf[i++] = (char) code; 248 } else if (code <= 0x10ffff) { cbuf[i++] = (char) (((code - 0x10000) >> 10) + 0xd800); 250 cbuf[i++] = (char) (((code - 0x10000) & 0x3ff) + 0xdc00); 251 } else { 252 throw new CharConversionException("Cannot convert U+" 253 + Integer.toHexString(code) 254 + " to char (code greater than U+10FFFF)"); 255 } 256 if (_start < _end) { 257 continue; 258 } 259 } 260 return i - off; 261 } else { cbuf[i++] = (char) b; 263 return i - off; 264 } 265 } 266 return len; 267 } 268 269 276 public void read(Appendable dest) throws IOException { 277 if (_inputStream == null) 278 throw new IOException("Stream closed"); 279 while (true) { 280 if (_start >= _end) { _start = 0; 282 _end = _inputStream.read(_bytes, 0, _bytes.length); 283 if (_end <= 0) { break; 285 } 286 } 287 byte b = _bytes[_start]; 288 if (b >= 0) { 289 dest.append((char) b); _start++; 291 } else { 292 int code = read2(); 293 if (code < 0x10000) { 294 dest.append((char) code); 295 } else if (code <= 0x10ffff) { dest.append((char) (((code - 0x10000) >> 10) + 0xd800)); 297 dest.append((char) (((code - 0x10000) & 0x3ff) + 0xdc00)); 298 } else { 299 throw new CharConversionException("Cannot convert U+" 300 + Integer.toHexString(code) 301 + " to char (code greater than U+10FFFF)"); 302 } 303 } 304 } 305 } 306 307 public void reset() { 309 _code = 0; 310 _end = 0; 311 _inputStream = null; 312 _moreBytes = 0; 313 _start = 0; 314 } 315 316 } | Popular Tags |