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); }
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); }
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); }
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); }