Beispiel #1
0
        private static long GrabLongs(int radix, ReadOnlySpan <char> s, ref int i, bool isUnsigned)
        {
            ulong result = 0;
            ulong maxVal;

            // Allow all non-decimal numbers to set the sign bit.
            if (radix == 10 && !isUnsigned)
            {
                maxVal = 0x7FFFFFFFFFFFFFFF / 10;

                // Read all of the digits and convert to a number
                while (i < s.Length && IsDigit(s[i], radix, out int value))
                {
                    // Check for overflows - this is sufficient & correct.
                    if (result > maxVal || ((long)result) < 0)
                    {
                        Number.ThrowOverflowException(TypeCode.Int64);
                    }

                    result = result * (ulong)radix + (ulong)value;
                    i++;
                }

                if ((long)result < 0 && result != 0x8000000000000000)
                {
                    Number.ThrowOverflowException(TypeCode.Int64);
                }
            }
            else
            {
                Debug.Assert(radix == 2 || radix == 8 || radix == 10 || radix == 16);
                maxVal =
                    radix == 10 ? 0xffffffffffffffff / 10 :
                    radix == 16 ? 0xffffffffffffffff / 16 :
                    radix == 8 ? 0xffffffffffffffff / 8 :
                    0xffffffffffffffff / 2;

                // Read all of the digits and convert to a number
                while (i < s.Length && IsDigit(s[i], radix, out int value))
                {
                    // Check for overflows - this is sufficient & correct.
                    if (result > maxVal)
                    {
                        Number.ThrowOverflowException(TypeCode.UInt64);
                    }

                    ulong temp = result * (ulong)radix + (ulong)value;

                    if (temp < result) // this means overflow as well
                    {
                        Number.ThrowOverflowException(TypeCode.UInt64);
                    }

                    result = temp;
                    i++;
                }
            }

            return((long)result);
        }
Beispiel #2
0
        private static ushort Parse(ReadOnlySpan <char> s, NumberStyles style, NumberFormatInfo info)
        {
            Number.ParsingStatus status = Number.TryParseUInt32(s, style, info, out uint i);
            if (status != Number.ParsingStatus.OK)
            {
                Number.ThrowOverflowOrFormatException(status, TypeCode.UInt16);
            }

            if (i > MaxValue)
            {
                Number.ThrowOverflowException(TypeCode.UInt16);
            }
            return((ushort)i);
        }
Beispiel #3
0
        private static sbyte Parse(ReadOnlySpan <char> s, NumberStyles style, NumberFormatInfo info)
        {
            Number.ParsingStatus status = Number.TryParseInt32(s, style, info, out int i);
            if (status != Number.ParsingStatus.OK)
            {
                Number.ThrowOverflowOrFormatException(status, TypeCode.SByte);
            }

            // For hex number styles AllowHexSpecifier >> 2 == 0x80 and cancels out MinValue so the check is effectively: (uint)i > byte.MaxValue
            // For integer styles it's zero and the effective check is (uint)(i - MinValue) > byte.MaxValue
            if ((uint)(i - MinValue - ((int)(style & NumberStyles.AllowHexSpecifier) >> 2)) > byte.MaxValue)
            {
                Number.ThrowOverflowException(TypeCode.SByte);
            }
            return((sbyte)i);
        }
Beispiel #4
0
        public static long StringToLong(ReadOnlySpan <char> s, int radix, int flags, ref int currPos)
        {
            int i = currPos;

            // Do some radix checking.
            // A radix of -1 says to use whatever base is spec'd on the number.
            // Parse in Base10 until we figure out what the base actually is.
            int r = (-1 == radix) ? 10 : radix;

            if (r != 2 && r != 10 && r != 8 && r != 16)
            {
                throw new ArgumentException(SR.Arg_InvalidBase, nameof(radix));
            }

            int length = s.Length;

            if (i < 0 || i >= length)
            {
                throw new ArgumentOutOfRangeException(SR.ArgumentOutOfRange_IndexMustBeLess);
            }

            // Get rid of the whitespace and then check that we've still got some digits to parse.
            if (((flags & IsTight) == 0) && ((flags & NoSpace) == 0))
            {
                EatWhiteSpace(s, ref i);
                if (i == length)
                {
                    throw new FormatException(SR.Format_EmptyInputString);
                }
            }

            // Check for a sign
            int sign = 1;

            if (s[i] == '-')
            {
                if (r != 10)
                {
                    throw new ArgumentException(SR.Arg_CannotHaveNegativeValue);
                }

                if ((flags & TreatAsUnsigned) != 0)
                {
                    throw new OverflowException(SR.Overflow_NegativeUnsigned);
                }

                sign = -1;
                i++;
            }
            else if (s[i] == '+')
            {
                i++;
            }

            if ((radix == -1 || radix == 16) && (i + 1 < length) && s[i] == '0')
            {
                if (s[i + 1] == 'x' || s[i + 1] == 'X')
                {
                    r  = 16;
                    i += 2;
                }
            }

            int  grabNumbersStart = i;
            long result           = GrabLongs(r, s, ref i, (flags & TreatAsUnsigned) != 0);

            // Check if they passed us a string with no parsable digits.
            if (i == grabNumbersStart)
            {
                throw new FormatException(SR.Format_NoParsibleDigits);
            }

            if ((flags & IsTight) != 0)
            {
                // If we've got effluvia left at the end of the string, complain.
                if (i < length)
                {
                    throw new FormatException(SR.Format_ExtraJunkAtEnd);
                }
            }

            // Put the current index back into the correct place.
            currPos = i;

            // Return the value properly signed.
            if ((ulong)result == 0x8000000000000000 && sign == 1 && r == 10 && ((flags & TreatAsUnsigned) == 0))
            {
                Number.ThrowOverflowException(TypeCode.Int64);
            }

            if (r == 10)
            {
                result *= sign;
            }

            return(result);
        }