/// <summary> /// Determines whether the beginning of the <paramref name="span"/> matches the specified <paramref name="value"/> when compared using the specified <paramref name="comparisonType"/> option. /// </summary> /// <param name="span">The source span.</param> /// <param name="value">The sequence to compare to the beginning of the source span.</param> /// <param name="comparisonType">One of the enumeration values that determines how the <paramref name="span"/> and <paramref name="value"/> are compared.</param> public static bool StartsWith(this ReadOnlySpan <char> span, ReadOnlySpan <char> value, StringComparison comparisonType) { string.CheckStringComparison(comparisonType); switch (comparisonType) { case StringComparison.CurrentCulture: case StringComparison.CurrentCultureIgnoreCase: return(CultureInfo.CurrentCulture.CompareInfo.IsPrefix(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType))); case StringComparison.InvariantCulture: case StringComparison.InvariantCultureIgnoreCase: return(CompareInfo.Invariant.IsPrefix(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType))); case StringComparison.Ordinal: return(span.StartsWith(value)); default: Debug.Assert(comparisonType == StringComparison.OrdinalIgnoreCase); return(span.StartsWithOrdinalIgnoreCase(value)); } }
/// <summary>Parses long inputs limited to styles that make up NumberStyles.Integer.</summary> private static bool TryParseInt64IntegerStyle(ReadOnlySpan <char> source, NumberStyles styles, NumberFormatInfo info, out long result, out bool overflow) { overflow = false; Debug.Assert((styles & ~NumberStyles.Integer) == 0); if ((uint)source.Length < 1) { goto FalseExit; } int sign = 1; int index = 0; int num = source[0]; // Skip past any whitespace at the beginning. if ((styles & NumberStyles.AllowLeadingWhite) != 0 && IsWhite(num)) { index++; while (true) { if ((uint)index >= (uint)source.Length) { goto FalseExit; } num = source[index]; if (!IsWhite(num)) { break; } index++; } } // Parse leading sign. if ((styles & NumberStyles.AllowLeadingSign) != 0) { string positiveSign = info.PositiveSign, negativeSign = info.NegativeSign; if (positiveSign == "+" && negativeSign == "-") { if (num == '-') { sign = -1; index++; if ((uint)index >= (uint)source.Length) { goto FalseExit; } num = source[index]; } else if (num == '+') { index++; if ((uint)index >= (uint)source.Length) { goto FalseExit; } num = source[index]; } } else { source = source.Slice(index); index = 0; if (!string.IsNullOrEmpty(positiveSign) && source.StartsWith(positiveSign)) { index += positiveSign.Length; if ((uint)index >= (uint)source.Length) { goto FalseExit; } num = source[index]; } else if (!string.IsNullOrEmpty(negativeSign) && source.StartsWith(negativeSign)) { sign = -1; index += negativeSign.Length; if ((uint)index >= (uint)source.Length) { goto FalseExit; } num = source[index]; } } } long answer = 0; if (IsDigit(num)) { // Skip past leading zeros. if (num == '0') { do { index++; if ((uint)index >= (uint)source.Length) { goto DoneAtEnd; } num = source[index]; } while (num == '0'); if (!IsDigit(num)) { goto DoneButRemainingChars; } } // Parse most digits, up to the potential for overflow, which can't // happen until after 18 digits. answer = num - '0'; // first digit index++; for (int i = 0; i < 17; i++) // next 17 digits can't overflow { if ((uint)index >= (uint)source.Length) { goto DoneAtEnd; } num = source[index]; if (!IsDigit(num)) { goto DoneButRemainingChars; } index++; answer = 10 * answer + num - '0'; } // Potential overflow now processing the 19th digit. if ((uint)index >= (uint)source.Length) { goto DoneAtEnd; } num = source[index]; if (!IsDigit(num)) { goto DoneButRemainingChars; } index++; if (answer > long.MaxValue / 10) { overflow = true; goto FalseExit; } answer = answer * 10 + num - '0'; if ((ulong)answer > (ulong)long.MaxValue + (ulong)((-1 * sign + 1) / 2)) // + sign => 0, - sign => 1 { overflow = true; goto FalseExit; } if ((uint)index >= (uint)source.Length) { goto DoneAtEnd; } num = source[index]; if (!IsDigit(num)) { goto DoneButRemainingChars; } // Anything more than 19 digits is definitely overflow. overflow = true; } FalseExit: // parsing failed result = 0; return(false); DoneAtEnd: // we've successfully parsed up to the end of the span result = answer * sign; return(true); DoneButRemainingChars: // we've successfully parsed, but there are still remaining characters in the span // Skip past trailing whitespace, then past trailing zeros, and // if anything else remains, fail. if (IsWhite(num)) { if ((styles & NumberStyles.AllowTrailingWhite) == 0) { goto FalseExit; } for (index++; index < source.Length; index++) { if (!IsWhite(source[index])) { break; } } if ((uint)index >= (uint)source.Length) { goto DoneAtEnd; } } if (!TrailingZeros(source, index)) { goto FalseExit; } goto DoneAtEnd; }