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;
20 * <p>あらかじめバイト長が既知であるバイトバッファを読み取り、
22 * <p>デコード対象のバイト列が全てメモリ上に展開される必要があるので、
24 * <p>入力バイト値0x00以降をデコード処理の対象から外す
26 * デフォルトではゼロチョップモードはオフ。
27 * ゼロチョップモードはUTF16などのデコーディング時に使ってはならない。
29 public class TextDecoder {
31 private final CharsetDecoder decoder;
33 private CharBuffer charBuffer;
35 private boolean chopZero = false;
42 public TextDecoder(Charset cs){
43 this(cs.newDecoder());
51 public TextDecoder(CharsetDecoder decoder){
54 this.decoder = decoder;
56 this.decoder.onMalformedInput (CodingErrorAction.REPORT);
57 this.decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
63 * 指定されたバイト長のデコードに必要な出力バッファを用意する。
64 * <p>既存バッファで足りなければ新たに確保し直す。
65 * @param byteLength 入力バイト長
66 * @return 出力バッファ長。(キャラクタ単位)
68 protected int prepareCharBuffer(int byteLength){
69 float maxCharsPerByte = this.decoder.maxCharsPerByte();
70 int maxChars = (int)( byteLength * maxCharsPerByte ) + 1;
72 if(this.charBuffer != null){
73 int capacity = this.charBuffer.capacity();
74 if(capacity >= maxChars){
79 this.charBuffer = CharBuffer.allocate(maxChars);
87 * 入力バイト値0x00以降はデコード対象外となる。
88 * @param chop trueならゼロチョップモードオン
90 public void setZeroChopMode(boolean chop){
97 * @return ゼロチョップモードならtrue
99 public boolean isZeroChopMode(){
100 return this.chopZero;
104 * 入力バイトバッファのバイト値'0'出現以降をチョップする。
105 * ゼロチョップモードでなければ何もしない。
106 * @param bBuf 入力バイトバッファ
108 protected void chopZeroTermed(ByteBuffer bBuf){
109 if( ! this.chopZero ) return;
111 int start = bBuf.position();
112 int limit = bBuf.limit();
113 for(int idx = start; idx < limit; idx++){
114 byte bVal = bBuf.get(idx);
125 * バイトバッファの文字列デコードを行う。
126 * @param bBuf バイトバッファ
128 * @throws CharacterCodingException デコード異常
130 public String decode(ByteBuffer bBuf) throws CharacterCodingException{
131 chopZeroTermed(bBuf);
133 int blen = bBuf.remaining();
134 prepareCharBuffer(blen);
135 this.charBuffer.clear();
137 this.decoder.reset();
138 CoderResult decResult;
139 decResult = this.decoder.decode(bBuf, this.charBuffer, true);
141 if(decResult.isError()){
142 decResult.throwException();
146 assert ! decResult.isOverflow();
148 String result = this.charBuffer.flip().toString();