StringUtils.cs
1 using LibHac.Common; 2 using Microsoft.IO; 3 using Ryujinx.Common.Memory; 4 using Ryujinx.HLE.HOS; 5 using System; 6 using System.Globalization; 7 using System.IO; 8 using System.Linq; 9 using System.Text; 10 11 namespace Ryujinx.HLE.Utilities 12 { 13 static class StringUtils 14 { 15 public static byte[] GetFixedLengthBytes(string inputString, int size, Encoding encoding) 16 { 17 inputString += "\0"; 18 19 int bytesCount = encoding.GetByteCount(inputString); 20 21 byte[] output = new byte[size]; 22 23 if (bytesCount < size) 24 { 25 encoding.GetBytes(inputString, 0, inputString.Length, output, 0); 26 } 27 else 28 { 29 int nullSize = encoding.GetByteCount("\0"); 30 31 output = encoding.GetBytes(inputString); 32 33 Array.Resize(ref output, size - nullSize); 34 35 output = output.Concat(encoding.GetBytes("\0")).ToArray(); 36 } 37 38 return output; 39 } 40 41 public static string ReadInlinedAsciiString(BinaryReader reader, int maxSize) 42 { 43 byte[] data = reader.ReadBytes(maxSize); 44 45 int stringSize = Array.IndexOf<byte>(data, 0); 46 47 return Encoding.ASCII.GetString(data, 0, stringSize < 0 ? maxSize : stringSize); 48 } 49 50 public static byte[] HexToBytes(string hexString) 51 { 52 // Ignore last character if HexLength % 2 != 0. 53 int bytesInHex = hexString.Length / 2; 54 55 byte[] output = new byte[bytesInHex]; 56 57 for (int index = 0; index < bytesInHex; index++) 58 { 59 output[index] = byte.Parse(hexString.AsSpan(index * 2, 2), NumberStyles.HexNumber); 60 } 61 62 return output; 63 } 64 65 public static string ReadUtf8String(ReadOnlySpan<byte> data, out int dataRead) 66 { 67 dataRead = data.IndexOf((byte)0) + 1; 68 69 if (dataRead <= 1) 70 { 71 return string.Empty; 72 } 73 74 return Encoding.UTF8.GetString(data[..dataRead]); 75 } 76 77 public static string ReadUtf8String(ServiceCtx context, int index = 0) 78 { 79 ulong position = context.Request.PtrBuff[index].Position; 80 ulong size = context.Request.PtrBuff[index].Size; 81 82 using RecyclableMemoryStream ms = MemoryStreamManager.Shared.GetStream(); 83 while (size-- > 0) 84 { 85 byte value = context.Memory.Read<byte>(position++); 86 87 if (value == 0) 88 { 89 break; 90 } 91 92 ms.WriteByte(value); 93 } 94 95 return Encoding.UTF8.GetString(ms.GetReadOnlySequence()); 96 } 97 98 public static U8Span ReadUtf8Span(ServiceCtx context, int index = 0) 99 { 100 ulong position = context.Request.PtrBuff[index].Position; 101 ulong size = context.Request.PtrBuff[index].Size; 102 103 ReadOnlySpan<byte> buffer = context.Memory.GetSpan(position, (int)size); 104 105 return new U8Span(buffer); 106 } 107 108 public static string ReadUtf8StringSend(ServiceCtx context, int index = 0) 109 { 110 ulong position = context.Request.SendBuff[index].Position; 111 ulong size = context.Request.SendBuff[index].Size; 112 113 using RecyclableMemoryStream ms = MemoryStreamManager.Shared.GetStream(); 114 115 while (size-- > 0) 116 { 117 byte value = context.Memory.Read<byte>(position++); 118 119 if (value == 0) 120 { 121 break; 122 } 123 124 ms.WriteByte(value); 125 } 126 127 return Encoding.UTF8.GetString(ms.GetReadOnlySequence()); 128 } 129 130 public static int CompareCStr(ReadOnlySpan<byte> s1, ReadOnlySpan<byte> s2) 131 { 132 int s1Index = 0; 133 int s2Index = 0; 134 135 while (s1[s1Index] != 0 && s2[s2Index] != 0 && s1[s1Index] == s2[s2Index]) 136 { 137 s1Index += 1; 138 s2Index += 1; 139 } 140 141 return s2[s2Index] - s1[s1Index]; 142 } 143 144 public static int LengthCstr(ReadOnlySpan<byte> s) 145 { 146 int i = 0; 147 148 while (s[i] != 0) 149 { 150 i++; 151 } 152 153 return i; 154 } 155 } 156 }