4 * License : The MIT License
5 * Copyright(c) 2010 MikuToga Partners
8 package jp.sourceforge.mikutoga.parser;
10 import java.io.IOException;
11 import java.nio.CharBuffer;
12 import java.nio.charset.Charset;
17 public class CommonParser {
20 * PMDで用いられる文字エンコーディング(windows-31j)。
21 * ほぼShift_JISのスーパーセットと思ってよい。
22 * デコード結果はUCS-2集合に収まるはず。
24 public static final Charset CS_WIN31J = Charset.forName("windows-31j");
26 /** PMXで用いられる文字エンコーディング(UTF-8)。 */
27 public static final Charset CS_UTF8 = Charset.forName("UTF-8");
29 /** PMXで用いられる文字エンコーディング(UTF-16のリトルエンディアン)。 */
30 public static final Charset CS_UTF16LE = Charset.forName("UTF-16LE");
32 private final MmdSource source;
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);
42 public CommonParser(MmdSource source){
47 this.decoderWin31j .setZeroChopMode(true);
48 this.decoderUTF8 .setZeroChopMode(false);
49 this.decoderUTF16LE.setZeroChopMode(false);
58 protected MmdSource getSource(){
64 * @return 入力ソースの読み込み位置。単位はbyte。
66 protected long getPosition(){
67 long result = this.source.getPosition();
72 * 入力ソースにまだデータが残っているか判定する。
73 * @return まだ読み込んでいないデータが残っていればtrue
74 * @throws IOException IOエラー
75 * @see MmdSource#hasMore()
77 protected boolean hasMore() throws IOException{
78 boolean result = this.source.hasMore();
84 * @param skipLength 読み飛ばすバイト数。
85 * @throws IOException IOエラー
86 * @throws MmdEofException 読み飛ばす途中でストリーム終端に達した。
87 * @see MmdSource#skip(long)
89 protected void skip(long skipLength)
90 throws IOException, MmdEofException {
91 long result = this.source.skip(skipLength);
92 if(result != skipLength){
93 throw new MmdEofException(this.source.getPosition());
101 * @param skipLength 読み飛ばすバイト数。
102 * @throws IOException IOエラー
103 * @throws MmdEofException 読み飛ばす途中でストリーム終端に達した。
104 * @see MmdSource#skip(long)
106 protected void skip(int skipLength)
107 throws IOException, MmdEofException {
108 skip((long) skipLength);
114 * @throws IOException IOエラー
115 * @throws MmdEofException 読み込む途中でストリーム終端に達した。
116 * @see MmdSource#parseByte()
118 protected byte parseByte()
119 throws IOException, MmdEofException{
120 return this.source.parseByte();
124 * 符号無し値としてbyte値を読み込み、int型に変換して返す。
125 * 符号は拡張されない。(0xffは0x000000ffとなる)
126 * @return 読み込まれた値のint値
127 * @throws IOException IOエラー
128 * @throws MmdEofException 読み込む途中でストリーム終端に達した。
129 * @see MmdSource#parseUByteAsInteger()
131 protected int parseUByteAsInteger()
132 throws IOException, MmdEofException{
133 return this.source.parseUByteAsInteger();
137 * byte値を読み込み、boolean型に変換して返す。
138 * 0x00は偽、それ以外は真と解釈される。
139 * @return 読み込まれた値のboolean値
140 * @throws IOException IOエラー
141 * @throws MmdEofException 読み込む途中でストリーム終端に達した。
142 * @see MmdSource#parseBoolean()
144 protected boolean parseBoolean()
145 throws IOException, MmdEofException{
146 return this.source.parseBoolean();
151 * short値はリトルエンディアンで格納されていると仮定される。
152 * @return 読み込んだshort値
153 * @throws IOException IOエラー
154 * @throws MmdEofException 読み込む途中でストリーム終端に達した。
155 * @see MmdSource#parseShort()
157 protected short parseShort()
158 throws IOException, MmdEofException{
159 return this.source.parseShort();
163 * 符号無し値としてshort値を読み込み、int型に変換して返す。
164 * 符号は拡張されない。(0xffffは0x0000ffffとなる)
165 * short値はリトルエンディアンで格納されていると仮定される。
166 * @return 読み込まれた値のint値
167 * @throws IOException IOエラー
168 * @throws MmdEofException 読み込む途中でストリーム終端に達した。
169 * @see MmdSource#parseUShortAsInteger()
171 protected int parseUShortAsInteger()
172 throws IOException, MmdEofException{
173 return this.source.parseUShortAsInteger();
178 * int値はリトルエンディアンで格納されていると仮定される。
180 * @throws IOException IOエラー
181 * @throws MmdEofException 読み込む途中でストリーム終端に達した。
182 * @see MmdSource#parseInteger()
184 protected int parseInteger()
185 throws IOException, MmdEofException{
186 return this.source.parseInteger();
191 * float値はリトルエンディアンで格納されていると仮定される。
192 * @return 読み込んだfloat値
193 * @throws IOException IOエラー
194 * @throws MmdEofException 読み込む途中でストリーム終端に達した。
195 * @see MmdSource#parseFloat()
197 protected float parseFloat()
198 throws IOException, MmdEofException{
199 return this.source.parseFloat();
205 * @param offset 読み込み開始オフセット
206 * @param length 読み込みバイト数
207 * @throws IOException IOエラー
208 * @throws NullPointerException 配列がnull
209 * @throws IndexOutOfBoundsException 引数が配列属性と矛盾
210 * @throws MmdEofException 読み込む途中でストリーム終端に達した。
211 * @see MmdSource#parseByteArray(byte[], int, int)
213 protected void parseByteArray(byte[] dst, int offset, int length)
215 NullPointerException,
216 IndexOutOfBoundsException,
218 this.source.parseByteArray(dst, offset, length);
226 * @throws IOException IOエラー
227 * @throws NullPointerException 配列がnull
228 * @throws MmdEofException 読み込む途中でストリーム終端に達した。
229 * @see MmdSource#parseByteArray(byte[])
231 protected void parseByteArray(byte[] dst)
232 throws IOException, NullPointerException, MmdEofException{
233 this.source.parseByteArray(dst);
240 * @param offset 読み込み開始オフセット
241 * @param length 読み込みfloat要素数
242 * @throws IOException IOエラー
243 * @throws NullPointerException 配列がnull
244 * @throws IndexOutOfBoundsException 引数が配列属性と矛盾
245 * @throws MmdEofException 読み込む途中でストリーム終端に達した。
246 * @see MmdSource#parseFloatArray(float[], int, int)
248 protected void parseFloatArray(float[] dst, int offset, int length)
250 NullPointerException,
251 IndexOutOfBoundsException,
253 this.source.parseFloatArray(dst, offset, length);
261 * @throws IOException IOエラー
262 * @throws NullPointerException 配列がnull
263 * @throws MmdEofException 読み込む途中でストリーム終端に達した。
264 * @see MmdSource#parseFloatArray(float[])
266 protected void parseFloatArray(float[] dst)
267 throws IOException, NullPointerException, MmdEofException{
268 this.source.parseFloatArray(dst);
273 * 指定された最大バイト長に収まるゼロ終端(0x00)文字列を読み込む。
274 * 入力バイト列はwindows-31jエンコーディングとして解釈される。
276 * IO入力は指定バイト数だけ読み進められる。
277 * ゼロ終端が見つからないまま指定バイト数が読み込み終わった場合、
278 * そこまでのデータから文字列を構成する。
279 * @param maxlen 読み込みバイト数
281 * @throws IOException IOエラー
282 * @throws MmdEofException 読み込む途中でストリーム終端に達した。
283 * @throws MmdFormatException 不正な文字エンコーディングが検出された。
285 protected String parseZeroTermWin31J(int maxlen)
290 this.decoderWin31j.parseString(this.source, maxlen);
292 String result = encoded.toString();
298 * 4byte整数によるバイト列長とそれに続くUTF8バイト列を
300 * @return デコードされた文字列。
301 * @throws IOException IOエラー
302 * @throws MmdEofException 予期せぬ入力終端
303 * @throws MmdFormatException 不正な文字エンコーディングが検出された。
305 protected String parseHollerithUtf8()
309 int byteLen = this.source.parseInteger();
312 this.decoderUTF8.parseString(this.source, byteLen);
314 String result = encoded.toString();
320 * 4byte整数によるバイト列長とそれに続くUTF16-LEバイト列を
322 * @return デコードされた文字列。
323 * @throws IOException IOエラー
324 * @throws MmdEofException 予期せぬ入力終端
325 * @throws MmdFormatException 不正な文字エンコーディングが検出された。
327 protected String parseHollerithUtf16LE()
331 int byteLen = this.source.parseInteger();
334 this.decoderUTF16LE.parseString(this.source, byteLen);
336 String result = encoded.toString();