|
|||||||||||||||||||
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover | |||||||||||||||||||
Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
BinaryDumpOutputStream.java | 0% | 0% | 0% | 0% |
|
1 |
// Copyright 2004, 2005 The Apache Software Foundation
|
|
2 |
//
|
|
3 |
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4 |
// you may not use this file except in compliance with the License.
|
|
5 |
// You may obtain a copy of the License at
|
|
6 |
//
|
|
7 |
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8 |
//
|
|
9 |
// Unless required by applicable law or agreed to in writing, software
|
|
10 |
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11 |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12 |
// See the License for the specific language governing permissions and
|
|
13 |
// limitations under the License.
|
|
14 |
|
|
15 |
package org.apache.tapestry.util.io;
|
|
16 |
|
|
17 |
import java.io.IOException;
|
|
18 |
import java.io.OutputStream;
|
|
19 |
import java.io.PrintWriter;
|
|
20 |
import java.io.Writer;
|
|
21 |
|
|
22 |
/**
|
|
23 |
* A kind of super-formatter. It is sent a stream of binary data and
|
|
24 |
* formats it in a human-readable dump format which is forwarded to
|
|
25 |
* its output stream.
|
|
26 |
*
|
|
27 |
* <p>Currently, output is in hex though options to change that may
|
|
28 |
* be introduced.
|
|
29 |
*
|
|
30 |
* @author Howard Lewis Ship
|
|
31 |
*
|
|
32 |
**/
|
|
33 |
|
|
34 |
public class BinaryDumpOutputStream extends OutputStream |
|
35 |
{ |
|
36 |
private PrintWriter out;
|
|
37 |
|
|
38 |
private boolean locked = false; |
|
39 |
|
|
40 |
private boolean showOffset = true; |
|
41 |
private int bytesPerLine = 16; |
|
42 |
private int spacingInterval = 4; |
|
43 |
private char substituteChar = '.'; |
|
44 |
private String offsetSeperator = ": "; |
|
45 |
private int offset = 0; |
|
46 |
private int lineCount = 0; |
|
47 |
private int bytesSinceSpace = 0; |
|
48 |
private char[] ascii = null; |
|
49 |
private boolean showAscii = true; |
|
50 |
private String asciiBegin = " |"; |
|
51 |
private String asciiEnd = "|"; |
|
52 |
|
|
53 |
private static final char[] HEX = |
|
54 |
{ |
|
55 |
'0', |
|
56 |
'1', |
|
57 |
'2', |
|
58 |
'3', |
|
59 |
'4', |
|
60 |
'5', |
|
61 |
'6', |
|
62 |
'7', |
|
63 |
'8', |
|
64 |
'9', |
|
65 |
'a', |
|
66 |
'b', |
|
67 |
'c', |
|
68 |
'd', |
|
69 |
'e', |
|
70 |
'f' }; |
|
71 |
|
|
72 |
/**
|
|
73 |
* Creates a <code>PrintWriter</code> for <code>System.out</code>.
|
|
74 |
*
|
|
75 |
**/
|
|
76 |
|
|
77 | 0 |
public BinaryDumpOutputStream()
|
78 |
{ |
|
79 | 0 |
this(new PrintWriter(System.out, true)); |
80 |
} |
|
81 |
|
|
82 | 0 |
public BinaryDumpOutputStream(PrintWriter out)
|
83 |
{ |
|
84 | 0 |
this.out = out;
|
85 |
} |
|
86 |
|
|
87 | 0 |
public BinaryDumpOutputStream(Writer out)
|
88 |
{ |
|
89 | 0 |
this.out = new PrintWriter(out); |
90 |
} |
|
91 |
|
|
92 | 0 |
public void close() throws IOException |
93 |
{ |
|
94 | 0 |
if (out != null) |
95 |
{ |
|
96 | 0 |
if (lineCount > 0)
|
97 | 0 |
finishFinalLine(); |
98 |
|
|
99 | 0 |
out.close(); |
100 |
} |
|
101 |
|
|
102 | 0 |
out = null;
|
103 |
} |
|
104 |
|
|
105 | 0 |
private void finishFinalLine() |
106 |
{ |
|
107 |
// Since we only finish the final line after at least one byte has
|
|
108 |
// been written to it, we don't need to worry about
|
|
109 |
// the offset.
|
|
110 |
|
|
111 | 0 |
while (lineCount < bytesPerLine)
|
112 |
{ |
|
113 |
// After every <n> bytes, emit a space.
|
|
114 |
|
|
115 | 0 |
if (spacingInterval > 0 && bytesSinceSpace == spacingInterval)
|
116 |
{ |
|
117 | 0 |
out.print(' '); |
118 | 0 |
bytesSinceSpace = 0; |
119 |
} |
|
120 |
|
|
121 |
// Two spaces to substitute for the two hex digits.
|
|
122 |
|
|
123 | 0 |
out.print(" ");
|
124 |
|
|
125 | 0 |
if (showAscii)
|
126 | 0 |
ascii[lineCount] = ' '; |
127 |
|
|
128 | 0 |
lineCount++; |
129 | 0 |
bytesSinceSpace++; |
130 |
} |
|
131 |
|
|
132 | 0 |
if (showAscii)
|
133 |
{ |
|
134 | 0 |
out.print(asciiBegin); |
135 | 0 |
out.print(ascii); |
136 | 0 |
out.print(asciiEnd); |
137 |
} |
|
138 |
|
|
139 | 0 |
out.println(); |
140 |
} |
|
141 |
|
|
142 |
/**
|
|
143 |
* Forwards the <code>flush()</code> to the <code>PrintWriter</code>.
|
|
144 |
*
|
|
145 |
**/
|
|
146 |
|
|
147 | 0 |
public void flush() throws IOException |
148 |
{ |
|
149 | 0 |
out.flush(); |
150 |
} |
|
151 |
|
|
152 | 0 |
public String getAsciiBegin()
|
153 |
{ |
|
154 | 0 |
return asciiBegin;
|
155 |
} |
|
156 |
|
|
157 | 0 |
public String getAsciiEnd()
|
158 |
{ |
|
159 | 0 |
return asciiEnd;
|
160 |
} |
|
161 |
|
|
162 | 0 |
public int getBytesPerLine() |
163 |
{ |
|
164 | 0 |
return bytesPerLine;
|
165 |
} |
|
166 |
|
|
167 | 0 |
public String getOffsetSeperator()
|
168 |
{ |
|
169 | 0 |
return offsetSeperator;
|
170 |
} |
|
171 |
|
|
172 | 0 |
public boolean getShowAscii() |
173 |
{ |
|
174 | 0 |
return showAscii;
|
175 |
} |
|
176 |
|
|
177 | 0 |
public char getSubstituteChar() |
178 |
{ |
|
179 | 0 |
return substituteChar;
|
180 |
} |
|
181 |
|
|
182 | 0 |
public void setAsciiBegin(String value) |
183 |
{ |
|
184 | 0 |
if (locked)
|
185 | 0 |
throw new IllegalStateException(); |
186 |
|
|
187 | 0 |
asciiBegin = value; |
188 |
} |
|
189 |
|
|
190 | 0 |
public void setAsciiEnd(String value) |
191 |
{ |
|
192 | 0 |
if (locked)
|
193 | 0 |
throw new IllegalStateException(); |
194 |
|
|
195 | 0 |
asciiEnd = value; |
196 |
} |
|
197 |
|
|
198 | 0 |
public void setBytesPerLine(int value) |
199 |
{ |
|
200 | 0 |
if (locked)
|
201 | 0 |
throw new IllegalStateException(); |
202 |
|
|
203 | 0 |
bytesPerLine = value; |
204 |
|
|
205 | 0 |
ascii = null;
|
206 |
} |
|
207 |
|
|
208 | 0 |
public void setOffsetSeperator(String value) |
209 |
{ |
|
210 | 0 |
if (locked)
|
211 | 0 |
throw new IllegalStateException(); |
212 |
|
|
213 | 0 |
offsetSeperator = value; |
214 |
} |
|
215 |
|
|
216 | 0 |
public void setShowAscii(boolean value) |
217 |
{ |
|
218 | 0 |
if (locked)
|
219 | 0 |
throw new IllegalStateException(); |
220 |
|
|
221 | 0 |
showAscii = value; |
222 |
} |
|
223 |
|
|
224 |
/**
|
|
225 |
* Sets the character used in the ASCII dump that substitutes for characters
|
|
226 |
* outside the range of 32..126.
|
|
227 |
*
|
|
228 |
**/
|
|
229 |
|
|
230 | 0 |
public void setSubstituteChar(char value) |
231 |
{ |
|
232 | 0 |
if (locked)
|
233 | 0 |
throw new IllegalStateException(); |
234 |
|
|
235 | 0 |
substituteChar = value; |
236 |
} |
|
237 |
|
|
238 | 0 |
public void write(int b) throws IOException |
239 |
{ |
|
240 | 0 |
char letter;
|
241 |
|
|
242 | 0 |
if (showAscii && ascii == null) |
243 | 0 |
ascii = new char[bytesPerLine]; |
244 |
|
|
245 |
// Prevent further customization after output starts being written.
|
|
246 |
|
|
247 | 0 |
locked = true;
|
248 |
|
|
249 | 0 |
if (lineCount == bytesPerLine)
|
250 |
{ |
|
251 | 0 |
if (showAscii)
|
252 |
{ |
|
253 | 0 |
out.print(asciiBegin); |
254 | 0 |
out.print(ascii); |
255 | 0 |
out.print(asciiEnd); |
256 |
} |
|
257 |
|
|
258 | 0 |
out.println(); |
259 |
|
|
260 | 0 |
bytesSinceSpace = 0; |
261 | 0 |
lineCount = 0; |
262 | 0 |
offset += bytesPerLine; |
263 |
} |
|
264 |
|
|
265 | 0 |
if (lineCount == 0 && showOffset)
|
266 |
{ |
|
267 | 0 |
writeHex(offset, 4); |
268 | 0 |
out.print(offsetSeperator); |
269 |
} |
|
270 |
|
|
271 |
// After every <n> bytes, emit a space.
|
|
272 |
|
|
273 | 0 |
if (spacingInterval > 0 && bytesSinceSpace == spacingInterval)
|
274 |
{ |
|
275 | 0 |
out.print(' '); |
276 | 0 |
bytesSinceSpace = 0; |
277 |
} |
|
278 |
|
|
279 | 0 |
writeHex(b, 2); |
280 |
|
|
281 | 0 |
if (showAscii)
|
282 |
{ |
|
283 | 0 |
if (b < 32 | b > 127)
|
284 | 0 |
letter = substituteChar; |
285 |
else
|
|
286 | 0 |
letter = (char) b;
|
287 |
|
|
288 | 0 |
ascii[lineCount] = letter; |
289 |
} |
|
290 |
|
|
291 | 0 |
lineCount++; |
292 | 0 |
bytesSinceSpace++; |
293 |
} |
|
294 |
|
|
295 | 0 |
private void writeHex(int value, int digits) |
296 |
{ |
|
297 | 0 |
int i;
|
298 | 0 |
int nybble;
|
299 |
|
|
300 | 0 |
for (i = 0; i < digits; i++)
|
301 |
{ |
|
302 | 0 |
nybble = (value >> 4 * (digits - i - 1)) & 0x0f; |
303 |
|
|
304 | 0 |
out.print(HEX[nybble]); |
305 |
} |
|
306 |
} |
|
307 |
} |
|