FileDocCategorySizeDatePackage
HexStringParser.javaAPI DocAndroid 1.5 API10936Wed May 06 22:41:04 BST 2009org.apache.harmony.luni.util

HexStringParser

public final class HexStringParser extends Object

Fields Summary
private static final int
DOUBLE_EXPONENT_WIDTH
private static final int
DOUBLE_MANTISSA_WIDTH
private static final int
FLOAT_EXPONENT_WIDTH
private static final int
FLOAT_MANTISSA_WIDTH
private static final int
HEX_RADIX
private static final int
MAX_SIGNIFICANT_LENGTH
private static final String
HEX_SIGNIFICANT
private static final String
BINARY_EXPONENT
private static final String
FLOAT_TYPE_SUFFIX
private static final String
HEX_PATTERN
private static final Pattern
PATTERN
private final int
EXPONENT_WIDTH
private final int
MANTISSA_WIDTH
private final long
EXPONENT_BASE
private final long
MAX_EXPONENT
private final long
MIN_EXPONENT
private final long
MANTISSA_MASK
private long
sign
private long
exponent
private long
mantissa
private String
abandonedNumber
Constructors Summary
public HexStringParser(int exponent_width, int mantissa_width)

 //$NON-NLS-1$

         
        this.EXPONENT_WIDTH = exponent_width;
        this.MANTISSA_WIDTH = mantissa_width;
        
        this.EXPONENT_BASE = ~(-1L << (exponent_width - 1));
        this.MAX_EXPONENT = ~(-1L << exponent_width);
        this.MIN_EXPONENT = -(MANTISSA_WIDTH + 1);
        this.MANTISSA_MASK = ~(-1L << mantissa_width);
    
Methods Summary
private voidcheckedAddExponent(long offset)

        long result = exponent + offset;
        int expSign = Long.signum(exponent);
        if (expSign * Long.signum(offset) > 0 && expSign * Long.signum(result) < 0) {
            exponent = expSign * Long.MAX_VALUE;
        } else {
            exponent = result;
        }
    
private intcountBitsLength(long value)

        int leadingZeros = Long.numberOfLeadingZeros(value);
        return Long.SIZE - leadingZeros;
    
private voiddiscardTrailingBits(long num)

        long mask = ~(-1L << num);
        abandonedNumber += (mantissa & mask);
        mantissa >>= num;
    
private voidfitMantissaInDesiredWidth(int desiredWidth)

        int bitLength = countBitsLength(mantissa);
        if (bitLength > desiredWidth) {
            discardTrailingBits(bitLength - desiredWidth);
        } else {
            mantissa <<= (desiredWidth - bitLength);
        }
    
private java.lang.StringgetNormalizedSignificand(java.lang.String strIntegerPart, java.lang.String strDecimalPart)

        String significand = strIntegerPart + strDecimalPart;
        significand = significand.replaceFirst("^0+", ""); //$NON-NLS-1$//$NON-NLS-2$
        if (significand.length() == 0) {
            significand = "0"; //$NON-NLS-1$
        }
        return significand;
    
private intgetOffset(java.lang.String strIntegerPart, java.lang.String strDecimalPart)

        strIntegerPart = strIntegerPart.replaceFirst("^0+", ""); //$NON-NLS-1$ //$NON-NLS-2$
        
        //If the Interger part is a nonzero number.
        if (strIntegerPart.length() != 0) {
            String leadingNumber = strIntegerPart.substring(0, 1);
            return (strIntegerPart.length() - 1) * 4 + countBitsLength(Long.parseLong(leadingNumber,HEX_RADIX)) - 1;
        }
        
        //If the Interger part is a zero number.
        int i;
        for (i = 0; i < strDecimalPart.length() && strDecimalPart.charAt(i) == '0"; i++);   
        if (i == strDecimalPart.length()) {
            return 0;
        }
        String leadingNumber=strDecimalPart.substring(i,i + 1);
        return (-i - 1) * 4 + countBitsLength(Long.parseLong(leadingNumber, HEX_RADIX)) - 1;
    
private static java.lang.String[]getSegmentsFromHexString(java.lang.String hexString)

        Matcher matcher = PATTERN.matcher(hexString);
        if (!matcher.matches()) {
            throw new NumberFormatException();
        }

        String[] hexSegments = new String[3];
        hexSegments[0] = matcher.group(1);
        hexSegments[1] = matcher.group(2);
        hexSegments[2] = matcher.group(3);

        return hexSegments;
    
private longparse(java.lang.String hexString)

        String[] hexSegments = getSegmentsFromHexString(hexString);
        String signStr = hexSegments[0];
        String significantStr = hexSegments[1];
        String exponentStr = hexSegments[2];

        parseHexSign(signStr);
        parseExponent(exponentStr);
        parseMantissa(significantStr);

        sign <<= (MANTISSA_WIDTH + EXPONENT_WIDTH);
        exponent <<= MANTISSA_WIDTH;
        return sign | exponent | mantissa;
    
public static doubleparseDouble(java.lang.String hexString)

        HexStringParser parser = new HexStringParser(DOUBLE_EXPONENT_WIDTH,
                DOUBLE_MANTISSA_WIDTH);
        long result = parser.parse(hexString);
        return Double.longBitsToDouble(result);
    
private voidparseExponent(java.lang.String exponentStr)

        char leadingChar = exponentStr.charAt(0);
        int expSign = (leadingChar == '-" ? -1 : 1);
        if (!Character.isDigit(leadingChar)) {
            exponentStr = exponentStr.substring(1);
        }

        try {
            exponent = expSign * Long.parseLong(exponentStr);
            checkedAddExponent(EXPONENT_BASE);
        } catch (NumberFormatException e) {
            exponent = expSign * Long.MAX_VALUE;
        }
    
public static floatparseFloat(java.lang.String hexString)

        HexStringParser parser = new HexStringParser(FLOAT_EXPONENT_WIDTH,
                FLOAT_MANTISSA_WIDTH);
        int result = (int) parser.parse(hexString);
        return Float.intBitsToFloat(result);
    
private voidparseHexSign(java.lang.String signStr)

        this.sign = signStr.equals("-") ? 1 : 0; //$NON-NLS-1$
    
private voidparseMantissa(java.lang.String significantStr)

        String[] strings = significantStr.split("\\."); //$NON-NLS-1$
        String strIntegerPart = strings[0];
        String strDecimalPart = strings.length > 1 ? strings[1] : ""; //$NON-NLS-1$

        String significand = getNormalizedSignificand(strIntegerPart,strDecimalPart);
        if (significand.equals("0")) { //$NON-NLS-1$
            setZero();
            return;
        }

        int offset = getOffset(strIntegerPart, strDecimalPart);
        checkedAddExponent(offset);
        
        if (exponent >= MAX_EXPONENT) {
            setInfinite();
            return;
        }
        
        if (exponent <= MIN_EXPONENT) {
            setZero();
            return;
        }

        if (significand.length() > MAX_SIGNIFICANT_LENGTH) {
            abandonedNumber = significand.substring(MAX_SIGNIFICANT_LENGTH);
            significand = significand.substring(0, MAX_SIGNIFICANT_LENGTH);
        }

        mantissa = Long.parseLong(significand, HEX_RADIX);

        if (exponent >= 1) {
            processNormalNumber();
        } else{
            processSubNormalNumber();
        }

    
private voidprocessNormalNumber()

        int desiredWidth = MANTISSA_WIDTH + 2;
        fitMantissaInDesiredWidth(desiredWidth);
        round();
        mantissa = mantissa & MANTISSA_MASK;
    
private voidprocessSubNormalNumber()

        int desiredWidth = MANTISSA_WIDTH + 1;
        desiredWidth += (int)exponent;//lends bit from mantissa to exponent
        exponent = 0;
        fitMantissaInDesiredWidth(desiredWidth);
        round();
        mantissa = mantissa & MANTISSA_MASK;
    
private voidround()

        String result = abandonedNumber.replaceAll("0+", ""); //$NON-NLS-1$ //$NON-NLS-2$
        boolean moreThanZero = (result.length() > 0 ? true : false);

        int lastDiscardedBit = (int) (mantissa & 1L);
        mantissa >>= 1;
        int tailBitInMantissa = (int) (mantissa & 1L);
        
        if (lastDiscardedBit == 1 && (moreThanZero || tailBitInMantissa == 1)) {
            int oldLength = countBitsLength(mantissa);
            mantissa += 1L;
            int newLength = countBitsLength(mantissa);
            
            //Rounds up to exponent when whole bits of mantissa are one-bits.
            if (oldLength >= MANTISSA_WIDTH && newLength > oldLength) {
                checkedAddExponent(1);
            }
        }
    
private voidsetInfinite()

        exponent = MAX_EXPONENT;
        mantissa = 0;
    
private voidsetZero()

        exponent = 0;
        mantissa = 0;