/ src / Ryujinx.HLE / Utilities / StringUtils.cs
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  }