blob: 47f780494633b407424013de6d3c419ca7cd1b24 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
using System;
using System.Text;
namespace Ryujinx.Horizon.Sdk.Ngc.Detail
{
readonly struct Utf8Text
{
private readonly byte[] _text;
private readonly int[] _charOffsets;
public int CharacterCount => _charOffsets.Length - 1;
public Utf8Text()
{
_text = Array.Empty<byte>();
_charOffsets = Array.Empty<int>();
}
public Utf8Text(byte[] text)
{
_text = text;
UTF8Encoding encoding = new(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true);
string str = encoding.GetString(text);
_charOffsets = new int[str.Length + 1];
int offset = 0;
for (int index = 0; index < str.Length; index++)
{
_charOffsets[index] = offset;
offset += encoding.GetByteCount(str.AsSpan().Slice(index, 1));
}
_charOffsets[str.Length] = offset;
}
public Utf8Text(ReadOnlySpan<byte> text) : this(text.ToArray())
{
}
public static Utf8ParseResult Create(out Utf8Text utf8Text, ReadOnlySpan<byte> text)
{
try
{
utf8Text = new(text);
}
catch (ArgumentException)
{
utf8Text = default;
return Utf8ParseResult.InvalidCharacter;
}
return Utf8ParseResult.Success;
}
public ReadOnlySpan<byte> AsSubstring(int startCharIndex, int endCharIndex)
{
int startOffset = _charOffsets[startCharIndex];
int endOffset = _charOffsets[endCharIndex];
return _text.AsSpan()[startOffset..endOffset];
}
public Utf8Text AppendNullTerminated(ReadOnlySpan<byte> toAppend)
{
int length = toAppend.IndexOf((byte)0);
if (length >= 0)
{
toAppend = toAppend[..length];
}
return Append(toAppend);
}
public Utf8Text Append(ReadOnlySpan<byte> toAppend)
{
byte[] combined = new byte[_text.Length + toAppend.Length];
_text.AsSpan().CopyTo(combined.AsSpan()[.._text.Length]);
toAppend.CopyTo(combined.AsSpan()[_text.Length..]);
return new(combined);
}
public void CopyTo(Span<byte> destination)
{
_text.CopyTo(destination[.._text.Length]);
if (destination.Length > _text.Length)
{
destination[_text.Length] = 0;
}
}
public ReadOnlySpan<byte> AsSpan()
{
return _text;
}
}
}
|