Closed
Description
As we look to support more efficient parsing/formatting/usage of ReadOnlySpan<char>
as slices of System.Strings, we're planning to add a variety of APIs across corefx that operate with ReadOnlySpan<char>
(https://github.com/dotnet/corefx/issues/21281). But for such APIs to be truly useful, and for ReadOnlySpan<char>
to be generally helpful as a string-like type, we need a set of extension methods on ReadOnlySpan<char>
that mirror the corresponding operations on string, e.g. Equals with various kinds of string comparisons, Trim, Replace, etc. We need to define, implement, test, and ship a core set of these (more can of course be added in the future), e.g.
Edit by @ahsonkhan - Updated APIs:
// All these do ordinal comparisons, and hence do not rely on StringComparison, and can live in System.Memory.dll
public static class MemoryExtensions
{
// If we decide to add overloads to Trim in the future that are non-ordinal and take StringComparison
// (similar to https://github.com/dotnet/corefx/issues/1244), they will be .NET Core specific.
public static ReadOnlySpan<char> Trim(this ReadOnlySpan<char> span);
public static ReadOnlySpan<char> Trim(this ReadOnlySpan<char> span, char trimChar);
public static ReadOnlySpan<char> Trim(this ReadOnlySpan<char> span, ReadOnlySpan<char> trimChars);
public static ReadOnlySpan<char> TrimStart(this ReadOnlySpan<char> span);
public static ReadOnlySpan<char> TrimStart(this ReadOnlySpan<char> span, char trimChar);
public static ReadOnlySpan<char> TrimStart(this ReadOnlySpan<char> span, ReadOnlySpan<char> trimChars);
public static ReadOnlySpan<char> TrimEnd(this ReadOnlySpan<char> span);
public static ReadOnlySpan<char> TrimEnd(this ReadOnlySpan<char> span, char trimChar);
public static ReadOnlySpan<char> TrimEnd(this ReadOnlySpan<char> span, ReadOnlySpan<char> trimChars);
public static bool IsWhiteSpace(this ReadOnlySpan<char> span);
public static bool Remove(this ReadOnlySpan<char> source, int startIndex, int count, Span<char> destination);
// Does exactly what string does today, i.e. ordinal, case-sensitive, culture-insensitive comparison
public static bool Replace(this ReadOnlySpan<char> source, ReadOnlySpan<char> oldValue, ReadOnlySpan<char> newValue, Span<char> destination, out int bytesWritten);
// To me, these are complementary to the Trim APIs and hence we should add them.
public static bool PadLeft(this ReadOnlySpan<char> source, int totalWidth, Span<char> destination);
public static bool PadLeft(this ReadOnlySpan<char> source, int totalWidth, Span<char> destination, char paddingChar);
public static bool PadRight(this ReadOnlySpan<char> source, int totalWidth, Span<char> destination);
public static bool PadRight(this ReadOnlySpan<char> source, int totalWidth, Span<char> destination, char paddingChar);
}
// Live in CoreLib and only available on .NET Core, exposed from System.Memory.dll
// Atm, this class in corelib is called 'Span' and contains the .NET Core specific implementation of the extension methods
public static class MemoryExtensions
{
public static bool Equals(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparison);
public static int Compare(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparison);
public static bool Contains(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparison);
public static bool StartsWith(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparison);
public static bool EndsWith(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparison);
public static bool Replace(this ReadOnlySpan<char> source, ReadOnlySpan<char> oldValue, ReadOnlySpan<char> newValue, StringComparison comparison, Span<char> destination, out int bytesWritten);
public static bool ToUpper(this ReadOnlySpan<char> source, Span<char> destination);
public static bool ToUpper(this ReadOnlySpan<char> source, Span<char> destination, CultureInfo culture);
public static bool ToUpperInvariant(this ReadOnlySpan<char> source, Span<char> destination);
public static bool ToLower(this ReadOnlySpan<char> source, Span<char> destination);
public static bool ToLower(this ReadOnlySpan<char> source, Span<char> destination, CultureInfo culture);
public static bool ToLowerInvariant(this ReadOnlySpan<char> source, Span<char> destination);
}
Original Proposal
public static class SpanExtensions
{
public static ReadOnlySpan<char> Trim(this ReadOnlySpan<char> span);
public static bool Equals(this ReadOnlySpan<char> source, ReadOnlySpan<char> value, StringComparison comparison);
public static int Compare(this ReadOnlySpan<char> source, ReadOnlySpan<char> value, StringComparison comparison);
public static bool StartsWith(this ReadOnlySpan<char> source, ReadOnlySpan<char> value, StringComparison comparison);
public static ReadOnlySpan<char> Remove(this ReadOnlySpan<char> source, int startIndex, int count); // this will need to allocate if any chars are removed from the middle
...
}