4 * License : The MIT License
5 * Copyright(c) 2011 MikuToga Partners
8 package jp.sfjp.mikutoga.bin.parser;
10 import java.nio.ByteBuffer;
11 import java.nio.CharBuffer;
12 import java.nio.charset.CharacterCodingException;
13 import java.nio.charset.Charset;
14 import java.nio.charset.CharsetDecoder;
15 import java.nio.charset.CoderResult;
16 import java.nio.charset.CodingErrorAction;
21 * <p>あらかじめバイト長が既知であるバイトバッファを読み取り、
24 * <p>デコード対象のバイト列が全てメモリ上に展開される必要があるので、
27 * <p>入力バイト値0x00以降をデコード処理の対象から外す
29 * デフォルトではゼロチョップモードはオフ。
30 * ゼロチョップモードはUTF16などのデコーディング時に使ってはならない。
32 public class TextDecoder {
34 private final CharsetDecoder decoder;
36 private CharBuffer charBuffer;
38 private boolean chopZero = false;
45 public TextDecoder(Charset cs){
46 this(cs.newDecoder());
54 public TextDecoder(CharsetDecoder decoder){
57 this.decoder = decoder;
59 this.decoder.onMalformedInput( CodingErrorAction.REPORT);
60 this.decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
66 * 指定されたバイト長のデコードに必要な出力バッファを用意する。
68 * <p>既存バッファで足りなければ新たに確保し直す。
70 * @param byteLength 入力バイト長
71 * @return 出力バッファ長。(キャラクタ単位)
73 protected int prepareCharBuffer(int byteLength){
74 float maxCharsPerByte = this.decoder.maxCharsPerByte();
75 int maxChars = (int)( byteLength * maxCharsPerByte ) + 1;
77 if(this.charBuffer != null){
78 int capacity = this.charBuffer.capacity();
79 if(capacity >= maxChars){
84 this.charBuffer = CharBuffer.allocate(maxChars);
92 * 入力バイト値0x00以降はデコード対象外となる。
93 * @param chop trueならゼロチョップモードオン
95 public void setZeroChopMode(boolean chop){
102 * @return ゼロチョップモードならtrue
104 public boolean isZeroChopMode(){
105 return this.chopZero;
109 * 入力バイトバッファのバイト値'0'出現以降をチョップする。
110 * ゼロチョップモードでなければ何もしない。
111 * @param bBuf 入力バイトバッファ
113 protected void chopZeroTermed(ByteBuffer bBuf){
114 if( ! this.chopZero ) return;
116 int start = bBuf.position();
117 int limit = bBuf.limit();
118 for(int idx = start; idx < limit; idx++){
119 byte bVal = bBuf.get(idx);
130 * バイトバッファの文字列デコードを行う。
131 * @param bBuf バイトバッファ
133 * @throws CharacterCodingException デコード異常
135 public String decode(ByteBuffer bBuf) throws CharacterCodingException{
136 chopZeroTermed(bBuf);
138 int blen = bBuf.remaining();
139 prepareCharBuffer(blen);
140 this.charBuffer.clear();
142 this.decoder.reset();
143 CoderResult decResult;
144 decResult = this.decoder.decode(bBuf, this.charBuffer, true);
146 if(decResult.isError()){
147 decResult.throwException();
151 assert ! decResult.isOverflow();
153 String result = this.charBuffer.flip().toString();