/// <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));
            }
        }
示例#2
0
        /// <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;
        }