4 * License : The MIT License
5 * Copyright(c) 2010 MikuToga Partners
8 package jp.sourceforge.mikutoga.pmd.pmdexporter;
10 import java.io.IOException;
11 import java.io.OutputStream;
12 import java.nio.BufferOverflowException;
13 import java.nio.ByteBuffer;
14 import java.nio.ByteOrder;
15 import java.nio.CharBuffer;
16 import java.nio.charset.Charset;
17 import java.nio.charset.CharsetEncoder;
18 import java.nio.charset.CoderResult;
19 import java.nio.charset.CodingErrorAction;
24 public abstract class AbstractExporter {
26 private static final Charset CS_WIN31J = Charset.forName("windows-31j");
28 private static final String ERRMSG_TOOLONGTEXT = "too long text";
29 private static final String ERRMSG_INVUCSSEQ = "invalid unicode sequence";
30 private static final String ERRMSG_NONWIN31J = "no character in win31j";
32 private static final int BYTES_SHORT = Short .SIZE / Byte.SIZE;
33 private static final int BYTES_INT = Integer.SIZE / Byte.SIZE;
34 private static final int BYTES_FLOAT = Float .SIZE / Byte.SIZE;
36 private static final int BUFSZ_BYTE = 512;
37 private static final int BUFSZ_CHAR = 512;
39 private final OutputStream ostream;
41 private final byte[] barray;
42 private final ByteBuffer bbuf;
44 private final CharBuffer cbuf;
45 private final CharsetEncoder encoder;
50 * @param stream 出力ストリーム
51 * @throws NullPointerException 引数がnull
53 protected AbstractExporter(OutputStream stream)
54 throws NullPointerException{
57 if(stream == null) throw new NullPointerException();
58 this.ostream = stream;
60 this.barray = new byte[BUFSZ_BYTE];
61 this.bbuf = ByteBuffer.wrap(this.barray);
62 this.bbuf.order(ByteOrder.LITTLE_ENDIAN);
64 this.cbuf = CharBuffer.allocate(BUFSZ_CHAR);
65 this.encoder = CS_WIN31J.newEncoder();
66 this.encoder.onMalformedInput(CodingErrorAction.REPORT);
67 this.encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
75 * I/O効率とデバッグ効率のバランスを考え、ご利用は計画的に。
76 * @throws IOException 出力エラー
78 protected void flush() throws IOException{
86 * @throws IOException 出力エラー
88 protected void dumpByte(byte bVal) throws IOException{
89 this.ostream.write((int)bVal);
95 * byte値に収まらない上位ビットはそのまま捨てられる。
97 * @throws IOException 出力エラー
99 protected void dumpByte(int iVal) throws IOException{
100 dumpByte((byte)iVal);
107 * @throws IOException 出力エラー
109 protected void dumpShort(short sVal) throws IOException{
111 this.bbuf.putShort(sVal);
112 this.ostream.write(this.barray, 0, BYTES_SHORT);
118 * short値に収まらない上位ビットはそのまま捨てられる。
120 * @throws IOException 出力エラー
122 protected void dumpShort(int iVal) throws IOException{
123 dumpShort((short)iVal);
130 * @throws IOException 出力エラー
132 protected void dumpInt(int iVal) throws IOException{
134 this.bbuf.putInt(iVal);
135 this.ostream.write(this.barray, 0, BYTES_INT);
142 * @throws IOException 出力エラー
144 protected void dumpFloat(float fVal) throws IOException{
146 this.bbuf.putFloat(fVal);
147 this.ostream.write(this.barray, 0, BYTES_FLOAT);
152 * 文字列をwindows-31jエンコーディングで出力する。
154 * @return 出力されたbyte総数。
155 * @throws IOException 出力エラー
156 * @throws IllegalPmdTextException 文字エンコーディングに関するエラー
158 protected int dumpCharSequence(CharSequence seq)
159 throws IOException, IllegalPmdTextException{
160 encodeToByteBuffer(seq);
162 int length = dumpByteBuffer();
167 * windows-31jにエンコーディングした文字列を内部バッファに蓄積する。
169 * @throws IllegalPmdTextException 文字エンコーディングに関するエラー。
172 * <li>入力文字列がUnicodeとしてすでにおかしい。
173 * (サロゲートペアがペアになってないなど)
174 * <li>windows-31jにない文字をエンコーディングしようとした
175 * <li>エンコーディング結果が内部バッファに収まらなかった。
179 private void encodeToByteBuffer(CharSequence seq)
180 throws IllegalPmdTextException{
183 this.cbuf.append(seq);
184 }catch(BufferOverflowException e){
185 throw new IllegalPmdTextException(ERRMSG_TOOLONGTEXT);
191 CoderResult result = this.encoder.encode(this.cbuf, this.bbuf, true);
192 if( ! result.isUnderflow()){
193 if(result.isOverflow()){
194 throw new IllegalPmdTextException(ERRMSG_TOOLONGTEXT);
195 }else if(result.isMalformed()){
196 throw new IllegalPmdTextException(ERRMSG_INVUCSSEQ);
197 }else if(result.isUnmappable()){
198 throw new IllegalPmdTextException(ERRMSG_NONWIN31J);
201 throw new AssertionError();
209 * 内部バッファに蓄積されたbyte値並びを出力する。
211 * @throws IOException 出力エラー
213 private int dumpByteBuffer() throws IOException{
214 int offset = this.bbuf.position();
215 int limit = this.bbuf.limit();
216 int length = limit - offset;
217 this.ostream.write(this.barray, offset, length);
219 this.bbuf.position(limit);