2 * stream decoder for Shift_JIS
4 * License : The MIT License
5 * Copyright(c) 2009 olyutorskii
8 package jp.sourceforge.jindolf.parser;
10 import java.io.IOException;
11 import java.nio.ByteBuffer;
12 import java.nio.charset.CoderResult;
15 * Shift_JISバイト列のデコードエラーに特化した、
16 * {@link StreamDecoder}の派生クラス。
18 * <p>Java実行系の細かな仕様差異による
19 * デコードエラー出現パターンゆらぎの正規化を行う。
21 * <p>0x5Cが{@literal U+005C}にデコードされるか
22 * {@literal U+00A5}にデコードされるかはJava実行系の実装依存。
24 * @see <a href="http://www.iana.org/assignments/character-sets">
27 public class SjisDecoder extends StreamDecoder{
33 this(BYTEBUF_DEFSZ, CHARBUF_DEFSZ);
40 * @param inbufSz 入力バッファサイズ
41 * @param outbufSz 出力バッファサイズ
42 * @throws IllegalArgumentException バッファサイズが小さすぎる。
44 public SjisDecoder(int inbufSz, int outbufSz)
45 throws IllegalArgumentException{
46 super(ShiftJis.CHARSET.newDecoder(), inbufSz, outbufSz);
51 * 1バイトのエラーをUnmap系2バイトエラーに統合できないか試す。
53 * <p>必要に応じて1バイト以上の追加先読みを行う。
55 * <p>バイト列 {0x85,0x40}(未割り当て9区の文字) を、
56 * 1バイトのエラーと文字@に分離するJava実行系への対処。
58 * @param result デコード異常系
59 * @return 修正されたデコード異常系。修正がなければ引数と同じものを返す。
60 * @throws IOException 入力エラー
62 private CoderResult modify1ByteError(CoderResult result)
64 assert result.length() == 1;
66 ByteBuffer inbuffer = getByteBuffer();
68 if(inbuffer.remaining() < 2){
71 // 入力バイト列の最後がこの1バイトエラーだった場合。
72 if(inbuffer.remaining() < 2) return result;
74 int currPos = inbuffer.position();
75 int nextPos = currPos + 1;
78 byte curr = inbuffer.get(currPos);
79 byte next = inbuffer.get(nextPos);
81 CoderResult newResult;
82 if( ShiftJis.isShiftJIS(curr, next) ){
83 newResult = CoderResult.unmappableForLength(2);
92 * 2バイトのエラーを1バイトに分割できないか試す。
94 * <p>※ バイト列"FF:32" のShift_JISデコードに際して、
95 * 2バイト長のデコードエラーを返す1.6系実行系が存在する。
97 * @param result デコード異常系
98 * @return 修正されたデコード異常系。修正がなければ引数と同じものを返す。
100 private CoderResult modify2ByteError(CoderResult result){
101 assert result.length() == 2;
103 ByteBuffer inbuffer = getByteBuffer();
104 assert inbuffer.remaining() >= 2;
106 int currPos = inbuffer.position();
107 int nextPos = currPos + 1;
109 byte curr = inbuffer.get(currPos); // 絶対的get
110 byte next = inbuffer.get(nextPos);
112 CoderResult newResult;
113 if( ! ShiftJis.isShiftJIS(curr, next) ){
114 newResult = CoderResult.malformedForLength(1);
125 * <p>シフトJISデコードエラー出現パターンの
128 * @param result {@inheritDoc}
129 * @return {@inheritDoc}
130 * @throws IOException {@inheritDoc}
133 protected CoderResult modifyErrorLength(CoderResult result)
135 int errorLength = result.length();
137 CoderResult newResult;
138 switch (errorLength) {
140 newResult = modify1ByteError(result);
143 newResult = modify2ByteError(result);