Mega Code Archive

 
Categories / Java / Data Type
 

This class allows a number to be easily formatted as a hexadecimal number The representation uses 0-f

/*  * Copyright (C) 1999  Jesse E. Peterson  *  * This library is free software; you can redistribute it and/or  * modify it under the terms of the GNU Lesser General Public  * License as published by the Free Software Foundation; either  * version 2 of the License, or (at your option) any later version.  *  * This library is distributed in the hope that it will be useful,  * but WITHOUT ANY WARRANTY; without even the implied warranty of  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  * Lesser General Public License for more details.  *  * You should have received a copy of the GNU Lesser General Public  * License along with this library; if not, write to the Free Software  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *  */ //package com.jpeterson.util; import java.text.CharacterIterator; import java.text.FieldPosition; import java.text.Format; import java.text.ParseException; import java.text.ParsePosition; import java.text.StringCharacterIterator; /**  * This class allows a number to be easily formatted as a hexadecimal number.  * The representation uses 0-f.  *   * @author Jesse Peterson <jesse@jpeterson.com>  *   * @version 1.0  */ public class HexFormat extends Format {   /**    * should upper case letters be used    */   private boolean upperCase;   private String hexDigits = "0123456789abcdefABCDEF";   /**    * Create a new HexFormat object. By default the lower case letters 'a'-'f'    * are used.    *     * @since 1.0    */   public HexFormat() {     upperCase = false;   }   /**    * Format an object in a hexadecimal representation. The object    * <CODE>number</CODE> must be an integer Number; Byte, Short, Integer, or    * Long. If the parameter <CODE>number</CODE> is not one of these, this    * method will throw a <CODE>IllegalArgumentException</CODE>.    *     * @param number    *            the number to format    * @param toAppendTo    *            where the text is to be appended    * @param pos    *            not used    * @return the formatted hex number    *     * @since 1.0    */   public StringBuffer format(Object number, StringBuffer toAppendTo,       FieldPosition pos) {     if (number instanceof Byte) {       format(((Number) number).byteValue(), toAppendTo, pos);     } else if (number instanceof Short) {       format(((Number) number).shortValue(), toAppendTo, pos);     } else if (number instanceof Integer) {       format(((Number) number).intValue(), toAppendTo, pos);     } else if (number instanceof Long) {       format(((Number) number).longValue(), toAppendTo, pos);     } else {       throw new IllegalArgumentException(           "Cannot format given Object as a Byte, Short, Integer, or Long");     }     return (toAppendTo);   }   /**    * Format a byte, returning an 8 bit hex number. (2 digits, with leading    * zeros)    *     * @param number    *            the byte to format    * @return the formatted hex number    *     * @since 1.0    */   public final String format(byte number) {     return (format(number, new StringBuffer(), new FieldPosition(0))         .toString());   }   /**    * Format a byte, returning an 8 bit hex number. (2 digits, with leading    * zeros)    *     * @param number    *            the number to format    * @param toAppendTo    *            where the text is to be appended    * @param pos    *            not used    * @return the formatted binary number    */   public StringBuffer format(byte number, StringBuffer toAppendTo,       FieldPosition pos) {     int hiNibble, loNibble;     String hiDigit, loDigit;     hiNibble = (number >>> 4) & 0x0f;     loNibble = number & 0x0f;     hiDigit = Integer.toHexString(hiNibble);     loDigit = Integer.toHexString(loNibble);     if (upperCase) {       hiDigit = hiDigit.toUpperCase();       loDigit = loDigit.toUpperCase();     } else {       hiDigit = hiDigit.toLowerCase();       loDigit = loDigit.toLowerCase();     }     toAppendTo.append(hiDigit).append(loDigit);     return (toAppendTo);   }   /**    * Format an array of bytes, returning 8 bits per byte. (2 digits with    * leading zeros, per byte) The byte at index zero is the most significant    * byte, making it possible to enter a stream of bytes received from a    * serial connection very easily.    *     * @param number    *            the bytes to format    * @return the formatted binary number    *     * @since 1.0    */   public final String format(byte[] number) {     return (format(number, new StringBuffer(), new FieldPosition(0))         .toString());   }   /**    * Format an array of bytes, returning 8 bits per bytes. (2 digits with    * leading zeros, per byte) The byte at index zero is the most significant    * byte, making it possible to enter a stream of bytes received from a    * serial connection very easily.    *     * @param number    *            the number to format    * @param toAppendTo    *            where the text is to be appended    * @param pos    *            not used    * @return the formatted binary number    *     * @since 1.0    */   public StringBuffer format(byte[] number, StringBuffer toAppendTo,       FieldPosition pos) {     for (int i = 0; i < number.length; i++) {       format(number[i], toAppendTo, pos);     }     return (toAppendTo);   }   /**    * Format a short value, returning a 16 bit hexadecimal number. (4 digits    * with leading zeros)    *     * @param number    *            the short to format    * @return the formatted binary number    *     * @since 1.0    */   public String format(short number) {     return (format(number, new StringBuffer(), new FieldPosition(0))         .toString());   }   /**    * Format a short value, returning a 16 bit hexadecimal number. (4 digits    * with leading zeros)    *     * @param number    *            the number to format    * @param toAppendTo    *            where the text is to be appended    * @param pos    *            not used    * @return the formatted binary number    *     * @since 1.0    */   public StringBuffer format(short number, StringBuffer toAppendTo,       FieldPosition pos) {     byte[] array = new byte[2];     array[0] = (byte) ((number >>> 8) & 0xff);     array[1] = (byte) (number & 0xff);     return (format(array, toAppendTo, pos));   }   /**    * Format an int value, returning a 32 bit hexadecimal number. (8 digits    * with leading zeros)    *     * @param number    *            the int to format    * @return the formatted binary number    *     * @since 1.0    */   public String format(int number) {     return (format(number, new StringBuffer(), new FieldPosition(0))         .toString());   }   /**    * Format an int value, returning a 32 bit hexadecimal number. (8 digits    * with leading zeros)    *     * @param number    *            the number to format    * @param toAppendTo    *            where the text is to be appended    * @param pos    *            not used    * @return the formatted binary number    *     * @since 1.0    */   public StringBuffer format(int number, StringBuffer toAppendTo,       FieldPosition pos) {     byte[] array = new byte[4];     array[0] = (byte) ((number >>> 24) & 0xff);     array[1] = (byte) ((number >>> 16) & 0xff);     array[2] = (byte) ((number >>> 8) & 0xff);     array[3] = (byte) (number & 0xff);     return (format(array, toAppendTo, pos));   }   /**    * Format a long value, returning a 64 bit hexadecimal number. (16 digits    * with leading zeros)    *     * @param number    *            the long to format    * @return the formatted binary number    *     * @since 1.0    */   public String format(long number) {     return (format(number, new StringBuffer(), new FieldPosition(0))         .toString());   }   /**    * Format a long value, returning a 64 bit hexadecimal number. (16 digits    * with leading zeros)    *     * @param number    *            the number to format    * @param toAppendTo    *            where the text is to be appended    * @param pos    *            not used    * @return the formatted binary number    *     * @since 1.0    */   public StringBuffer format(long number, StringBuffer toAppendTo,       FieldPosition pos) {     byte[] array = new byte[8];     array[0] = (byte) ((number >>> 56) & 0xff);     array[1] = (byte) ((number >>> 48) & 0xff);     array[2] = (byte) ((number >>> 40) & 0xff);     array[3] = (byte) ((number >>> 32) & 0xff);     array[4] = (byte) ((number >>> 24) & 0xff);     array[5] = (byte) ((number >>> 16) & 0xff);     array[6] = (byte) ((number >>> 8) & 0xff);     array[7] = (byte) (number & 0xff);     return (format(array, toAppendTo, pos));   }   /**    * Parse a hex number into a Number object. Hexadecimal numbers may be    * indicated with a leading character designation of '0x'. If up to 1 byte    * is parsed, returns a Byte. If more than 1 and up to 2 bytes are parsed,    * return a Short. If more than 2 and up to 4 bytes are parsed, return an    * Integer. If more than 4 and up to 8 bytes are parsed, return a Long.    *     * @param source    *            a binary number    * @return return an integer form of Number object if parse is successful    * @exception ParseException    *                thrown if source is cannot be converted to a Byte, Short,    *                Int, or Long.    *     * @since 1.0    */   public Number parse(String source) throws ParseException {     int startIndex = 0;     Number result;     ParsePosition parsePosition = new ParsePosition(startIndex);     result = parse(source, parsePosition);     if (result == null) {       throw new ParseException("Unable to parse " + source           + " using HexFormat", parsePosition.getIndex());     }     return (result);   }   /**    * Parse a hex number into a Number object. Hexadecimal numbers may be    * indicated with a leading character designation of '0x'. If up to 1 byte    * is parsed, returns a Byte. If more than 1 and up to 2 bytes are parsed,    * return a Short. If more than 2 and up to 4 bytes are parsed, return an    * Integer. If more than 4 and up to 8 bytes are parsed, return a Long.    *     * @param text    *            a hexadecimal number    * @param parsePosition    *            position to start parsing from    * @return return an integer form of Number object if parse is successful;    *         <CODE>null</CODE> otherwise    *     * @since 1.0    */   public Number parse(String text, ParsePosition parsePosition) {     boolean skipWhitespace = true;     int startIndex, nibbles;     // remove whitespace     StringCharacterIterator iter = new StringCharacterIterator(text,         parsePosition.getIndex());     for (char c = iter.current(); c != CharacterIterator.DONE; c = iter         .next()) {       if (skipWhitespace && Character.isWhitespace(c)) {         // skip whitespace         continue;       }       break;     }     // skip a leading hex designation of the characters '0x'     if (text.regionMatches(iter.getIndex(), "0x", 0, 2)) {       parsePosition.setIndex(iter.getIndex() + 2);     } else {       parsePosition.setIndex(iter.getIndex());     }     startIndex = parsePosition.getIndex();     Number result = (Number) parseObject(text, parsePosition);     if (result == null) {       return (result);     }     nibbles = parsePosition.getIndex() - startIndex;     if (nibbles <= 2) {       result = new Byte(result.byteValue());     } else if (nibbles <= 4) {       result = new Short(result.shortValue());     } else if (nibbles <= 8) {       result = new Integer(result.intValue());     } else if (nibbles <= 16) {       result = new Long(result.longValue());     }     return (result);   }   /**    * Parse a hexadecimal number, skipping leading whitespace. Does not throw    * an exception; if no object can be parsed, index is unchanged! Hexadecimal    * numbers may be indicated with a leading character designation of '0x'.    *     * @param source    *            the string to parse    * @param status    *            the string index to start at    * @return The hexadecimal number as a Long object.    *     * @since 1.0    */   public Object parseObject(String source, ParsePosition status) {     int start = status.getIndex();     boolean success = false;     StringBuffer buffer = new StringBuffer();     char c, c2;     long result;     StringCharacterIterator iter = new StringCharacterIterator(source,         start);     for (c = iter.current(); c != CharacterIterator.DONE; c = iter.next()) {       if (Character.isWhitespace(c)) {         // skip whitespace         continue;       }       break;     }     if (c == CharacterIterator.DONE) {       return (null);     }     if (c == '0') {       c2 = iter.next();       if (c2 == CharacterIterator.DONE) {         return (null);       }       if (c2 == 'x') {         // has a leading '0x' designation, so skip over it       } else {         // replace the two characters         iter.previous();         iter.previous();       }     } else {       // skip back one character       iter.previous();     }     // gather valid hex digits     for (c = iter.next(); c != CharacterIterator.DONE; c = iter.next()) {       if (hexDigits.indexOf(c) != -1) {         success = true;         buffer.append(c);       } else {         break;       }     }     if (!success) {       // no valid hex digits       return (null);     }     // convert hex to long     if (buffer.length() > 16) {       // larger than a long, error       // with a buffer full of nibbles, the maximum nibbles in a       // 64 bit number is 16 nibbles       return (null);     }     // parse number     try {       result = Long.parseLong(buffer.toString(), 16);     } catch (NumberFormatException e) {       // unable to parse number       return (null);     }     status.setIndex(iter.getIndex());     return (new Long(result));   }   /**    * Set upper case mode for alpha characters.    *     * @param upperCase    *            true if upper case alpha characters should be used; false    *            otherwise    *     * @since 1.0    */   public void setUpperCase(boolean upperCase) {     this.upperCase = upperCase;   }   /**    * Get upper case mode for alpha characters.    *     * @return true if upper case alpha characters should be used; false    *         otherwise    *     * @since 1.0    */   public boolean getUpperCase() {     return (upperCase);   }   /**    * Is upper case mode for alpha characters in affect?    *     * @return true if upper case alpha characters should be used; false    *         otherwise    *     * @since 1.0    */   public boolean isUpperCase() {     return (getUpperCase());   }   /**    * Is lower case mode for alpha characters in affect?    *     * @return true if lower case alpha characters should be used; false    *         otherwise    *     * @since 1.0    */   public boolean isLowerCase() {     return (!getUpperCase());   }   // /////////////   // self test //   // /////////////   public static void main(String[] args) {     String result;     HexFormat format = new HexFormat();     // byte     byte bNumber = 0x33;     result = format.format(bNumber);     if (result.equals("33")) {       System.out.print("Success => ");     } else {       System.out.print("FAILURE => ");     }     System.out.println("Byte: " + bNumber + " (0x" + result + ")");     bNumber = (byte) 0x85;     result = format.format(bNumber);     if (result.equals("85")) {       System.out.print("Success => ");     } else {       System.out.print("FAILURE => ");     }     System.out.println("Byte: " + bNumber + " (0x" + result + ")");     bNumber = (byte) 0x0f;     result = format.format(bNumber);     if (result.equals("0f")) {       System.out.print("Success => ");     } else {       System.out.print("FAILURE => ");     }     System.out.println("Byte: " + bNumber + " (0x" + result + ")");     short sNumber = (short) 0xa2b6;     result = format.format(sNumber);     if (result.equals("a2b6")) {       System.out.print("Success => ");     } else {       System.out.print("FAILURE => ");     }     System.out.println("Byte: " + bNumber + " (0x" + result + ")");     format.setUpperCase(true);     int iNumber = (int) 0x4321fedc;     result = format.format(iNumber);     if (result.equals("4321FEDC")) {       System.out.print("Success => ");     } else {       System.out.print("FAILURE => ");     }     System.out.println("Byte: " + bNumber + " (0x" + result + ")");     long lNumber = (long) 0x4321fedc4321fedcL;     result = format.format(lNumber);     if (result.equals("4321FEDC4321FEDC")) {       System.out.print("Success => ");     } else {       System.out.print("FAILURE => ");     }     System.out.println("Byte: " + bNumber + " (0x" + result + ")");     String num = "0xfe";     Number number = null;     Byte bExpect = new Byte((byte) 0xfe);     try {       number = format.parse(num);     } catch (ParseException e) {       System.out.println(e);       e.printStackTrace();     }     if ((number instanceof Byte) && (number.equals(bExpect))) {       System.out.print("Success => ");     } else {       System.out.print("FAILURE => ");     }     System.out.println("Byte: " + bExpect + " result: " + number);     num = "0xf";     number = null;     bExpect = new Byte((byte) 0xf);     try {       number = format.parse(num);     } catch (ParseException e) {       System.out.println(e);       e.printStackTrace();     }     if ((number instanceof Byte) && (number.equals(bExpect))) {       System.out.print("Success => ");     } else {       System.out.print("FAILURE => ");     }     System.out.println("Byte: " + bExpect + " result: " + number);     num = "0xf0f0";     number = null;     Short sExpect = new Short((short) 0xf0f0);     try {       number = format.parse(num);     } catch (ParseException e) {       System.out.println(e);       e.printStackTrace();     }     if ((number instanceof Short) && (number.equals(sExpect))) {       System.out.print("Success => ");     } else {       System.out.print("FAILURE => ");     }     System.out.println("Short: " + sExpect + " result: " + number);     num = "0xdEAdbEEf";     number = null;     Integer iExpect = new Integer((int) 0xdEAdbEEf);     try {       number = format.parse(num);     } catch (ParseException e) {       System.out.println(e);       e.printStackTrace();     }     if ((number instanceof Integer) && (number.equals(iExpect))) {       System.out.print("Success => ");     } else {       System.out.print("FAILURE => ");     }     System.out.println("Integer: " + iExpect + " result: " + number);   } }