OSDN Git Service

release-1.503.4 タグをチェンジセット c16348cc4c65 に追加しました
[jindolf/JinArchiver.git] / src / main / java / jp / sourceforge / jindolf / archiver / Win31j.java
1 /*
2  * windows-31j encoding utilities
3  *
4  * License : The MIT License
5  * Copyright(c) 2008 olyutorskii
6  */
7
8 package jp.sourceforge.jindolf.archiver;
9
10 import java.nio.ByteBuffer;
11 import java.nio.charset.CharacterCodingException;
12 import java.nio.charset.Charset;
13 import java.nio.charset.CharsetDecoder;
14 import java.nio.charset.CodingErrorAction;
15 import jp.sourceforge.jindolf.parser.DecodeErrorInfo;
16 import jp.sourceforge.jindolf.parser.DecodedContent;
17
18 /**
19  * windows-31jエンコーディング(機種依存文字)に関する諸々。
20  */
21 public final class Win31j{
22
23     /** デフォルト置換文字。 */
24     public static final char REP_CHAR = '\ufffd';
25
26     /** windows-31j Charset. */
27     public static final Charset CS_WIN31J = Charset.forName("windows-31j");
28
29     private static final CharsetDecoder WIN31JDECODER;
30     private static final ByteBuffer BYTEBUFFER = ByteBuffer.allocate(2);
31
32     static{
33         WIN31JDECODER = CS_WIN31J.newDecoder();
34         WIN31JDECODER.onMalformedInput(CodingErrorAction.REPORT);
35         WIN31JDECODER.onUnmappableCharacter(CodingErrorAction.REPORT);
36         WIN31JDECODER.reset();
37         BYTEBUFFER.clear();
38     }
39
40
41     /**
42      * 隠しコンストラクタ。
43      */
44     private Win31j(){
45         assert false;
46         throw new AssertionError();
47     }
48
49
50     /**
51      * winsows-31jエンコーディングされたと想定した2バイトデータ
52      * の復号を試みる。
53      * 復号に失敗すればU+FFFDを返す。
54      * @param b1 1バイト目
55      * @param b2 2バイト目
56      * @return 復号化された1文字
57      */
58     public static synchronized char getWin31jChar(byte b1, byte b2){
59         char replaced;
60
61         WIN31JDECODER.reset();
62         BYTEBUFFER.clear();
63         BYTEBUFFER.put(b1).put(b2);
64         BYTEBUFFER.flip();
65
66         try{
67             replaced = WIN31JDECODER.decode(BYTEBUFFER).charAt(0);
68         }catch(CharacterCodingException e){
69             replaced = REP_CHAR;
70         }
71
72         return replaced;
73     }
74
75     /**
76      * デコードエラーがwindows-31jに由来する物と仮定して
77      * 復号を試みる。
78      * 1バイトエラーもしくは復号に失敗すればU+FFFDを返す。
79      * @param info デコードエラー
80      * @return 復号化された1文字
81      */
82     public static char getWin31jChar(DecodeErrorInfo info){
83         if( ! info.has2nd() ) return REP_CHAR;
84
85         byte b1 = info.getRawByte1st();
86         byte b2 = info.getRawByte2nd();
87         char replaceChar = getWin31jChar(b1, b2);
88
89         return replaceChar;
90     }
91
92     /**
93      * デコードエラーを含む文字列に対し、
94      * windows-31jによる復号での補完を試みる。
95      * @param content 文字列
96      */
97     public static void supplyWin31jChar(DecodedContent content){
98         if( ! content.hasDecodeError() ) return;
99
100         for(DecodeErrorInfo info : content.getDecodeErrorList()){
101             int pos = info.getCharPosition();
102             char replaceChar = getWin31jChar(info);
103             content.setCharAt(pos, replaceChar);
104         }
105
106         return;
107     }
108
109 }