/// <summary>
        /// Compares the specified <paramref name="span"/> and <paramref name="other"/> using the specified <paramref name="comparisonType"/>,
        /// and returns an integer that indicates their relative position in the sort order.
        /// <param name="span">The source span.</param>
        /// <param name="other">The value to compare with the source span.</param>
        /// <param name="comparisonType">One of the enumeration values that determines how the <paramref name="span"/> and <paramref name="other"/> are compared.</param>
        /// </summary>
        public static int CompareTo(this ReadOnlySpan <char> span, ReadOnlySpan <char> other, StringComparison comparisonType)
        {
            string.CheckStringComparison(comparisonType);

            switch (comparisonType)
            {
            case StringComparison.CurrentCulture:
            case StringComparison.CurrentCultureIgnoreCase:
                return(CultureInfo.CurrentCulture.CompareInfo.Compare(span, other, string.GetCaseCompareOfComparisonCulture(comparisonType)));

            case StringComparison.InvariantCulture:
            case StringComparison.InvariantCultureIgnoreCase:
                return(CompareInfo.Invariant.Compare(span, other, string.GetCaseCompareOfComparisonCulture(comparisonType)));

            case StringComparison.Ordinal:
                if (span.Length == 0 || other.Length == 0)
                {
                    return(span.Length - other.Length);
                }
                return(string.CompareOrdinal(span, other));

            default:
                Debug.Assert(comparisonType == StringComparison.OrdinalIgnoreCase);
                return(Ordinal.CompareStringIgnoreCase(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(other), other.Length));
            }
        }
Exemple #2
0
        public static int Compare(string?strA, int indexA, string?strB, int indexB, int length, StringComparison comparisonType)
        {
            CheckStringComparison(comparisonType);

            if (strA == null || strB == null)
            {
                if (object.ReferenceEquals(strA, strB))
                {
                    // They're both null
                    return(0);
                }

                return(strA == null ? -1 : 1);
            }

            if (length < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NegativeLength);
            }

            if (indexA < 0 || indexB < 0)
            {
                string paramName = indexA < 0 ? nameof(indexA) : nameof(indexB);
                throw new ArgumentOutOfRangeException(paramName, SR.ArgumentOutOfRange_Index);
            }

            if (strA.Length - indexA < 0 || strB.Length - indexB < 0)
            {
                string paramName = strA.Length - indexA < 0 ? nameof(indexA) : nameof(indexB);
                throw new ArgumentOutOfRangeException(paramName, SR.ArgumentOutOfRange_Index);
            }

            if (length == 0 || (object.ReferenceEquals(strA, strB) && indexA == indexB))
            {
                return(0);
            }

            int lengthA = Math.Min(length, strA.Length - indexA);
            int lengthB = Math.Min(length, strB.Length - indexB);

            switch (comparisonType)
            {
            case StringComparison.CurrentCulture:
            case StringComparison.CurrentCultureIgnoreCase:
                return(CultureInfo.CurrentCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, GetCaseCompareOfComparisonCulture(comparisonType)));

            case StringComparison.InvariantCulture:
            case StringComparison.InvariantCultureIgnoreCase:
                return(CompareInfo.Invariant.Compare(strA, indexA, lengthA, strB, indexB, lengthB, GetCaseCompareOfComparisonCulture(comparisonType)));

            case StringComparison.Ordinal:
                return(CompareOrdinalHelper(strA, indexA, lengthA, strB, indexB, lengthB));

            default:
                Debug.Assert(comparisonType == StringComparison.OrdinalIgnoreCase);     // CheckStringComparison validated these earlier
                return(Ordinal.CompareStringIgnoreCase(ref Unsafe.Add(ref strA.GetRawStringData(), indexA), lengthA, ref Unsafe.Add(ref strB.GetRawStringData(), indexB), lengthB));
            }
        }
Exemple #3
0
        // Provides a more flexible function for string comparison. See StringComparison
        // for meaning of different comparisonType.
        public static int Compare(string?strA, string?strB, StringComparison comparisonType)
        {
            if (object.ReferenceEquals(strA, strB))
            {
                CheckStringComparison(comparisonType);
                return(0);
            }

            // They can't both be null at this point.
            if (strA == null)
            {
                CheckStringComparison(comparisonType);
                return(-1);
            }
            if (strB == null)
            {
                CheckStringComparison(comparisonType);
                return(1);
            }

            switch (comparisonType)
            {
            case StringComparison.CurrentCulture:
            case StringComparison.CurrentCultureIgnoreCase:
                return(CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, GetCaseCompareOfComparisonCulture(comparisonType)));

            case StringComparison.InvariantCulture:
            case StringComparison.InvariantCultureIgnoreCase:
                return(CompareInfo.Invariant.Compare(strA, strB, GetCaseCompareOfComparisonCulture(comparisonType)));

            case StringComparison.Ordinal:
                // Most common case: first character is different.
                // Returns false for empty strings.
                if (strA._firstChar != strB._firstChar)
                {
                    return(strA._firstChar - strB._firstChar);
                }

                return(CompareOrdinalHelper(strA, strB));

            case StringComparison.OrdinalIgnoreCase:
                return(Ordinal.CompareStringIgnoreCase(ref strA.GetRawStringData(), strA.Length, ref strB.GetRawStringData(), strB.Length));

            default:
                throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
            }
        }
Exemple #4
0
        public bool EndsWith(string value, StringComparison comparisonType)
        {
            if (value is null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            if ((object)this == (object)value)
            {
                CheckStringComparison(comparisonType);
                return(true);
            }

            if (value.Length == 0)
            {
                CheckStringComparison(comparisonType);
                return(true);
            }

            switch (comparisonType)
            {
            case StringComparison.CurrentCulture:
            case StringComparison.CurrentCultureIgnoreCase:
                return(CultureInfo.CurrentCulture.CompareInfo.IsSuffix(this, value, GetCaseCompareOfComparisonCulture(comparisonType)));

            case StringComparison.InvariantCulture:
            case StringComparison.InvariantCultureIgnoreCase:
                return(CompareInfo.Invariant.IsSuffix(this, value, GetCaseCompareOfComparisonCulture(comparisonType)));

            case StringComparison.Ordinal:
                int offset = this.Length - value.Length;
                return((uint)offset <= (uint)this.Length && this.AsSpan(offset).SequenceEqual(value));

            case StringComparison.OrdinalIgnoreCase:
                return(this.Length < value.Length ?
                       false :
                       (Ordinal.CompareStringIgnoreCase(ref Unsafe.Add(ref this.GetRawStringData(), this.Length - value.Length), value.Length, ref value.GetRawStringData(), value.Length) == 0));

            default:
                throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
            }
        }