// 
// Decompiled by Procyon v0.6.0
// 

package ch.randelshofer.fastdoubleparser;

abstract class AbstractJsonFloatingPointBitsFromByteArray extends AbstractFloatValueParser
{
    public final long parseNumber(final byte[] str, final int offset, final int length) {
        final int endIndex = AbstractNumberParser.checkBounds(str.length, offset, length);
        int index = offset;
        byte ch = AbstractNumberParser.charAt(str, index, endIndex);
        final boolean isNegative = ch == 45;
        if (isNegative) {
            ch = AbstractNumberParser.charAt(str, ++index, endIndex);
            if (ch == 0) {
                return 9221120237041090561L;
            }
        }
        final boolean hasLeadingZero = ch == 48;
        if (hasLeadingZero) {
            ch = AbstractNumberParser.charAt(str, ++index, endIndex);
            if (ch == 48) {
                return 9221120237041090561L;
            }
        }
        long significand = 0L;
        final int significandStartIndex = index;
        int integerDigitCount = -1;
        final int swarLimit = Math.min(endIndex - 4, 1073741824);
        boolean illegal = false;
        while (index < endIndex) {
            ch = str[index];
            final int digit = (char)(ch - 48);
            if (digit < 10) {
                significand = 10L * significand + digit;
            }
            else {
                if (ch != 46) {
                    break;
                }
                illegal |= (integerDigitCount >= 0);
                integerDigitCount = index - significandStartIndex;
                while (index < swarLimit) {
                    final int digits = FastDoubleSwar.tryToParseFourDigits(str, index + 1);
                    if (digits < 0) {
                        break;
                    }
                    significand = 10000L * significand + digits;
                    index += 4;
                }
            }
            ++index;
        }
        final int significandEndIndex = index;
        int digitCount;
        int exponent;
        if (integerDigitCount < 0) {
            digitCount = (integerDigitCount = index - significandStartIndex);
            exponent = 0;
        }
        else {
            digitCount = index - significandStartIndex - 1;
            exponent = integerDigitCount - digitCount;
        }
        int expNumber = 0;
        if ((ch | 0x20) == 0x65) {
            ch = AbstractNumberParser.charAt(str, ++index, endIndex);
            final boolean isExponentNegative = ch == 45;
            if (isExponentNegative || ch == 43) {
                ch = AbstractNumberParser.charAt(str, ++index, endIndex);
            }
            int digit2 = (char)(ch - 48);
            illegal |= (digit2 >= 10);
            do {
                if (expNumber < 1024) {
                    expNumber = 10 * expNumber + digit2;
                }
                ch = AbstractNumberParser.charAt(str, ++index, endIndex);
                digit2 = (char)(ch - 48);
            } while (digit2 < 10);
            if (isExponentNegative) {
                expNumber = -expNumber;
            }
            exponent += expNumber;
        }
        if (illegal || index < endIndex || (!hasLeadingZero && digitCount == 0)) {
            return 9221120237041090561L;
        }
        boolean isSignificandTruncated;
        int exponentOfTruncatedSignificand;
        if (digitCount > 19) {
            int truncatedDigitCount = 0;
            significand = 0L;
            for (index = significandStartIndex; index < significandEndIndex; ++index) {
                ch = str[index];
                final int digit3 = (char)(ch - 48);
                if (digit3 < 10) {
                    if (Long.compareUnsigned(significand, 1000000000000000000L) >= 0) {
                        break;
                    }
                    significand = 10L * significand + digit3;
                    ++truncatedDigitCount;
                }
            }
            isSignificandTruncated = (index < significandEndIndex);
            exponentOfTruncatedSignificand = integerDigitCount - truncatedDigitCount + expNumber;
        }
        else {
            isSignificandTruncated = false;
            exponentOfTruncatedSignificand = 0;
        }
        return this.valueOfFloatLiteral(str, offset, endIndex, isNegative, significand, exponent, isSignificandTruncated, exponentOfTruncatedSignificand);
    }
    
    abstract long valueOfFloatLiteral(final byte[] p0, final int p1, final int p2, final boolean p3, final long p4, final int p5, final boolean p6, final int p7);
}
