Skip to content

[API Proposal]: Add SearchValues.CreateRange #129283

@Neme12

Description

@Neme12

Background and motivation

I'm proposing a new way of creating SearchValues - instead of some values, it would represent all values except that value (CreateExcept), or a range of values. I know I can achieve this via IndexOfAnyExcept, IndexOfAnyInRange and IndexOfAnyExceptInRange, but encapsulating the search inside SearchValues seems like a much better design to me than method explosions like this, and the three methods I mentioned would be now unnecessary and effectively obsolete. It would be convenient to be able to always store SearchValues<T>, even in case of ranges, and then use the one method that uses it.

API Proposal

namespace System.Buffers;

public static partial class SearchValues
{
	public static SearchValues<T> CreateExcept<T>(params ReadOnlySpan<T> values);

	public static SearchValues<T> CreateRange<T>(T lowInclusive, T highInclusive);
	public static SearchValues<T> CreateExceptRange<T>(T lowInclusive, T highInclusive);

	public static SearchValues<T> CreateRanges<T>(params ReadOnlySpan<Range<T>> ranges);
	public static SearchValues<T> CreateExceptRanges<T>(params ReadOnlySpan<Range<T>> ranges);

	public readonly struct Range<T> : IEquatable<Range<T>>
	{
		public Range(T value);
		public Range(T lowInclusive, T highInclusive);

		public T LowInclusive { get; }
		public T HighInclusive { get; }

		public void Deconstruct(out T lowInclusive, out T highInclusive);

		public static implicit operator Range<T>(T value);
		public static implicit operator Range<T>((T lowInclusive, T highInclusive) range);
	}
}

Note: The T might have to be expanded to a list of overloads for concrete types instead of being generic.

Also, if I'm unsure whether to use CreateRange with 2 or 3 sequential elements or Create with those elements, no matter what I pick, it would be nice if the implementation chose the right and fastest form of searching for such a set no matter which method I choose, so I don't have to worry about it. Tbat's the benefit of using SearchValues, even for ranges.

API Usage

var searchValues = SearchValues.CreateExceptRange<char>('a', 'z');
var index = span.IndexOfAny(searchValues);

var invalidChars = SearchValues.CreateRanges<char>(((char)0, (char)31), '@', '#', '|');
var index2 = span.IndexOfAny(invalidChars);

// or, get all control characters except for newline
var invalidChars2 = SearchValues.CreateRanges<char>(((char)0, (char)9), ((char)11, (char)31));

Alternative Designs

As an alternative, only the CreateRange and CreateRanges APIs could be added - those are the ones I'd like to use.

Risks

Idk. cc @stephentoub

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-suggestionEarly API idea and discussion, it is NOT ready for implementationarea-System.Memory

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions