001: /**
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */package com.tc.util;
004:
005: import com.tc.bytes.TCByteBuffer;
006: import com.tc.bytes.TCByteBufferFactory;
007:
008: import java.io.IOException;
009: import java.io.OutputStream;
010: import java.io.OutputStreamWriter;
011: import java.io.PrintWriter;
012: import java.io.StringWriter;
013: import java.io.Writer;
014: import java.nio.ByteBuffer;
015:
016: /**
017: * Class to facilitate printing out binary data or opaque objects in some sort of other usable form.
018: */
019: public final class Dumper {
020:
021: /**
022: * Does nothing
023: */
024: private Dumper() {
025: super ();
026: }
027:
028: /**
029: * Calls <code>dump(buffer, 10, 16, 2, 8, new OutputStreamWriter(outs))</code>.
030: */
031: public static final void hexDump(TCByteBuffer buffer,
032: OutputStream outs) throws IOException {
033: dump(new ByteishWrapper(null, buffer), 10, 16, 2, 8,
034: new OutputStreamWriter(outs));
035: }
036:
037: /**
038: * Calls <code>dump(buffer, 10, 16, 2, 8, new OutputStreamWriter(outs))</code>.
039: */
040: public static final void hexDump(TCByteBuffer buffer, Writer writer)
041: throws IOException {
042: dump(new ByteishWrapper(null, buffer), 10, 16, 2, 8, writer);
043: }
044:
045: /**
046: * Calls <code>dump(buffer, 10, 16, 2, 8, new OutputStreamWriter(outs))</code>.
047: */
048: public static final void hexDump(ByteBuffer buffer,
049: OutputStream outs) throws IOException {
050: dump(new ByteishWrapper(buffer, null), 10, 16, 2, 8,
051: new OutputStreamWriter(outs));
052: }
053:
054: /**
055: * Calls <code>dump(buffer, 10, 16, 2, 8, new OutputStreamWriter(outs))</code>.
056: */
057: public static final void hexDump(ByteBuffer buffer, Writer writer)
058: throws IOException {
059: dump(new ByteishWrapper(buffer, null), 10, 16, 2, 8, writer);
060: }
061:
062: /**
063: * Calls <code>dump(buffer, 10, 8, 2, 8, new OutputStreamWriter(outs))</code>.
064: */
065: public static final void octalDump(TCByteBuffer buffer,
066: OutputStream outs) throws IOException {
067: dump(new ByteishWrapper(null, buffer), 10, 8, 2, 8,
068: new OutputStreamWriter(outs));
069: }
070:
071: /**
072: * Calls <code>dump(buffer, 10, 8, 2, 8, new OutputStreamWriter(outs))</code>.
073: */
074: public static final void octalDump(TCByteBuffer buffer,
075: Writer writer) throws IOException {
076: dump(new ByteishWrapper(null, buffer), 10, 8, 2, 8, writer);
077: }
078:
079: /**
080: * Calls <code>dump(buffer, 10, 8, 2, 8, new OutputStreamWriter(outs))</code>.
081: */
082: public static final void octalDump(ByteBuffer buffer,
083: OutputStream outs) throws IOException {
084: dump(new ByteishWrapper(buffer, null), 10, 8, 2, 8,
085: new OutputStreamWriter(outs));
086: }
087:
088: /**
089: * Calls <code>dump(buffer, 10, 8, 2, 8, new OutputStreamWriter(outs))</code>.
090: */
091: public static final void octalDump(ByteBuffer buffer, Writer writer)
092: throws IOException {
093: dump(new ByteishWrapper(buffer, null), 10, 8, 2, 8, writer);
094: }
095:
096: /**
097: * Calls
098: * <code>dump(buffer, offsetRadix, dataRadix, bytesPerColumn, columnsPerLine, new OutputStreamWriter(outs))</code>.
099: */
100: public static final void dump(TCByteBuffer buffer, int offsetRadix,
101: int dataRadix, int bytesPerColumn, int columnsPerLine,
102: OutputStream outs) throws IOException {
103: dump(new ByteishWrapper(null, buffer), offsetRadix, dataRadix,
104: bytesPerColumn, columnsPerLine, new OutputStreamWriter(
105: outs));
106: }
107:
108: /**
109: * Calls <code>dump(buffer, offsetRadix, dataRadix, bytesPerColumn, columnsPerLine, writer)</code>.
110: */
111: public static final void dump(TCByteBuffer buffer, int offsetRadix,
112: int dataRadix, int bytesPerColumn, int columnsPerLine,
113: Writer writer) throws IOException {
114: dump(new ByteishWrapper(null, buffer), offsetRadix, dataRadix,
115: bytesPerColumn, columnsPerLine, writer);
116: }
117:
118: /**
119: * Calls
120: * <code>dump(buffer, offsetRadix, dataRadix, bytesPerColumn, columnsPerLine, new OutputStreamWriter(outs))</code>.
121: */
122: public static final void dump(ByteBuffer buffer, int offsetRadix,
123: int dataRadix, int bytesPerColumn, int columnsPerLine,
124: OutputStream outs) throws IOException {
125: dump(new ByteishWrapper(buffer, null), offsetRadix, dataRadix,
126: bytesPerColumn, columnsPerLine, new OutputStreamWriter(
127: outs));
128: }
129:
130: /**
131: * Calls <code>dump(buffer, offsetRadix, dataRadix, bytesPerColumn, columnsPerLine, writer)</code>.
132: */
133: public static final void dump(ByteBuffer buffer, int offsetRadix,
134: int dataRadix, int bytesPerColumn, int columnsPerLine,
135: Writer writer) throws IOException {
136: dump(new ByteishWrapper(buffer, null), offsetRadix, dataRadix,
137: bytesPerColumn, columnsPerLine, writer);
138: }
139:
140: /**
141: * Dumps the contents of the buffer in the tradition of the "od" and "hexdump" UNIX utilities.
142: *
143: * @param buffer the byte-ish buffer to read from
144: * @param offsetRadix the radix to use when printing the offset
145: * @param dataRadix the radix to use when printing the data
146: * @param bytesPerColumn the number of bytes to concatenate in radix <code>dataRadix</code> in each column (2 is
147: * normal)
148: * @param columnsPerLine the number of columns of groups of bytes to have (8 is normal for bases 8 and 16, probably
149: * want less for smaller bases)
150: * @param writer the writer to spit the output to
151: */
152: private static final void dump(ByteishBuffer buffer,
153: int offsetRadix, int dataRadix, int bytesPerColumn,
154: int columnsPerLine, Writer writer) throws IOException {
155: // Do some basic sanity checking
156: if (buffer == null || offsetRadix < 2 || dataRadix < 2
157: || bytesPerColumn < 1 || columnsPerLine < 1
158: || writer == null) {
159: return;
160: }
161: int dataPadding = 2;
162: // Increase the padding per byte for any radix lower than 16
163: if (dataRadix < 16) {
164: if (dataRadix > 6) {
165: dataPadding = 3;
166: } else if (dataRadix > 3) {
167: dataPadding = 4;
168: } else if (dataRadix == 3) {
169: dataPadding = 6;
170: } else if (dataRadix == 2) {
171: dataPadding = 8;
172: }
173: }
174: int bytesPerLine = bytesPerColumn * columnsPerLine;
175: int bytesPrintedOnLine = 0;
176: for (int pos = 0; pos < buffer.limit(); ++pos) {
177: // See if we need to start a new line
178: if (bytesPrintedOnLine == bytesPerLine) {
179: writer.write("\n");
180: writer.flush();
181: bytesPrintedOnLine = 0;
182: }
183: // See if we need to print out the offset
184: if (bytesPrintedOnLine == 0) {
185: // Print the offset
186: writer.write(StringUtil.toPaddedString(pos,
187: offsetRadix, 7));
188: }
189: // See if we need to print a column break, either after the offset
190: // is printed
191: // or we've finished a column
192: if (bytesPrintedOnLine % bytesPerColumn == 0) {
193: writer.write(StringUtil.SPACE_STRING);
194: }
195: // Print out the next byte in the specified radix with a certain
196: // padding
197: writer.write(StringUtil.toPaddedString(
198: 0x00000000000000ff & buffer.get(pos), dataRadix,
199: dataPadding));
200: ++bytesPrintedOnLine;
201: }
202: // If we didn't fill up the line, fill it with spaces
203:
204: // Print the offset of the buffer length + 1 on a line by itself
205: writer.write("\n"
206: + StringUtil.toPaddedString(buffer.limit() + 1,
207: offsetRadix, 7) + "\n");
208: writer.flush();
209: }
210:
211: public static String hexDump(byte[] bytes, int length) {
212: StringWriter sw = new StringWriter();
213: sw.write("\n");
214: byte[] dumpBytes = new byte[length];
215: for (int pos = 0; pos < length; ++pos)
216: dumpBytes[pos] = bytes[pos];
217: try {
218: Dumper.hexDump(TCByteBufferFactory.copyAndWrap(dumpBytes),
219: sw);
220: } catch (IOException ioe) {
221: sw = new StringWriter();
222: PrintWriter pw = new PrintWriter(sw);
223: sw.write("Unable to generate hex dump, exception was: ");
224: ioe.printStackTrace(pw);
225: pw.flush();
226: }
227: return sw.toString();
228: }
229:
230: }
|