/******************************************************************************* * Copyright © 2006, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * *******************************************************************************/ package org.eclipse.edt.javart.util; import org.eclipse.edt.javart.ByteStorage; import org.eclipse.edt.javart.ConversionAttributeSet; import eglx.lang.AnyException; import org.eclipse.edt.javart.resources.Trace; /** * This class formats bytes into an easily readable format. * In addition it converts the byte data to the format specified in the ConversionAttributeSet * This is used as a debugging tool when passing bytes to and from a host * * @author jvincens */ public class ByteFormatter { private ConversionAttributeSet attrs; private static final int MAX_DISPLAY_LEN = 1024; private static final int BYTE_LINE_LEN = 37; private static final int CHAR_LINE_LEN = 17; private static ByteStorage bs; private ByteFormatter( ConversionAttributeSet attrs ) { this.attrs = attrs; bs = new ByteStorage( 1 ); } private void print( byte[] bytes, StringBuilder line, int max ) { int len = bytes == null ? 0 : bytes.length; if( len > max ) { len = max; } evalBytes( bytes, line, len ); } private void evalBytes( byte[] bytes, StringBuilder line, int limit ) { StringBuilder ebcdicBuf = new StringBuilder(); StringBuilder asciiBuf = new StringBuilder(); StringBuilder byteBuf = new StringBuilder(); int i; for( i = 0; i < bytes.length && i < limit; i++ ) { //16 is the start of a new line if( i % 16 == 0 ) { line.append( getInt( i ) + " " ); ebcdicBuf = new StringBuilder( "'" ); asciiBuf = new StringBuilder( "'" ); byteBuf = new StringBuilder(); } byteBuf.append( getByte( bytes[ i ] ) ); appendChar( bytes[ i ], asciiBuf, attrs ); //is the next value on a new line append the asii and ebcdic diplay values if( (i + 1) % 16 == 0 ) { endLine( line, ebcdicBuf, asciiBuf, byteBuf ); } else if( (i + 1) % 4 == 0 ) { byteBuf.append( " " ); } } if( byteBuf.length() < BYTE_LINE_LEN ) { endLine( line, ebcdicBuf, asciiBuf, byteBuf ); } } private void endLine( StringBuilder line, StringBuilder ebcdicBuf, StringBuilder asciiBuf, StringBuilder byteBuf ) { if( byteBuf.length() < BYTE_LINE_LEN ) { while( byteBuf.length() < BYTE_LINE_LEN ) { byteBuf.append( ' ' ); } while( asciiBuf.length() < CHAR_LINE_LEN ) { asciiBuf.append( ' ' ); } while( ebcdicBuf.length() < CHAR_LINE_LEN ) { ebcdicBuf.append( ' ' ); } } line.append( byteBuf ); if( attrs != null ) { line.append( asciiBuf ); line.append( "' " ); } line.append( '\n' ); } private static String getInt( int i ) { String retVal = "00000000" + Integer.toHexString( i ).toUpperCase(); return retVal.substring( retVal.length() - 8 ); } private static String getByte( byte b ) { String retVal = "00" + Integer.toHexString( b ).toUpperCase(); return retVal.substring( retVal.length() - 2 ); } private static void appendChar( byte val, StringBuilder buf, ConversionAttributeSet attrs ) { if( attrs != null ) { char ch = getChar( val, attrs ); if( Character.isISOControl( ch ) ) { ch = '.'; } buf.append( ch ); } } private static char getChar( byte val, ConversionAttributeSet attrs ) { char ch = ' '; try { attrs.apply( bs ); byte[] bytes = new byte[1]; bytes[0] = val; bs.reset( bytes ); String strVal = bs.loadString( 1, 1 ); if( strVal != null && strVal.length() > 0 ) { ch = strVal.charAt( 0 ); } } catch( Exception e ) { } return ch; } public static void printBytes( byte[] bytes, String header, ConversionAttributeSet attrs ) throws AnyException { if( bytes != null ) { ByteFormatter bf = new ByteFormatter( attrs ); StringBuilder buf = new StringBuilder(); bf.print( bytes, buf, MAX_DISPLAY_LEN ); System.out.println( header ); System.out.println( buf.toString() ); } } public static void traceBytes( byte[] bytes, int dumpSize, String header, ConversionAttributeSet attrs, Trace tracer ) throws AnyException { if( bytes != null ) { ByteFormatter bf = new ByteFormatter( attrs ); StringBuilder buf = new StringBuilder(); bf.print( bytes, buf, dumpSize ); buf.insert( 0, "\n" ); buf.insert( 0, header ); tracer.put( buf.toString() ); } } public static void traceBytes( byte[] bytes, String header, ConversionAttributeSet attrs, Trace tracer ) throws AnyException { traceBytes( bytes, MAX_DISPLAY_LEN, header, attrs, tracer ); } public static void traceBytes( byte[] bytes, Trace tracer ) throws AnyException { if( bytes != null ) { ByteFormatter bf = new ByteFormatter( null ); StringBuilder buf = new StringBuilder(); bf.print( bytes, buf, MAX_DISPLAY_LEN ); buf.insert( 0, "\n" ); tracer.put( buf.toString() ); } } }