1 7 8 10 package java.nio.charset; 11 12 import java.nio.Buffer ; 13 import java.nio.ByteBuffer ; 14 import java.nio.CharBuffer ; 15 import java.nio.BufferOverflowException ; 16 import java.nio.BufferUnderflowException ; 17 import java.lang.ref.WeakReference ; 18 import java.nio.charset.CoderMalfunctionError ; 20 21 118 119 public abstract class CharsetDecoder { 120 121 private final Charset charset; 122 private final float averageCharsPerByte; 123 private final float maxCharsPerByte; 124 125 private String replacement; 126 private CodingErrorAction malformedInputAction 127 = CodingErrorAction.REPORT; 128 private CodingErrorAction unmappableCharacterAction 129 = CodingErrorAction.REPORT; 130 131 private static final int ST_RESET = 0; 134 private static final int ST_CODING = 1; 135 private static final int ST_END = 2; 136 private static final int ST_FLUSHED = 3; 137 138 private int state = ST_RESET; 139 140 private static String stateNames[] 141 = { "RESET", "CODING", "CODING_END", "FLUSHED" }; 142 143 144 164 private 165 CharsetDecoder(Charset cs, 166 float averageCharsPerByte, 167 float maxCharsPerByte, 168 String replacement) 169 { 170 this.charset = cs; 171 if (averageCharsPerByte <= 0.0f) 172 throw new IllegalArgumentException ("Non-positive " 173 + "averageCharsPerByte"); 174 if (maxCharsPerByte <= 0.0f) 175 throw new IllegalArgumentException ("Non-positive " 176 + "maxCharsPerByte"); 177 if (!Charset.atBugLevel("1.4")) { 178 if (averageCharsPerByte > maxCharsPerByte) 179 throw new IllegalArgumentException ("averageCharsPerByte" 180 + " exceeds " 181 + "maxCharsPerByte"); 182 } 183 this.replacement = replacement; 184 this.averageCharsPerByte = averageCharsPerByte; 185 this.maxCharsPerByte = maxCharsPerByte; 186 replaceWith(replacement); 187 } 188 189 205 protected CharsetDecoder(Charset cs, 206 float averageCharsPerByte, 207 float maxCharsPerByte) 208 { 209 this(cs, 210 averageCharsPerByte, maxCharsPerByte, 211 "\uFFFD"); 212 } 213 214 219 public final Charset charset() { 220 return charset; 221 } 222 223 229 public final String replacement() { 230 return replacement; 231 } 232 233 258 public final CharsetDecoder replaceWith(String newReplacement) { 259 if (newReplacement == null) 260 throw new IllegalArgumentException ("Null replacement"); 261 int len = newReplacement.length(); 262 if (len == 0) 263 throw new IllegalArgumentException ("Empty replacement"); 264 if (len > maxCharsPerByte) 265 throw new IllegalArgumentException ("Replacement too long"); 266 267 268 269 270 this.replacement = newReplacement; 271 implReplaceWith(newReplacement); 272 return this; 273 } 274 275 284 protected void implReplaceWith(String newReplacement) { 285 } 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 334 public CodingErrorAction malformedInputAction() { 335 return malformedInputAction; 336 } 337 338 351 public final CharsetDecoder onMalformedInput(CodingErrorAction newAction) { 352 if (newAction == null) 353 throw new IllegalArgumentException ("Null action"); 354 malformedInputAction = newAction; 355 implOnMalformedInput(newAction); 356 return this; 357 } 358 359 366 protected void implOnMalformedInput(CodingErrorAction newAction) { } 367 368 375 public CodingErrorAction unmappableCharacterAction() { 376 return unmappableCharacterAction; 377 } 378 379 392 public final CharsetDecoder onUnmappableCharacter(CodingErrorAction 393 newAction) 394 { 395 if (newAction == null) 396 throw new IllegalArgumentException ("Null action"); 397 unmappableCharacterAction = newAction; 398 implOnUnmappableCharacter(newAction); 399 return this; 400 } 401 402 409 protected void implOnUnmappableCharacter(CodingErrorAction newAction) { } 410 411 419 public final float averageCharsPerByte() { 420 return averageCharsPerByte; 421 } 422 423 431 public final float maxCharsPerByte() { 432 return maxCharsPerByte; 433 } 434 435 531 public final CoderResult decode(ByteBuffer in, CharBuffer out, 532 boolean endOfInput) 533 { 534 int newState = endOfInput ? ST_END : ST_CODING; 535 if ((state != ST_RESET) && (state != ST_CODING) 536 && !(endOfInput && (state == ST_END))) 537 throwIllegalStateException(state, newState); 538 state = newState; 539 540 for (;;) { 541 542 CoderResult cr; 543 try { 544 cr = decodeLoop(in, out); 545 } catch (BufferUnderflowException x) { 546 throw new CoderMalfunctionError (x); 547 } catch (BufferOverflowException x) { 548 throw new CoderMalfunctionError (x); 549 } 550 551 if (cr.isOverflow()) 552 return cr; 553 554 if (cr.isUnderflow()) { 555 if (endOfInput && in.hasRemaining()) { 556 cr = CoderResult.malformedForLength(in.remaining()); 557 } else { 559 return cr; 560 } 561 } 562 563 CodingErrorAction action = null; 564 if (cr.isMalformed()) 565 action = malformedInputAction; 566 else if (cr.isUnmappable()) 567 action = unmappableCharacterAction; 568 else 569 assert false : cr.toString(); 570 571 if (action == CodingErrorAction.REPORT) 572 return cr; 573 574 if (action == CodingErrorAction.REPLACE) { 575 if (out.remaining() < replacement.length()) 576 return CoderResult.OVERFLOW; 577 out.put(replacement); 578 } 579 580 if ((action == CodingErrorAction.IGNORE) 581 || (action == CodingErrorAction.REPLACE)) { 582 in.position(in.position() + cr.length()); 584 continue; 585 } 586 587 assert false; 588 } 589 590 } 591 592 628 public final CoderResult flush(CharBuffer out) { 629 if (state != ST_END) 630 throwIllegalStateException(state, ST_FLUSHED); 631 state = ST_FLUSHED; 632 return implFlush(out); 633 } 634 635 649 protected CoderResult implFlush(CharBuffer out) { 650 return CoderResult.UNDERFLOW; 651 } 652 653 663 public final CharsetDecoder reset() { 664 implReset(); 665 state = ST_RESET; 666 return this; 667 } 668 669 675 protected void implReset() { } 676 677 712 protected abstract CoderResult decodeLoop(ByteBuffer in, 713 CharBuffer out); 714 715 746 public final CharBuffer decode(ByteBuffer in) 747 throws CharacterCodingException 748 { 749 int n = (int)(in.remaining() * averageCharsPerByte()); 750 CharBuffer out = CharBuffer.allocate(n); 751 752 if (n == 0) 753 return out; 754 reset(); 755 for (;;) { 756 CoderResult cr; 757 if (in.hasRemaining()) 758 cr = decode(in, out, true); 759 else 760 cr = flush(out); 761 if (cr.isUnderflow()) 762 break; 763 if (cr.isOverflow()) { 764 n *= 2; 765 CharBuffer o = CharBuffer.allocate(n); 766 out.flip(); 767 o.put(out); 768 out = o; 769 continue; 770 } 771 cr.throwException(); 772 } 773 out.flip(); 774 return out; 775 } 776 777 778 779 789 public boolean isAutoDetecting() { 790 return false; 791 } 792 793 819 public boolean isCharsetDetected() { 820 throw new UnsupportedOperationException (); 821 } 822 823 847 public Charset detectedCharset() { 848 throw new UnsupportedOperationException (); 849 } 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 private void throwIllegalStateException(int from, int to) { 941 throw new IllegalStateException ("Current state = " + stateNames[from] 942 + ", new state = " + stateNames[to]); 943 } 944 945 } 946 | Popular Tags |