- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在寻找一种高效、免分配(!)的实现
public static int IndexOf(this ReadOnlySpan<byte> utf8Bytes, char @char)
{
// Should return the index of the first byte of @char within utf8Bytes
// (not the character index of @char within the string)
}
我还没有找到一种方法来逐个字符地遍历跨度。 Utf8Parser 没有支持单个字符的重载。System.Text.Encoding 似乎主要在整个跨度上工作,并且在这样做时确实在内部分配。
是否有任何我还没有发现的内置功能?如果没有,有人能想到一个合理的自定义实现吗?
最佳答案
而不是尝试迭代 utf8Bytes
逐个字符,将字符转换为短的 stackalloc'ed utf8 字节序列并搜索它可能会更容易:
public static class StringExtensions
{
const int MaxBytes = 4;
public static int IndexOf(this ReadOnlySpan<byte> utf8Bytes, char @char)
{
Rune rune;
try
{
rune = new Rune(@char);
}
catch (ArgumentOutOfRangeException)
{
// Malformed unicode character, return -1 or throw?
return -1;
}
return utf8Bytes.IndexOf(rune);
}
public static int IndexOf(this ReadOnlySpan<byte> utf8Bytes, Rune @char)
{
Span<byte> charBytes = stackalloc byte[MaxBytes];
var n = @char.EncodeToUtf8(charBytes);
charBytes = charBytes.Slice(0, n);
for (int i = 0, thisLength = 1; i <= utf8Bytes.Length - charBytes.Length; i += thisLength)
{
thisLength = Utf8ByteSequenceLength(utf8Bytes[i]);
if (thisLength == charBytes.Length && charBytes.CommonPrefixLength(utf8Bytes.Slice(i)) == charBytes.Length)
return i;
}
return -1;
}
static int Utf8ByteSequenceLength(byte firstByte)
{
//https://en.wikipedia.org/wiki/UTF-8#Encoding
if ( (firstByte & 0b11111000) == 0b11110000) // 11110xxx
return 4;
else if ((firstByte & 0b11110000) == 0b11100000) // 1110xxxx
return 3;
else if ((firstByte & 0b11100000) == 0b11000000) // 110xxxxx
return 2;
return 1; // Either a 1-byte sequence (matching 0xxxxxxx) or an invalid start byte.
}
}
注释:
Rune
是 .NET Core 3.x 中引入的一个结构体,表示 Unicode 标量值。如果您需要搜索您的utf8Bytes
对于不在 basic multilingual plane 中的 Unicode 代码点,你将需要使用 rune 。
Rune
其方法 Rune.TryEncodeToUtf8()
具有额外的优点是轻量级且免分配的。
如果 char @char
是无效的 Unicode 字符,如果您尝试构造 Rune
,.NET 编码算法将引发异常。从中。上面的代码捕获异常并返回-1
。您可能希望重新抛出异常。
作为替代方案, Rune.DecodeFromUtf8(ReadOnlySpan<Byte>, Rune, Int32)
可用于逐个 Rune 迭代 utf8 字节范围。您可以使用它通过索引来定位传入的 rune 。不过,我怀疑这样做的效率会比上面的方法低。
演示 fiddle here .
关于c# - UTF8 字节的 ReadOnlySpan<byte> 内的 IndexOf char,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75338574/
呃......微软已经做了一些事情。 过去几个小时(大约 10:00 GMT)启动的所有构建都因以下错误(来自日志)而因“构建解决方案步骤”而失败: ##[error]EXEC(0,0): Error
我尝试理解 .net core 3.0。据我所知,我不能将 Span 或 ReadonlySpan 用作属性或成员,因为它是基于堆栈的结构。我想知道以下定义之间的区别。我可以成功定义“part1”而不
好的,.NET Core 2.1 已经落地。有了它,我们就得到了一种处理字符串数据的新方法 ReadOnlySpan 。它非常适合分割字符串数据,但是如何将跨度重新组合在一起呢? var hello
以下代码会导致编译器在属性 getter 的第一行抛出错误 CS1605(“无法将 'var' 作为 ref 或 out 参数传递,因为它是只读的”)。 [StructLayout(LayoutKin
我有一个相当简单的字符串扩展方法,该方法在我拥有的系统中被频繁调用,该方法正在执行大量字符串操作。我读了这篇文章 ( String.Substring() seems to bottleneck th
我正在使用ReadOnlySpan,我想亲自看看它比使用字符串快得多,但是......到目前为止,情况并非如此。我知道我的代码中可能犯了一个错误,但我找不到它。 static int CountCha
ReadOnlySpan据说非常适合解析,所以我尝试使用它,但遇到了一个我不知道如何处理的用例。 我有一个命令行 string其中参数前缀 -和分隔符 (空格)被转义了(我知道我可以在这里引用它们但是
引入了 C# 7.2 reference semantics with value-types ,除此之外,微软还开发了类似 Span and ReadOnlySpan 的类型潜在地提高需要在连续内存
假设我有如下方法: unsafe void Convert(byte* ptr, int length) { var span = new Span(ptr, length); var
在解析 int 时数据来自 string , 有没有办法使用 ReadOnlySpan ?喜欢int.Parse(str.AsSpan().Slice(2,3)) 因为如果 int 数据在字符串的中间
我理解为什么 ReadOnlySpan 不能用作泛型类的类型参数。 ReadOnlySpan 只是堆栈,因此它不能用作字段类型,字段成员像它的容器对象一样存在于堆中。然而,返回值和参数始终只是堆栈,那
我的类(class)有一个属性 public byte[] Location{get;} = new byte[30];我希望能够从 ReadOnlySpan 填充它但我找不到任何允许这样做的 API
Microsoft 在 Write safe and efficient C# code 中推荐: Apply the in modifier to readonly struct parameter
如果我已经只有 ReadOnlySpan 切片,那么连接字符串的最有效方法是什么? 简化示例: public class Program { public string ConcatSpans
我正在尝试尽可能快地解析二进制文件。所以这是我第一次尝试做的: using (FileStream filestream = path.OpenRead()) { using (var d =
我想知道当两者都ReadOnlySpan时是否有任何界面、模式或其他什么东西和 IReadOnlyList (以及更通用的接口(interface)),并且您希望避免无用的分配 . 考虑使用 IEnu
我正在寻找一种高效、免分配(!)的实现 public static int IndexOf(this ReadOnlySpan utf8Bytes, char @char) { // Shoul
我正在 Fsharp 中创建 RSA pki 并尝试加载私钥: let getRsa () = let rsa = RSA.Create() let privateKey = ge
我正在 Fsharp 中创建 RSA pki 并尝试加载私钥: let getRsa () = let rsa = RSA.Create() let privateKey = ge
我使用的是 Visual Studio 15.5.6 版本。 当我创建一个简单的控制台应用程序项目时,我无法使用 ReadOnlySpan或 Span或 Memory . 我将项目设置为 .Net F
我是一名优秀的程序员,十分优秀!