internal static bool TryParseBigInteger(string value, NumberStyles style, NumberFormatInfo info, out BigInteger result)
        {
            result = Zero;
            ArgumentException e;

            if (!TryValidateParseStyleInteger(style, out e))
            {
                throw e; // TryParse still throws ArgumentException on invalid NumberStyles
            }
            if (value == null)
            {
                return(false);
            }
            var number = BigNumberBuffer.Create();

            if (!ParseNumber(new StringProcessor(value), style, number, info))
            {
                return(false);
            }
            if ((style & NumberStyles.AllowHexSpecifier) != 0)
            {
                if (!HexNumberToBigInteger(number, ref result))
                {
                    return(false);
                }
            }
            else
            {
                if (!NumberToBigInteger(number, out result))
                {
                    return(false);
                }
            }
            return(true);
        }
        private static bool HexNumberToBigInteger(BigNumberBuffer number, ref BigInteger value)
        {
            if (number.Digits == null || number.Digits.Length == 0)
            {
                return(false);
            }

            var len  = number.Digits.Length; // there is no trailing '\0'
            var bits = new byte[(len / 2) + (len % 2)];

            var shift      = false;
            var isNegative = false;
            var bitIndex   = 0;

            // parse the string into a little-endian two's complement byte array
            // string value     : O F E B 7 \0
            // string index (i) : 0 1 2 3 4 5 <--
            // byte[] (bitIndex): 2 1 1 0 0 <--
            //
            for (var i = len - 1; i > -1; i--)
            {
                var c = number.Digits[i];

                byte b;
                if (c >= '0' && c <= '9')
                {
                    b = (byte)(c - '0');
                }
                else if (c >= 'A' && c <= 'F')
                {
                    b = (byte)((c - 'A') + 10);
                }
                else
                {
                    Contract.Assert(c >= 'a' && c <= 'f');
                    b = (byte)((c - 'a') + 10);
                }
                isNegative |= (i == 0 && (b & 0x08) == 0x08);

                if (shift)
                {
                    bits[bitIndex] = (byte)(bits[bitIndex] | (b << 4));
                    bitIndex++;
                }
                else
                {
                    bits[bitIndex] = isNegative ? (byte)(b | 0xF0) : (b);
                }
                shift = !shift;
            }

            value = new BigInteger(bits);
            return(true);
        }
        private static bool NumberToBigInteger(BigNumberBuffer number, out BigInteger value)
        {
            var cur = 0;

            if (number.Scale > number.Digits.Length)
            {
                var i = number.Digits.Length;
                value = 0;
                while (--i >= 0)
                {
                    value *= 10;
                    value += (number.Digits[cur++] - '0');
                }
                var adjust = number.Scale - number.Digits.Length;
                while (adjust > 9)
                {
                    value  *= 1000000000;
                    adjust -= 9;
                }
                while (adjust > 0)
                {
                    value *= 10;
                    adjust--;
                }
            }
            else
            {
                var i = number.Scale;
                value = 0;
                while (--i >= 0)
                {
                    value *= 10;
                    value += (number.Digits[cur++] - '0');
                }
                for (; cur < number.Digits.Length - 1; cur++)
                {
                    if (number.Digits[cur++] != '0')
                    {
                        return(false);
                    }
                }
            }
            if (number.Negative)
            {
                value = -value;
            }
            return(true);
        }
        internal static bool ParseNumber(StringProcessor reader, NumberStyles options, BigNumberBuffer number, NumberFormatInfo info)
        {
            // Percent intentionally not supported
            // After testig with .NET the patterns are ignored... all patterns are welcome

            var currencySymbol         = info.CurrencySymbol;
            var numberGroupSeparator   = info.NumberGroupSeparator;
            var currencyGroupSeparator = info.CurrencyGroupSeparator;
            var positiveSign           = info.PositiveSign;
            var negativeSign           = info.NegativeSign;

            if ((options & NumberStyles.AllowHexSpecifier) != NumberStyles.None)
            {
                var allowLeadingWhite  = (options & NumberStyles.AllowLeadingWhite) != NumberStyles.None;
                var allowTrailingWhite = (options & NumberStyles.AllowTrailingWhite) != NumberStyles.None;

                /*
                 * // Assume validated
                 * if (
                 *  (options & NumberStyles.AllowCurrencySymbol) != NumberStyles.None
                 || (options & NumberStyles.AllowLeadingSign) != NumberStyles.None
                 || (options & NumberStyles.AllowParentheses) != NumberStyles.None
                 || (options & NumberStyles.AllowThousands) != NumberStyles.None
                 || (options & NumberStyles.AllowExponent) != NumberStyles.None
                 || (options & NumberStyles.AllowTrailingSign) != NumberStyles.None
                 || )
                 ||{
                 || return false;
                 ||}*/
                number.Negative = false;
                if (allowLeadingWhite)
                {
                    reader.SkipWhile(CharHelper.IsClassicWhitespace);
                }
                while (true)
                {
                    var input =
                        reader.ReadWhile(new[]
                    {
                        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C',
                        'D', 'E', 'F'
                    });
                    if (input == string.Empty)
                    {
                        break;
                    }
                    number.Scale += input.Length;
                    number.Digits.Append(input.ToUpperInvariant());
                }
                if (allowTrailingWhite)
                {
                    reader.SkipWhile(CharHelper.IsClassicWhitespace);
                }
                return(reader.EndOfString);
            }
            else
            {
                var allowCurrencySymbol = (options & NumberStyles.AllowCurrencySymbol) != NumberStyles.None;
                var allowLeadingWhite   = (options & NumberStyles.AllowLeadingWhite) != NumberStyles.None;
                var allowLeadingSign    = (options & NumberStyles.AllowLeadingSign) != NumberStyles.None;
                var allowParentheses    = (options & NumberStyles.AllowParentheses) != NumberStyles.None;
                var allowThousands      = (options & NumberStyles.AllowThousands) != NumberStyles.None;
                var allowExponent       = (options & NumberStyles.AllowExponent) != NumberStyles.None;
                var allowTrailingWhite  = (options & NumberStyles.AllowTrailingWhite) != NumberStyles.None;
                var allowTrailingSign   = (options & NumberStyles.AllowTrailingSign) != NumberStyles.None;
                var allowDecimalPoint   = (options & NumberStyles.AllowDecimalPoint) != NumberStyles.None;

                var isCurrency = false;
                number.Negative = false;
                var waitingParentheses = false;
                var positive           = false;
                // [ws][$][sign][digits,]digits[E[sign]exponential_digits][ws]
                if (allowLeadingWhite)
                {
                    reader.SkipWhile(CharHelper.IsClassicWhitespace);
                }
                // [$][sign][digits,]digits[E[sign]exponential_digits][ws]
                if (allowCurrencySymbol && reader.Read(currencySymbol))
                {
                    isCurrency = true;
                    reader.SkipWhile(CharHelper.IsClassicWhitespace);
                }
                // [sign][digits,]digits[E[sign]exponential_digits][ws
                if (allowLeadingSign)
                {
                    number.Negative |= reader.Read(negativeSign);
                    positive        |= reader.Read(positiveSign);
                }
                if (!number.Negative && allowParentheses && reader.Read('('))
                {
                    // Testing on .NET show that $(n) is allowed, even tho there is no CurrencyNegativePattern for it
                    number.Negative    = true;
                    waitingParentheses = true;
                }
                // ---
                if (!isCurrency && allowCurrencySymbol && reader.Read(currencySymbol)) // If the currency symbol is after the negative sign
                {
                    isCurrency = true;
                    reader.SkipWhile(CharHelper.IsClassicWhitespace);
                }
                // [digits,]digits[E[sign]exponential_digits][ws]
                var failure      = true;
                var digits       = new[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
                var decimalFound = false;
                while (true)
                {
                    var input = reader.ReadWhile(digits);
                    if (input == string.Empty)
                    {
                        if (allowDecimalPoint && !decimalFound)
                        {
                            if (reader.Read(info.CurrencyDecimalSeparator))
                            {
                                decimalFound = true;
                                continue;
                            }
                            if (reader.Read(info.NumberDecimalSeparator))
                            {
                                if (isCurrency)
                                {
                                    return(false);
                                }
                                decimalFound = true;
                                continue;
                            }
                        }
                        break;
                    }
                    failure = false;
                    if (!decimalFound)
                    {
                        number.Scale += input.Length;
                    }
                    number.Digits.Append(input);
                    if (allowThousands)
                    {
                        // Testing on .NET show that combining currency and number group separators is allowed
                        // But not if the currency symbol has already appeared
                        reader.SkipWhile(currencyGroupSeparator);
                        if (!isCurrency)
                        {
                            reader.SkipWhile(numberGroupSeparator);
                        }
                    }
                }
                if (failure)
                {
                    return(false);
                }
                // [E[sign]exponential_digits][ws]
                if (allowExponent && (reader.Read('E') || reader.Read('e')))
                {
                    // [sign]exponential_digits
                    // Testing on .NET show that no pattern is used here, also no parentheses nor group separators supported
                    // The exponent can be big - but anything beyond 9999 is ignored
                    var exponentNegative = reader.Read(negativeSign);
                    if (!exponentNegative)
                    {
                        reader.Read(positiveSign);
                    }
                    var input             = reader.ReadWhile(digits);
                    var exponentMagnitude = int.Parse(input, CultureInfo.InvariantCulture);
                    number.Scale += (exponentNegative ? -1 : 1) * (input.Length > 4 ? 9999 : exponentMagnitude);
                    if (number.Scale < 0)
                    {
                        return(false);
                    }
                }
                // ---
                if (allowTrailingWhite)
                {
                    reader.SkipWhile(CharHelper.IsClassicWhitespace);
                }
                if (!isCurrency && allowCurrencySymbol && reader.Read(currencySymbol))
                {
                    isCurrency = true;
                }
                // ---
                if (!number.Negative && !positive && allowTrailingSign)
                {
                    number.Negative |= reader.Read(negativeSign);
                    positive        |= reader.Read(positiveSign);
                }
                if (waitingParentheses && !reader.Read(')'))
                {
                    return(false);
                }
                // ---
                if (!isCurrency && allowCurrencySymbol && reader.Read(currencySymbol)) // If the currency symbol is after the negative sign
                {
                    isCurrency = true;                                                 // For completeness sake
                }
                // [ws]
                if (allowTrailingWhite)
                {
                    reader.SkipWhile(CharHelper.IsClassicWhitespace);
                }
                return(reader.EndOfString);
            }
        }