/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.harmony.luni.util;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/*
 * Parses hex string to a single or double precision floating point number.
 */
final class HexStringParser {

    private static final int DOUBLE_EXPONENT_WIDTH = 11;

    private static final int DOUBLE_MANTISSA_WIDTH = 52;

    private static final int FLOAT_EXPONENT_WIDTH = 8;

    private static final int FLOAT_MANTISSA_WIDTH = 23;
    
    private static final int HEX_RADIX = 16;
    
    private static final int MAX_SIGNIFICANT_LENGTH = 15;

    private static final String HEX_SIGNIFICANT = "0[xX](\\p{XDigit}+\\.?|\\p{XDigit}*\\.\\p{XDigit}+)"; //$NON-NLS-1$

    private static final String BINARY_EXPONENT = "[pP]([+-]?\\d+)"; //$NON-NLS-1$

    private static final String FLOAT_TYPE_SUFFIX = "[fFdD]?"; //$NON-NLS-1$

    private static final String HEX_PATTERN = "[\\x00-\\x20]*([+-]?)" + HEX_SIGNIFICANT //$NON-NLS-1$
            + BINARY_EXPONENT + FLOAT_TYPE_SUFFIX + "[\\x00-\\x20]*"; //$NON-NLS-1$

    private static final Pattern PATTERN = Pattern.compile(HEX_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=""; //$NON-NLS-1$

    public HexStringParser(int exponent_width, int mantissa_width) {
        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);
    }

    /*
     * Parses the hex string to a double number.
     */
    public static double parseDouble(String hexString) {
        HexStringParser parser = new HexStringParser(DOUBLE_EXPONENT_WIDTH,
                DOUBLE_MANTISSA_WIDTH);
        long result = parser.parse(hexString);
        return Double.longBitsToDouble(result);
    }

    /*
     * Parses the hex string to a float number.
     */
    public static float parseFloat(String hexString) {
        HexStringParser parser = new HexStringParser(FLOAT_EXPONENT_WIDTH,
                FLOAT_MANTISSA_WIDTH);
        int result = (int) parser.parse(hexString);
        return Float.intBitsToFloat(result);
    }

    private long parse(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;
    }

    /*
     * Analyzes the hex string and extracts the sign and digit segments.
     */
    private static String[] getSegmentsFromHexString(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;
    }

    /*
     * Parses the sign field.
     */
    private void parseHexSign(String signStr) {
        this.sign = signStr.equals("-") ? 1 : 0; //$NON-NLS-1$
    }

    /*
     * Parses the exponent field.
     */
    private void parseExponent(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;
        }
    }
   
    /*
     * Parses the mantissa field.
     */
    private void parseMantissa(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 void setInfinite() {
        exponent = MAX_EXPONENT;
        mantissa = 0;
    }

    private void setZero() {
        exponent = 0;
        mantissa = 0;
    }
    
    /*
     * Sets the exponent variable to Long.MAX_VALUE or -Long.MAX_VALUE if
     * overflow or underflow happens.
     */
    private void checkedAddExponent(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 void processNormalNumber(){
        int desiredWidth = MANTISSA_WIDTH + 2;
        fitMantissaInDesiredWidth(desiredWidth);
        round();
        mantissa = mantissa & MANTISSA_MASK;
    }
    
    private void processSubNormalNumber(){
        int desiredWidth = MANTISSA_WIDTH + 1;
        desiredWidth += (int)exponent;//lends bit from mantissa to exponent
        exponent = 0;
        fitMantissaInDesiredWidth(desiredWidth);
        round();
        mantissa = mantissa & MANTISSA_MASK;
    }
    
    /*
     * Adjusts the mantissa to desired width for further analysis.
     */
    private void fitMantissaInDesiredWidth(int desiredWidth){
        int bitLength = countBitsLength(mantissa);
        if (bitLength > desiredWidth) {
            discardTrailingBits(bitLength - desiredWidth);
        } else {
            mantissa <<= (desiredWidth - bitLength);
        }
    }
    
    /*
     * Stores the discarded bits to abandonedNumber.
     */
    private void discardTrailingBits(long num) {
        long mask = ~(-1L << num);
        abandonedNumber += (mantissa & mask);
        mantissa >>= num;
    }

    /*
     * The value is rounded up or down to the nearest infinitely precise result.
     * If the value is exactly halfway between two infinitely precise results,
     * then it should be rounded up to the nearest infinitely precise even.
     */
    private void round() {
        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);
            }
        }
    }

    /*
     * Returns the normalized significand after removing the leading zeros.
     */
    private String getNormalizedSignificand(String strIntegerPart, 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;
    }

    /*
     * Calculates the offset between the normalized number and unnormalized
     * number. In a normalized representation, significand is represented by the
     * characters "0x1." followed by a lowercase hexadecimal representation of
     * the rest of the significand as a fraction.
     */
    private int getOffset(String strIntegerPart, 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 int countBitsLength(long value) {
        int leadingZeros = Long.numberOfLeadingZeros(value);
        return Long.SIZE - leadingZeros;
    }
}
