package jp.sourceforge.mikutoga.vmd.parser;
import java.io.IOException;
-import jp.sourceforge.mikutoga.parser.CommonParser;
-import jp.sourceforge.mikutoga.parser.MmdFormatException;
-import jp.sourceforge.mikutoga.parser.MmdSource;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import jp.sfjp.mikutoga.bin.parser.CommonParser;
+import jp.sfjp.mikutoga.bin.parser.MmdEofException;
+import jp.sfjp.mikutoga.bin.parser.MmdFormatException;
+import jp.sfjp.mikutoga.bin.parser.TextDecoder;
import jp.sourceforge.mikutoga.vmd.VmdConst;
/**
*/
class VmdBasicParser extends CommonParser{
+ /**
+ * VMDで用いられる文字エンコーディング(windows-31j)。
+ * ほぼShift_JISのスーパーセットと思ってよい。
+ * デコード結果はUCS-2集合に収まるはず。
+ */
+ public static final Charset CS_WIN31J = Charset.forName("windows-31j");
+
private static final int BZ_SIZE = 4; // 4byte Bezier parameter
private static final int BZXYZR_SIZE = BZ_SIZE * 4; // XYZR Bezier
private static final int BZ_REDUNDANT = 4; // redundant spare
+"(Strict-mode)";
+ private final TextDecoder decoderWin31j = new TextDecoder(CS_WIN31J);
+
private final byte[] motionIntplt = new byte[BZTOTAL_SIZE];
private VmdBasicHandler handler = null;
* コンストラクタ。
* @param source 入力ソース
*/
- VmdBasicParser(MmdSource source){
+ VmdBasicParser(InputStream source){
super(source);
+ this.decoderWin31j.setZeroChopMode(true);
return;
}
}
/**
+ * 指定された最大バイト長に収まるゼロ終端(0x00)文字列を読み込む。
+ * 入力バイト列はwindows-31jエンコーディングとして解釈される。
+ * ゼロ終端以降のデータは無視されるが、
+ * IO入力は指定バイト数だけ読み進められる。
+ * ゼロ終端が見つからないまま指定バイト数が読み込み終わった場合、
+ * そこまでのデータから文字列を構成する。
+ * @param byteLen 読み込みバイト数
+ * @return デコードされた文字列
+ * @throws IOException IOエラー
+ * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+ * @throws MmdFormatException 不正な文字エンコーディングが検出された。
+ */
+ protected String parseVmdText(int byteLen)
+ throws IOException,
+ MmdEofException,
+ MmdFormatException {
+ String result = parseString(this.decoderWin31j, byteLen);
+ return result;
+ }
+
+ /**
* VMDファイル基本部のパースを開始する。
* @throws IOException IOエラー
* @throws MmdFormatException フォーマットエラー
* @throws MmdFormatException フォーマットエラー
*/
private void parseVmdModelName() throws IOException, MmdFormatException{
- String modelName = parseZeroTermWin31J(VmdConst.MODELNAME_MAX);
+ String modelName = parseVmdText(VmdConst.MODELNAME_MAX);
if(VmdConst.isStageActName(modelName)){
this.hasStageActName = true;
*/
private void parseVmdBoneMotion()
throws IOException, MmdFormatException{
- int boneMotionNo = parseInteger();
+ int boneMotionNo = parseLeInt();
if(this.handler == null){
skip(VmdConst.BONEMOTION_DATA_SZ * boneMotionNo);
VmdBasicHandler.BONEMOTION_LIST, boneMotionNo);
for(int ct = 0; ct < boneMotionNo; ct++){
- String boneName = parseZeroTermWin31J(VmdConst.BONENAME_MAX);
- int keyFrameNo = parseInteger();
+ String boneName = parseVmdText(VmdConst.BONENAME_MAX);
+ int keyFrameNo = parseLeInt();
this.handler.vmdBoneMotion(boneName, keyFrameNo);
- float xPos = parseFloat();
- float yPos = parseFloat();
- float zPos = parseFloat();
+ float xPos = parseLeFloat();
+ float yPos = parseLeFloat();
+ float zPos = parseLeFloat();
this.handler.vmdBonePosition(xPos, yPos, zPos);
- float qx = parseFloat();
- float qy = parseFloat();
- float qz = parseFloat();
- float qw = parseFloat();
+ float qx = parseLeFloat();
+ float qy = parseLeFloat();
+ float qz = parseLeFloat();
+ float qw = parseLeFloat();
this.handler.vmdBoneRotationQt(qx, qy, qz, qw);
parseVmdMotionInterpolation();
* @throws MmdFormatException フォーマットエラー
*/
private void parseVmdMorph() throws IOException, MmdFormatException{
- int morphMotionNo = parseInteger();
+ int morphMotionNo = parseLeInt();
if(this.handler == null){
skip(VmdConst.MORPH_DATA_SZ * morphMotionNo);
VmdBasicHandler.MORPH_LIST, morphMotionNo);
for(int ct = 0; ct < morphMotionNo; ct++){
- String morphName = parseZeroTermWin31J(VmdConst.MORPHNAME_MAX);
- int keyFrameNo = parseInteger();
- float flex = parseFloat();
+ String morphName = parseVmdText(VmdConst.MORPHNAME_MAX);
+ int keyFrameNo = parseLeInt();
+ float flex = parseLeFloat();
this.handler.vmdMorphMotion(morphName, keyFrameNo, flex);
this.handler.loopNext(VmdBasicHandler.MORPH_LIST);