-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create APIs to deal with processing ASCII text (as bytes) #28230
Comments
Why is it useful to return source length? |
@danmosemsft It's not useful. It's just to match the API shape of |
I suggest not to perpetuate the design flaw? |
As mentioned that's easy to achieve, but it would be convenient to have these (as common use case?) in corefx. |
@danmosemsft - Sure, no complaints from my end to make it void-returning. We can simply document the behavior. |
would it be better to have these helper methods on the ASCIIEncoding class instead of creating a new utility class? |
@tarekgh I had this same concern with the UTF-8 APIs. Why not put them on the existing The argument that pushed me away from putting them on the existing Encoding classes is that the proposed static APIs are very opinionated in how they behave. If you subclass |
I didn't see anyone sub-classing Ascii encoding at all. this mean is unlikely to happen. even it show up in the list when sub-classing, I don't think this will be issue as these static methods anyway. my whole point having these in the Ascii encoding for easier discoverability as one class encapsulating the Ascii operations. You don't have to block on that though :-) and we should proceed with the design review. |
What is the behavior of this API if |
@vcsjones I assume undefined. See also https://github.com/dotnet/corefx/issues/34799, where I contemplated this same question with the existing span-based text case conversion APIs. |
It was done intentionally.
I would keep it consistent and return an int. Here is the context for why we returned an int: https://github.com/dotnet/corefx/issues/31340#issuecomment-407866739
|
@GrabYourPitchforks regarding undefined behavior: It seems better to detect this and throw or to make it defined (for example, by using a slower but safe algorithm). |
I don't think this is ever going to happen realistically. String manipulation APIs like An enormous amount of code is written with the assumption that simple case folding semantics are used for all String manipulation APIs, and it would introduce a massive breaking change throughout our ecosystem if we were to suddenly upend this. If we were going to introduce an API to perform full folding (which could change the length of the UTF-16 data), it really should be on a brand new API rather than one that purports to have the same semantics as existing APIs. Something like See also https://github.com/dotnet/coreclr/issues/20955#issuecomment-438389558. Edit: I'd still prefer returning an |
@GrabYourPitchforks are we still targeting this for 3.0? |
@tarekgh Probably not unless somebody really wants it. I'll re-milestone. |
More food for thought: |
@scalablecory are the heterogeneous parameters |
Think |
Looks good but needs work:
namespace System.Buffers.Text
{
public static class Ascii
{
public static bool EqualsOrdinalIgnoreCase(ReadOnlySpan<byte> left, ReadOnlySpan<byte> right);
public static int ToLowerInvariant(ReadOnlySpan<byte> source, Span<byte> destination);
public static int ToUpperInvariant(ReadOnlySpan<byte> source, Span<byte> destination);
public static void ToLowerInvariantInPlace(Span<byte> buffer);
public static void ToUpperInvariantInPlace(Span<byte> buffer);
}
} |
(Comment deleted since the updated API surface has been rolled into the proposal at the top of this issue.) |
Marking as ready for review since there's now a more fleshed-out API surface. |
If one is |
I'm not too attached to the name to be honest, so sure. :) Though the nice thing about naming it |
True, also matches behaviour of Question then, are other comparisions in the mix other than ordinal (e.g. see some So would a |
I don't think it makes sense to put proper culture-aware APIs here. At that point we're talking globalization, which almost always involves non-ASCII data at some point, and which isn't really prevalent for the scenarios we're considering here like network protocol parsing. If globalization is a concern for the developer IMO they'd be better served by the existing APIs on |
That makes sense; then my final concern from that would be inconsistency here EqualsOrdinalIgnoreCase
ToLowerInvariant
IndexOfOrdinalIgnoreCase Why are some |
namespace System.Buffers.Text
{
public static class Ascii
{
// Compares an ASCII byte buffer and an ASCII char buffer for value equality.
- public static bool Equals(ReadOnlySpan<byte> left, ReadOnlySpan<byte> right);
- public static bool Equals(ReadOnlySpan<char> left, ReadOnlySpan<char> right);
- public static bool Equals(ReadOnlySpan<byte> left, string right);
public static bool Equals(ReadOnlySpan<byte> left, ReadOnlySpan<char> right);
// Compare two ASCII buffers for value equality, treating [A-Z] and [a-z] as equal.
- public static bool EqualsIgnoreCase(ReadOnlySpan<byte> left, string right);
public static bool EqualsIgnoreCase(ReadOnlySpan<byte> left, ReadOnlySpan<byte> right);
public static bool EqualsIgnoreCase(ReadOnlySpan<char> left, ReadOnlySpan<char> right);
public static bool EqualsIgnoreCase(ReadOnlySpan<byte> left, ReadOnlySpan<char> right);
// Searches for the first (last) occurrence of the target substring within the
// search space, optionally treating [A-Z] and [a-z] as equal.
// Returns -1 if not found.
// Throws an exception if the needle contains non-ASCII data.
// The haystack is allowed to contain non-ASCII data.
- public static int IndexOf(ReadOnlySpan<byte> text, ReadOnlySpan<byte> value);
- public static int IndexOf(ReadOnlySpan<byte> text, string value);
- public static int IndexOf(ReadOnlySpan<byte> text, ReadOnlySpan<char> value);
+ public static int IndexOf(ReadOnlySpan<char> text, ReadOnlySpan<byte> value);
- public static int IndexOfIgnoreCase(ReadOnlySpan<byte> text, string value);
+ public static int IndexOfIgnoreCase(ReadOnlySpan<byte> text, ReadOnlySpan<char> value);
+ public static int LastIndexOf(ReadOnlySpan<byte> text, ReadOnlySpan<char> value);
+ public static int LastIndexOf(ReadOnlySpan<char> text, ReadOnlySpan<byte> value);
+ public static int LastIndexOfIgnoreCase(ReadOnlySpan<byte> text, ReadOnlySpan<byte> value);
+ public static int LastIndexOfIgnoreCase(ReadOnlySpan<char> text, ReadOnlySpan<char> value);
+ public static int LastIndexOfIgnoreCase(ReadOnlySpan<byte> text, ReadOnlySpan<char> value);
+ public static int LastIndexOfIgnoreCase(ReadOnlySpan<char> text, ReadOnlySpan<byte> value);
// Given a buffer, determines whether it starts (ends) with the given value,
// optionally treating [A-Z] and [a-z] as equal.
// Throws an exception if the needle contains non-ASCII data.
// The haystack is allowed to contain non-ASCII data.
+ public static bool StartsWith(ReadOnlySpan<byte> text, ReadOnlySpan<char> value);
+ public static bool StartsWith(ReadOnlySpan<char> text, ReadOnlySpan<byte> value);
+ public static bool EndsWith(ReadOnlySpan<byte> text, ReadOnlySpan<char> value);
+ public static bool EndsWith(ReadOnlySpan<char> text, ReadOnlySpan<byte> value);
+ public static bool StartsWithIgnoreCase(ReadOnlySpan<byte> text, ReadOnlySpan<byte> value);
+ public static bool StartsWithIgnoreCase(ReadOnlySpan<char> text, ReadOnlySpan<char> value);
+ public static bool StartsWithIgnoreCase(ReadOnlySpan<byte> text, ReadOnlySpan<char> value);
+ public static bool StartsWithIgnoreCase(ReadOnlySpan<char> text, ReadOnlySpan<byte> value);
+ public static bool EndsWithIgnoreCase(ReadOnlySpan<byte> text, ReadOnlySpan<byte> value);
+ public static bool EndsWithIgnoreCase(ReadOnlySpan<char> text, ReadOnlySpan<char> value);
+ public static bool EndsWithIgnoreCase(ReadOnlySpan<byte> text, ReadOnlySpan<char> value);
+ public static bool EndsWithIgnoreCase(ReadOnlySpan<char> text, ReadOnlySpan<byte> value);
// Given a buffer, returns the index of the first element in the buffer which
// is a non-ASCII byte, or -1 if the buffer is empty or all-ASCII. The bool-
// returning method is a convenience shortcut to perform the same check.
public static int GetIndexOfFirstNonAsciiByte(ReadOnlySpan<byte> buffer);
public static int GetIndexOfFirstNonAsciiChar(ReadOnlySpan<char> buffer);
public static bool IsAscii(ReadOnlySpan<byte> value);
public static bool IsAscii(ReadOnlySpan<char> value);
// Returns true iff the provided byte is an ASCII byte; i.e., in the range [ 00 .. 7F ];
// or if the provided char is in the range [ 0000 .. 007F ].
public static bool IsAscii(byte value);
public static bool IsAscii(char value);
// Copies source to destination, converting [A-Z] <-> [a-z] during the copy.
// Returns OperationStatus.InvalidData on non-ASCII input.
- public static int ToLower(ReadOnlySpan<byte> source, Span<byte> destination);
- public static int ToLower(ReadOnlySpan<char> source, Span<char> destination);
- public static int ToUpper(ReadOnlySpan<byte> source, Span<byte> destination);
- public static int ToUpper(ReadOnlySpan<char> source, Span<char> destination);
+ public static OperationStatus ToUpper(ReadOnlySpan<byte> source, Span<byte> destination, out int elementsProcessed);
+ public static OperationStatus ToUpper(ReadOnlySpan<char> source, Span<char> destination, out int elementsProcessed);
+ public static OperationStatus ToUpper(ReadOnlySpan<byte> source, Span<char> destination, out int elementsProcessed);
+ public static OperationStatus ToUpper(ReadOnlySpan<char> source, Span<byte> destination, out int elementsProcessed);
+ public static OperationStatus ToLower(ReadOnlySpan<byte> source, Span<byte> destination, out int elementsProcessed);
+ public static OperationStatus ToLower(ReadOnlySpan<char> source, Span<char> destination, out int elementsProcessed);
+ public static OperationStatus ToLower(ReadOnlySpan<byte> source, Span<char> destination, out int elementsProcessed);
+ public static OperationStatus ToLower(ReadOnlySpan<char> source, Span<byte> destination, out int elementsProcessed);
- public static byte ToLower(byte value);
- public static byte ToLower(char value);
- public static byte ToUpper(byte value);
- public static byte ToUpper(char value);
// Performs case conversion ([A-Z] <-> [a-z]) in-place.
// Returns true on success, false if any non-ASCII data was found (and stops processing).
// Always outs the number of elements it was able to convert.
- public static void ToLowerInPlace(Span<byte> value);
+ public static bool TryToUpperInPlace(Span<byte> value, out int bytesProcessed);
- public static void ToLowerInPlace(Span<char> value);
+ public static bool TryToUpperInPlace(Span<char> value, out int charsProcessed);
- public static void ToUpperInPlace(Span<byte> value);
+ public static bool TryToLowerInPlace(Span<byte> value, out int bytesProcessed);
- public static void ToUpperInPlace(Span<char> value);
+ public static bool TryToLowerInPlace(Span<char> value, out int charsProcessed);
// Returns a hash code for the provided buffer suitable for use in a dictionary or
// other keyed collection, optionally treating [A-Z] and [a-z] as equal.
// The hash code is randomized and is not guaranteed to match string.GetHashCode
// or any other public PRF within the framework. The ROS<byte> and ROS<char> overloads
// will produce the same hash code if Equals[IgnoreCase](ROS<byte>, ROS<char>) returns
// true. The Try* methods return false (and out 0) if the input is not ASCII;
// the non-Try* methods throw an exception.
+ public static bool TryGetHashCode(ReadOnlySpan<byte> value, out int hashCode);
+ public static bool TryGetHashCode(ReadOnlySpan<char> value, out int hashCode);
+ public static bool TryGetHashCodeIgnoreCase(ReadOnlySpan<byte> value, out int hashCode);
+ public static bool TryGetHashCodeIgnoreCase(ReadOnlySpan<char> value, out int hashCode);
public static int GetHashCode(ReadOnlySpan<byte> value);
public static int GetHashCode(ReadOnlySpan<char> value);
public static int GetHashCodeIgnoreCase(ReadOnlySpan<byte> value);
public static int GetHashCodeIgnoreCase(ReadOnlySpan<char> value);
// Widens an ASCII buffer to UTF-16 or narrows a UTF-16 buffer to ASCII.
// Returns OperationStatus.InvalidData if the source buffer contains a non-ASCII byte
// or a char in the range [ 0080 .. FFFF ].
- public static OperationStatus WidenToUtf16(ReadOnlySpan<byte> source, Span<char> destination, out int bytesConsumed, out int charsWritten);
- public static OperationStatus NarrowFromUTf16(ReadOnlySpan<char> source, Span<byte> destination, out int charsConsumed, out int bytesWritten);
+ public static OperationStatus ToUtf16(ReadOnlySpan<byte> source, Span<char> destination, out int elementsProcessed);
+ public static OperationStatus FromUtf16(ReadOnlySpan<char> source, Span<byte> destination, out int elementsProcessed);
// Trims only ASCII whitespace values from the buffer, returning the trimmed buffer.
// The full set of trimmed values is: U+0009..U+000D and U+0020.
// All other elements, including non-ASCII elements, are ignored.
public static Range Trim(ReadOnlySpan<byte> value);
public static Range Trim(ReadOnlySpan<char> value);
public static Range TrimStart(ReadOnlySpan<byte> value);
public static Range TrimStart(ReadOnlySpan<char> value);
public static Range TrimEnd(ReadOnlySpan<byte> value);
public static Range TrimEnd(ReadOnlySpan<char> value);
}
} |
+ public static int IndexOf(ReadOnlySpan<char> text, ReadOnlySpan<byte> value);
+ public static int IndexOfIgnoreCase(ReadOnlySpan<byte> text, ReadOnlySpan<char> value); is the difference between these intentional? |
Original API: namespace System.Buffers.Text;
public static class Ascii
{
public static bool Equals(ReadOnlySpan<byte> left, ReadOnlySpan<char> right);
public static bool EqualsIgnoreCase(ReadOnlySpan<byte> left, ReadOnlySpan<byte> right);
public static bool EqualsIgnoreCase(ReadOnlySpan<char> left, ReadOnlySpan<char> right);
public static bool EqualsIgnoreCase(ReadOnlySpan<byte> left, ReadOnlySpan<char> right);
public static int IndexOf(ReadOnlySpan<byte> text, ReadOnlySpan<char> value);
public static int IndexOf(ReadOnlySpan<char> text, ReadOnlySpan<byte> value);
public static int LastIndexOf(ReadOnlySpan<byte> text, ReadOnlySpan<char> value);
public static int LastIndexOf(ReadOnlySpan<char> text, ReadOnlySpan<byte> value);
public static int IndexOfIgnoreCase(ReadOnlySpan<byte> text, ReadOnlySpan<byte> value);
public static int IndexOfIgnoreCase(ReadOnlySpan<char> text, ReadOnlySpan<char> value);
public static int IndexOfIgnoreCase(ReadOnlySpan<byte> text, ReadOnlySpan<char> value);
public static int IndexOfIgnoreCase(ReadOnlySpan<char> text, ReadOnlySpan<byte> value);
public static int LastIndexOfIgnoreCase(ReadOnlySpan<byte> text, ReadOnlySpan<byte> value);
public static int LastIndexOfIgnoreCase(ReadOnlySpan<char> text, ReadOnlySpan<char> value);
public static int LastIndexOfIgnoreCase(ReadOnlySpan<byte> text, ReadOnlySpan<char> value);
public static int LastIndexOfIgnoreCase(ReadOnlySpan<char> text, ReadOnlySpan<byte> value);
public static bool StartsWith(ReadOnlySpan<byte> text, ReadOnlySpan<char> value);
public static bool StartsWith(ReadOnlySpan<char> text, ReadOnlySpan<byte> value);
public static bool EndsWith(ReadOnlySpan<byte> text, ReadOnlySpan<char> value);
public static bool EndsWith(ReadOnlySpan<char> text, ReadOnlySpan<byte> value);
public static bool StartsWithIgnoreCase(ReadOnlySpan<byte> text, ReadOnlySpan<byte> value);
public static bool StartsWithIgnoreCase(ReadOnlySpan<char> text, ReadOnlySpan<char> value);
public static bool StartsWithIgnoreCase(ReadOnlySpan<byte> text, ReadOnlySpan<char> value);
public static bool StartsWithIgnoreCase(ReadOnlySpan<char> text, ReadOnlySpan<byte> value);
public static bool EndsWithIgnoreCase(ReadOnlySpan<byte> text, ReadOnlySpan<byte> value);
public static bool EndsWithIgnoreCase(ReadOnlySpan<char> text, ReadOnlySpan<char> value);
public static bool EndsWithIgnoreCase(ReadOnlySpan<byte> text, ReadOnlySpan<char> value);
public static bool EndsWithIgnoreCase(ReadOnlySpan<char> text, ReadOnlySpan<byte> value);
public static int GetIndexOfFirstNonAsciiByte(ReadOnlySpan<byte> buffer);
public static int GetIndexOfFirstNonAsciiChar(ReadOnlySpan<char> buffer);
public static bool IsAscii(ReadOnlySpan<byte> value);
public static bool IsAscii(ReadOnlySpan<char> value);
public static bool IsAscii(byte value);
public static bool IsAscii(char value);
public static OperationStatus ToUpper(ReadOnlySpan<byte> source, Span<byte> destination, out int elementsProcessed);
public static OperationStatus ToUpper(ReadOnlySpan<char> source, Span<char> destination, out int elementsProcessed);
public static OperationStatus ToUpper(ReadOnlySpan<byte> source, Span<char> destination, out int elementsProcessed);
public static OperationStatus ToUpper(ReadOnlySpan<char> source, Span<byte> destination, out int elementsProcessed);
public static OperationStatus ToLower(ReadOnlySpan<byte> source, Span<byte> destination, out int elementsProcessed);
public static OperationStatus ToLower(ReadOnlySpan<char> source, Span<char> destination, out int elementsProcessed);
public static OperationStatus ToLower(ReadOnlySpan<byte> source, Span<char> destination, out int elementsProcessed);
public static OperationStatus ToLower(ReadOnlySpan<char> source, Span<byte> destination, out int elementsProcessed);
public static bool TryToUpperInPlace(Span<byte> value, out int bytesProcessed);
public static bool TryToUpperInPlace(Span<char> value, out int charsProcessed);
public static bool TryToLowerInPlace(Span<byte> value, out int bytesProcessed);
public static bool TryToLowerInPlace(Span<char> value, out int charsProcessed);
public static bool TryGetHashCode(ReadOnlySpan<byte> value, out int hashCode);
public static bool TryGetHashCode(ReadOnlySpan<char> value, out int hashCode);
public static bool TryGetHashCodeIgnoreCase(ReadOnlySpan<byte> value, out int hashCode);
public static bool TryGetHashCodeIgnoreCase(ReadOnlySpan<char> value, out int hashCode);
public static int GetHashCode(ReadOnlySpan<byte> value);
public static int GetHashCode(ReadOnlySpan<char> value);
public static int GetHashCodeIgnoreCase(ReadOnlySpan<byte> value);
public static int GetHashCodeIgnoreCase(ReadOnlySpan<char> value);
public static OperationStatus ToUtf16(ReadOnlySpan<byte> source, Span<char> destination, out int elementsProcessed);
public static OperationStatus FromUtf16(ReadOnlySpan<char> source, Span<byte> destination, out int elementsProcessed);
public static Range Trim(ReadOnlySpan<byte> value);
public static Range Trim(ReadOnlySpan<char> value);
public static Range TrimStart(ReadOnlySpan<byte> value);
public static Range TrimStart(ReadOnlySpan<char> value);
public static Range TrimEnd(ReadOnlySpan<byte> value);
public static Range TrimEnd(ReadOnlySpan<char> value);
} |
To make some progress on #75012 I would like to discuss only a subset of the ASCII APIs. Here is what was changes since last discussion: - namespace System.Buffers.Text;
+ namespace System.Text;
public static class Ascii
{
- public static bool IsAscii(ReadOnlySpan<byte> value);
- public static bool IsAscii(ReadOnlySpan<char> value);
+ public static bool IsValid(ReadOnlySpan<byte> value);
+ public static bool IsValid(ReadOnlySpan<char> value);
- public static bool IsAscii(byte value);
- public static bool IsAscii(char value);
+ public static bool IsValid(byte value);
+ public static bool IsValid(char value);
public static OperationStatus ToUpper(ReadOnlySpan<byte> source, Span<byte> destination, out int elementsProcessed);
public static OperationStatus ToUpper(ReadOnlySpan<char> source, Span<char> destination, out int elementsProcessed);
public static OperationStatus ToUpper(ReadOnlySpan<byte> source, Span<char> destination, out int elementsProcessed);
public static OperationStatus ToUpper(ReadOnlySpan<char> source, Span<byte> destination, out int elementsProcessed);
public static OperationStatus ToLower(ReadOnlySpan<byte> source, Span<byte> destination, out int elementsProcessed);
public static OperationStatus ToLower(ReadOnlySpan<char> source, Span<char> destination, out int elementsProcessed);
public static OperationStatus ToLower(ReadOnlySpan<byte> source, Span<char> destination, out int elementsProcessed);
public static OperationStatus ToLower(ReadOnlySpan<char> source, Span<byte> destination, out int elementsProcessed);
public static bool TryToUpperInPlace(Span<byte> value, out int bytesProcessed);
public static bool TryToUpperInPlace(Span<char> value, out int charsProcessed);
public static bool TryToLowerInPlace(Span<byte> value, out int bytesProcessed);
public static bool TryToLowerInPlace(Span<char> value, out int charsProcessed);
public static OperationStatus ToUtf16(ReadOnlySpan<byte> source, Span<char> destination, out int elementsProcessed);
public static OperationStatus FromUtf16(ReadOnlySpan<char> source, Span<byte> destination, out int elementsProcessed);
public static Range Trim(ReadOnlySpan<byte> value);
public static Range Trim(ReadOnlySpan<char> value);
public static Range TrimStart(ReadOnlySpan<byte> value);
public static Range TrimStart(ReadOnlySpan<char> value);
public static Range TrimEnd(ReadOnlySpan<byte> value);
public static Range TrimEnd(ReadOnlySpan<char> value);
}
Very good point, fixed.
In my opinion, users would be confused if Writing the following code is just more natural and obvious to me: if (Ascii.TryToLowerInPlace(buffer, out int cosumed))
{
// success
}
else
{
// non-ascii found at index "consumed"
} |
@GrabYourPitchforks @stephentoub while studying ASP.NET code today I've realized that their corresponding helper for The check if performed here: https://github.com/dotnet/aspnetcore/blob/c4b57c452447f70ab874097436226542c70d74c0/src/Shared/ServerInfrastructure/StringUtilities.cs#L799 So what we have right now in the proposal won't meet their requirements. What is your opinion on extending - public static OperationStatus ToUtf16(ReadOnlySpan<byte> source, Span<char> destination, out int elementsProcessed);
+ public static OperationStatus ToUtf16(ReadOnlySpan<byte> source, Span<char> destination, bool allowNullCharacters = true, out int elementsProcessed);
- public static OperationStatus FromUtf16(ReadOnlySpan<char> source, Span<byte> destination, out int elementsProcessed);
+ public static OperationStatus FromUtf16(ReadOnlySpan<char> source, Span<byte> destination, bool allowNullCharacters = true, out int elementsProcessed); I just want to make sure that they can delete their own copy of |
@adamsitnik in case you missed it: dotnet/aspnetcore#44040 (comment) |
I strongly oppose special-casing NULL (or any other control character, including For the particular API being suggested here, we don't special-case control chars within |
namespace System.Text;
public static class Ascii
{
public static bool IsValid(ReadOnlySpan<byte> value);
public static bool IsValid(ReadOnlySpan<char> value);
public static bool IsValid(byte value);
public static bool IsValid(char value);
public static OperationStatus ToUpper(ReadOnlySpan<byte> source, Span<byte> destination, out int bytesWritten);
public static OperationStatus ToUpper(ReadOnlySpan<char> source, Span<char> destination, out int charsWritten);
public static OperationStatus ToUpper(ReadOnlySpan<byte> source, Span<char> destination, out int charsWritten);
public static OperationStatus ToUpper(ReadOnlySpan<char> source, Span<byte> destination, out int bytesWritten);
public static OperationStatus ToLower(ReadOnlySpan<byte> source, Span<byte> destination, out int bytesWritten);
public static OperationStatus ToLower(ReadOnlySpan<char> source, Span<char> destination, out int charsWritten);
public static OperationStatus ToLower(ReadOnlySpan<byte> source, Span<char> destination, out int charsWritten);
public static OperationStatus ToLower(ReadOnlySpan<char> source, Span<byte> destination, out int bytesWritten);
public static OperationStatus ToUpperInPlace(Span<byte> value, out int bytesWritten);
public static OperationStatus ToUpperInPlace(Span<char> value, out int charsWritten);
public static OperationStatus ToLowerInPlace(Span<byte> value, out int bytesWritten);
public static OperationStatus ToLowerInPlace(Span<char> value, out int charsWritten);
public static OperationStatus ToUtf16(ReadOnlySpan<byte> source, Span<char> destination, out int charsWritten);
public static OperationStatus FromUtf16(ReadOnlySpan<char> source, Span<byte> destination, out int bytesWritten);
public static Range Trim(ReadOnlySpan<byte> value);
public static Range Trim(ReadOnlySpan<char> value);
public static Range TrimStart(ReadOnlySpan<byte> value);
public static Range TrimStart(ReadOnlySpan<char> value);
public static Range TrimEnd(ReadOnlySpan<byte> value);
public static Range TrimEnd(ReadOnlySpan<char> value);
} |
@bartonjs @GrabYourPitchforks @stephentoub I've realized that What do you think about renaming - public static OperationStatus ToUpperInPlace(Span<byte> value, out int bytesWritten);
- public static OperationStatus ToUpperInPlace(Span<char> value, out int charsWritten);
+ public static OperationStatus ToUpperInPlace(Span<byte> value, out int bytesProcessed);
+ public static OperationStatus ToUpperInPlace(Span<char> value, out int charsProcessed);
- public static OperationStatus ToLowerInPlace(Span<byte> value, out int bytesWritten);
- public static OperationStatus ToLowerInPlace(Span<char> value, out int charsWritten);
+ public static OperationStatus ToLowerInPlace(Span<byte> value, out int bytesProcessed);
+ public static OperationStatus ToLowerInPlace(Span<char> value, out int charsProcessed); |
The guideline is
If you see any existing OperationStatus method that has done something other than "Written" and has a similar justification, then maybe... but "Written" is what the pattern suggests, and it isn't so wrong as to feel like it needs something different. |
EDIT: most up to date proposal can be found here: #28230 (comment)
Most recent API review comment: #28230 (comment)
If you are interested in the original proposal, click "details" below:
To make @KrzysztofCwalina happy. :)
Networking protocols and parsers in particular use ASCII very frequently - even more so than UTF-8. It would be useful to introduce high-performance APIs that work very specifically on ASCII text without trying to interpret it as UTF-8.
The text was updated successfully, but these errors were encountered: