1 9 package javolution.io; 10 11 import j2me.lang.IllegalStateException; 12 import j2me.io.CharConversionException; 13 import j2me.nio.BufferUnderflowException; 14 import j2me.nio.ByteBuffer; 15 16 import java.io.IOException; 17 import java.io.Reader; 18 19 import javolution.lang.Appendable; 20 import javolution.lang.Reusable; 21 22 44 public final class Utf8ByteBufferReader extends Reader implements Reusable { 45 46 49 private ByteBuffer _byteBuffer; 50 51 54 public Utf8ByteBufferReader() { 55 } 56 57 66 public Utf8ByteBufferReader setByteBuffer(ByteBuffer byteBuffer) { 67 if (_byteBuffer != null) 68 throw new IllegalStateException("Reader not closed or reset"); 69 _byteBuffer = byteBuffer; 70 return this; 71 } 72 73 80 public boolean ready() throws IOException { 81 if (_byteBuffer != null) { 82 return _byteBuffer.hasRemaining(); 83 } else { 84 throw new IOException("Reader closed"); 85 } 86 } 87 88 93 public void close() throws IOException { 94 if (_byteBuffer != null) { 95 reset(); 96 } 97 } 98 99 108 public int read() throws IOException { 109 if (_byteBuffer != null) { 110 if (_byteBuffer.hasRemaining()) { 111 byte b = _byteBuffer.get(); 112 return (b >= 0) ? b : read2(b); 113 } else { 114 return -1; 115 } 116 } else { 117 throw new IOException("Reader closed"); 118 } 119 } 120 121 private int read2(byte b) throws IOException { 123 try { 124 if ((b >= 0) && (_moreBytes == 0)) { 126 return b; 128 } else if (((b & 0xc0) == 0x80) && (_moreBytes != 0)) { 129 _code = (_code << 6) | (b & 0x3f); if (--_moreBytes == 0) { 132 return _code; 133 } else { 134 return read2(_byteBuffer.get()); 135 } 136 } else if (((b & 0xe0) == 0xc0) && (_moreBytes == 0)) { 137 _code = b & 0x1f; 139 _moreBytes = 1; 140 return read2(_byteBuffer.get()); 141 } else if (((b & 0xf0) == 0xe0) && (_moreBytes == 0)) { 142 _code = b & 0x0f; 144 _moreBytes = 2; 145 return read2(_byteBuffer.get()); 146 } else if (((b & 0xf8) == 0xf0) && (_moreBytes == 0)) { 147 _code = b & 0x07; 149 _moreBytes = 3; 150 return read2(_byteBuffer.get()); 151 } else if (((b & 0xfc) == 0xf8) && (_moreBytes == 0)) { 152 _code = b & 0x03; 154 _moreBytes = 4; 155 return read2(_byteBuffer.get()); 156 } else if (((b & 0xfe) == 0xfc) && (_moreBytes == 0)) { 157 _code = b & 0x01; 159 _moreBytes = 5; 160 return read2(_byteBuffer.get()); 161 } else { 162 throw new CharConversionException("Invalid UTF-8 Encoding"); 163 } 164 } catch (BufferUnderflowException e) { 165 throw new CharConversionException("Incomplete Sequence"); 166 } 167 } 168 169 private int _code; 170 171 private int _moreBytes; 172 173 187 public int read(char cbuf[], int off, int len) throws IOException { 188 if (_byteBuffer == null) 189 throw new IOException("Reader closed"); 190 final int off_plus_len = off + len; 191 int remaining = _byteBuffer.remaining(); 192 for (int i = off; i < off_plus_len;) { 193 if (remaining-- > 0) { 194 byte b = _byteBuffer.get(); 195 if (b >= 0) { 196 cbuf[i++] = (char) b; } else { 198 if (i < off_plus_len - 1) { int code = read2(b); 200 remaining = _byteBuffer.remaining(); if (code < 0x10000) { 202 cbuf[i++] = (char) code; 203 } else if (code <= 0x10ffff) { cbuf[i++] = (char) (((code - 0x10000) >> 10) + 0xd800); 205 cbuf[i++] = (char) (((code - 0x10000) & 0x3ff) + 0xdc00); 206 } else { 207 throw new CharConversionException( 208 "Cannot convert U+" 209 + Integer.toHexString(code) 210 + " to char (code greater than U+10FFFF)"); 211 } 212 } else { _byteBuffer.position(_byteBuffer.position() - 1); 214 remaining++; 215 return i - off; 216 } 217 } 218 } else { 219 return i - off; 220 } 221 } 222 return len; 223 } 224 225 235 public void read(Appendable dest) throws IOException { 236 if (_byteBuffer == null) 237 throw new IOException("Reader closed"); 238 while (_byteBuffer.hasRemaining()) { 239 byte b = _byteBuffer.get(); 240 if (b >= 0) { 241 dest.append((char) b); } else { 243 int code = read2(b); 244 if (code < 0x10000) { 245 dest.append((char) code); 246 } else if (code <= 0x10ffff) { dest.append((char) (((code - 0x10000) >> 10) + 0xd800)); 248 dest.append((char) (((code - 0x10000) & 0x3ff) + 0xdc00)); 249 } else { 250 throw new CharConversionException("Cannot convert U+" 251 + Integer.toHexString(code) 252 + " to char (code greater than U+10FFFF)"); 253 } 254 } 255 } 256 } 257 258 public void reset() { 260 _byteBuffer = null; 261 _code = 0; 262 _moreBytes = 0; 263 } 264 } | Popular Tags |