diff options
Diffstat (limited to 'src/Ryujinx.Horizon/Sdk/Ngc/Detail/Utf8Text.cs')
| -rw-r--r-- | src/Ryujinx.Horizon/Sdk/Ngc/Detail/Utf8Text.cs | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/src/Ryujinx.Horizon/Sdk/Ngc/Detail/Utf8Text.cs b/src/Ryujinx.Horizon/Sdk/Ngc/Detail/Utf8Text.cs new file mode 100644 index 00000000..47f78049 --- /dev/null +++ b/src/Ryujinx.Horizon/Sdk/Ngc/Detail/Utf8Text.cs @@ -0,0 +1,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; + } + } +} |
