package com.mindprod.example;
import com.mindprod.common18.ST;
import static java.lang.System.*;
/**
* Demonstrate how to handle hex strings.
*
* @author Roedy Green, Canadian Mind Products
* @version 1.0 2009-06-05 initial version.
* @since 2009-06-05
*/
public final class TestHex
{
/**
* precomputed translate table for chars 0..'f'
*/
private static final byte[] correspondingNibble = new byte[ 'f' + 1 ];
static
{
for ( int i = 0; i <= 'f'; i++ )
{
correspondingNibble[ i ] = -1;
}
for ( int i = '0'; i <= '9'; i++ )
{
correspondingNibble[ i ] = ( byte ) ( i - '0' );
}
for ( int i = 'A'; i <= 'F'; i++ )
{
correspondingNibble[ i ] = ( byte ) ( i - 'A' + 10 );
}
for ( int i = 'a'; i <= 'f'; i++ )
{
correspondingNibble[ i ] = ( byte ) ( i - 'a' + 10 );
}
}
/**
* convert a single char to corresponding nibble using a precalculated array.
* Based on code by:
* Brian Marquis
* Orion Group Software Engineers http://www.ogse.com
*
* @param c char to convert. must be 0-9 a-f A-F, no
* spaces, plus or minus signs.
*
* @return corresponding integer 0..15
* @throws IllegalArgumentException on invalid c.
*/
private static int charToNibble( char c )
{
if ( c > 'f' )
{
throw new IllegalArgumentException( "Invalid hex character: " + c );
}
int nibble = correspondingNibble[ c ];
if ( nibble < 0 )
{
throw new IllegalArgumentException( "Invalid hex character: " + c );
}
return nibble;
}
/**
* Convert a hex string to an unsigned byte array.
* Permits upper or lower case hex.
*
* @param s String must have even number of characters.
* and be formed only of digits 0-9 A-F or
* a-f. No spaces, minus or plus signs.
*
* @return corresponding unsigned byte array. see http://mindprod.com/jgloss/unsigned.html
*/
private static byte[] fromHexString( String s )
{
int stringLength = s.length();
if ( ( stringLength & 0x1 ) != 0 )
{
throw new IllegalArgumentException( "fromHexString requires an even number of hex characters" );
}
byte[] bytes = new byte[ stringLength / 2 ];
for ( int i = 0, j = 0; i < stringLength; i += 2, j++ )
{
int high = charToNibble( s.charAt( i ) );
int low = charToNibble( s.charAt( i + 1 ) );
bytes[ j ] = ( byte ) ( ( high << 4 ) | low );
}
return bytes;
}
/**
* code not used, for explanation only.
* convert a single char to corresponding nibble.
* Slow version, easier to understand.
*
* @param c char to convert. must be 0-9 a-f A-F, no
* spaces, plus or minus signs.
*
* @return corresponding integer
*/
private static int slowCharToNibble( char c )
{
if ( '0' <= c && c <= '9' )
{
return c - '0';
}
else if ( 'a' <= c && c <= 'f' )
{
return c - 'a' + 0xa;
}
else if ( 'A' <= c && c <= 'F' )
{
return c - 'A' + 0xa;
}
else
{
throw new IllegalArgumentException( "Invalid hex character: " + c );
}
}
/**
* Test harness
*
* @param args not used
*/
public static void main( String[] args )
{
String hexString = "9000003D050000000000123456789ABCDEFabcde6f00000000000000";
out.println( hexString );
byte[] bytes = fromHexString( hexString );
out.println( bytes.length + " bytes long" );
for ( byte b : bytes )
{
out.print( ST.toLZHexString( b & 0xff, 2 ) );
out.print( ' ' );
}
out.println();
}
}