OSDN Git Service

d64b52e67d656820ad71b8689369e335d985997c
[mikutoga/TogaGem.git] / src / main / java / jp / sourceforge / mikutoga / parser / CommonParser.java
1 /*
2  * common MMD parser
3  *
4  * License : The MIT License
5  * Copyright(c) 2010 MikuToga Partners
6  */
7
8 package jp.sourceforge.mikutoga.parser;
9
10 import java.io.IOException;
11 import java.nio.CharBuffer;
12 import java.nio.charset.Charset;
13
14 /**
15  * 各種パーサの共通実装。
16  */
17 public class CommonParser {
18
19     /**
20      * PMDで用いられる文字エンコーディング(windows-31j)。
21      * ほぼShift_JISのスーパーセットと思ってよい。
22      * デコード結果はUCS-2集合に収まるはず。
23      */
24     public static final Charset CS_WIN31J = Charset.forName("windows-31j");
25
26     /** PMXで用いられる文字エンコーディング(UTF-8)。 */
27     public static final Charset CS_UTF8 = Charset.forName("UTF-8");
28
29     /** PMXで用いられる文字エンコーディング(UTF-16のリトルエンディアン)。 */
30     public static final Charset CS_UTF16LE = Charset.forName("UTF-16LE");
31
32     private final MmdSource source;
33
34     private final TextDecoder decoderWin31j  = new TextDecoder(CS_WIN31J);
35     private final TextDecoder decoderUTF8    = new TextDecoder(CS_UTF8);
36     private final TextDecoder decoderUTF16LE = new TextDecoder(CS_UTF16LE);
37
38     /**
39      * コンストラクタ。
40      * @param source 入力ソース
41      */
42     public CommonParser(MmdSource source){
43         super();
44
45         this.source = source;
46
47         this.decoderWin31j .setZeroChopMode(true);
48         this.decoderUTF8   .setZeroChopMode(false);
49         this.decoderUTF16LE.setZeroChopMode(false);
50
51         return;
52     }
53
54     /**
55      * 入力ソースにまだデータが残っているか判定する。
56      * @return まだ読み込んでいないデータが残っていればtrue
57      * @throws IOException IOエラー
58      * @see MmdSource#hasMore()
59      */
60     protected boolean hasMore() throws IOException{
61         boolean result = this.source.hasMore();
62         return result;
63     }
64
65     /**
66      * 入力ソースを読み飛ばす。
67      * @param skipLength 読み飛ばすバイト数。
68      * @throws IOException IOエラー
69      * @throws MmdEofException 読み飛ばす途中でストリーム終端に達した。
70      * @see MmdSource#skip(long)
71      */
72     protected void skip(long skipLength)
73             throws IOException, MmdEofException {
74         long result = this.source.skip(skipLength);
75         if(result != skipLength){
76             throw new MmdEofException(this.source.getPosition());
77         }
78
79         return;
80     }
81
82     /**
83      * 入力ソースを読み飛ばす。
84      * @param skipLength 読み飛ばすバイト数。
85      * @throws IOException IOエラー
86      * @throws MmdEofException 読み飛ばす途中でストリーム終端に達した。
87      * @see MmdSource#skip(long)
88      */
89     protected void skip(int skipLength)
90             throws IOException, MmdEofException {
91         skip((long) skipLength);
92     }
93
94     /**
95      * byte値を読み込む。
96      * @return 読み込んだbyte値
97      * @throws IOException IOエラー
98      * @throws MmdEofException 読み込む途中でストリーム終端に達した。
99      * @see MmdSource#parseByte()
100      */
101     protected byte parseByte()
102             throws IOException, MmdEofException{
103         return this.source.parseByte();
104     }
105
106     /**
107      * 符号無し値としてbyte値を読み込み、int型に変換して返す。
108      * 符号は拡張されない。(0xffは0x000000ffとなる)
109      * @return 読み込まれた値のint値
110      * @throws IOException IOエラー
111      * @throws MmdEofException 読み込む途中でストリーム終端に達した。
112      * @see MmdSource#parseUByteAsInteger()
113      */
114     protected int parseUByteAsInteger()
115             throws IOException, MmdEofException{
116         return this.source.parseUByteAsInteger();
117     }
118
119     /**
120      * byte値を読み込み、boolean型に変換して返す。
121      * 0x00は偽、それ以外は真と解釈される。
122      * @return 読み込まれた値のboolean値
123      * @throws IOException IOエラー
124      * @throws MmdEofException 読み込む途中でストリーム終端に達した。
125      * @see MmdSource#parseBoolean()
126      */
127     protected boolean parseBoolean()
128             throws IOException, MmdEofException{
129         return this.source.parseBoolean();
130     }
131
132     /**
133      * short値を読み込む。
134      * short値はリトルエンディアンで格納されていると仮定される。
135      * @return 読み込んだshort値
136      * @throws IOException IOエラー
137      * @throws MmdEofException 読み込む途中でストリーム終端に達した。
138      * @see MmdSource#parseShort()
139      */
140     protected short parseShort()
141             throws IOException, MmdEofException{
142         return this.source.parseShort();
143     }
144
145     /**
146      * 符号無し値としてshort値を読み込み、int型に変換して返す。
147      * 符号は拡張されない。(0xffffは0x0000ffffとなる)
148      * short値はリトルエンディアンで格納されていると仮定される。
149      * @return 読み込まれた値のint値
150      * @throws IOException IOエラー
151      * @throws MmdEofException 読み込む途中でストリーム終端に達した。
152      * @see MmdSource#parseUShortAsInteger()
153      */
154     protected int parseUShortAsInteger()
155             throws IOException, MmdEofException{
156         return this.source.parseUShortAsInteger();
157     }
158
159     /**
160      * int値を読み込む。
161      * int値はリトルエンディアンで格納されていると仮定される。
162      * @return 読み込んだint値
163      * @throws IOException IOエラー
164      * @throws MmdEofException 読み込む途中でストリーム終端に達した。
165      * @see MmdSource#parseInteger()
166      */
167     protected int parseInteger()
168             throws IOException, MmdEofException{
169         return this.source.parseInteger();
170     }
171
172     /**
173      * float値を読み込む。
174      * float値はリトルエンディアンで格納されていると仮定される。
175      * @return 読み込んだfloat値
176      * @throws IOException IOエラー
177      * @throws MmdEofException 読み込む途中でストリーム終端に達した。
178      * @see MmdSource#parseFloat()
179      */
180     protected float parseFloat()
181             throws IOException, MmdEofException{
182         return this.source.parseFloat();
183     }
184
185     /**
186      * byte配列を読み込む。
187      * @param dst 格納先配列
188      * @param offset 読み込み開始オフセット
189      * @param length 読み込みバイト数
190      * @throws IOException IOエラー
191      * @throws NullPointerException 配列がnull
192      * @throws IndexOutOfBoundsException 引数が配列属性と矛盾
193      * @throws MmdEofException 読み込む途中でストリーム終端に達した。
194      * @see MmdSource#parseByteArray(byte[], int, int)
195      */
196     protected void parseByteArray(byte[] dst, int offset, int length)
197             throws IOException,
198                    NullPointerException,
199                    IndexOutOfBoundsException,
200                    MmdEofException {
201         this.source.parseByteArray(dst, offset, length);
202         return;
203     }
204
205     /**
206      * byte配列を読み込む。
207      * 配列要素全ての読み込みが試みられる。
208      * @param dst 格納先配列
209      * @throws IOException IOエラー
210      * @throws NullPointerException 配列がnull
211      * @throws MmdEofException 読み込む途中でストリーム終端に達した。
212      * @see MmdSource#parseByteArray(byte[])
213      */
214     protected void parseByteArray(byte[] dst)
215             throws IOException, NullPointerException, MmdEofException{
216         this.source.parseByteArray(dst);
217         return;
218     }
219
220     /**
221      * float配列を読み込む。
222      * @param dst 格納先配列
223      * @param offset 読み込み開始オフセット
224      * @param length 読み込みfloat要素数
225      * @throws IOException IOエラー
226      * @throws NullPointerException 配列がnull
227      * @throws IndexOutOfBoundsException 引数が配列属性と矛盾
228      * @throws MmdEofException 読み込む途中でストリーム終端に達した。
229      * @see MmdSource#parseFloatArray(float[], int, int)
230      */
231     protected void parseFloatArray(float[] dst, int offset, int length)
232             throws IOException,
233                    NullPointerException,
234                    IndexOutOfBoundsException,
235                    MmdEofException {
236         this.source.parseFloatArray(dst, offset, length);
237         return;
238     }
239
240     /**
241      * float配列を読み込む。
242      * 配列要素全ての読み込みが試みられる。
243      * @param dst 格納先配列
244      * @throws IOException IOエラー
245      * @throws NullPointerException 配列がnull
246      * @throws MmdEofException 読み込む途中でストリーム終端に達した。
247      * @see MmdSource#parseFloatArray(float[])
248      */
249     protected void parseFloatArray(float[] dst)
250             throws IOException, NullPointerException, MmdEofException{
251         this.source.parseFloatArray(dst);
252         return;
253     }
254
255     /**
256      * 指定された最大バイト長に収まるゼロ終端(0x00)文字列を読み込む。
257      * 入力バイト列はwindows-31jエンコーディングとして解釈される。
258      * ゼロ終端以降のデータは無視されるが、
259      * IO入力は指定バイト数だけ読み進められる。
260      * ゼロ終端が見つからないまま指定バイト数が読み込み終わった場合、
261      * そこまでのデータから文字列を構成する。
262      *
263      * @param maxlen 読み込みバイト数
264      * @return デコードされた文字列
265      * @throws IOException IOエラー
266      * @throws MmdEofException 読み込む途中でストリーム終端に達した。
267      * @throws MmdFormatException 不正な文字エンコーディングが検出された。
268      */
269     protected String parseZeroTermWin31J(int maxlen)
270             throws IOException,
271                    MmdEofException,
272                    MmdFormatException {
273         CharBuffer encoded =
274                 this.decoderWin31j.parseString(this.source, maxlen);
275
276         String result = encoded.toString();
277
278         return result;
279     }
280
281 }