mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
79 lines
2.3 KiB
C#
79 lines
2.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
|
|
namespace Penumbra.GameData.Files;
|
|
|
|
public partial class ShpkFile
|
|
{
|
|
public class StringPool
|
|
{
|
|
public MemoryStream Data;
|
|
public List<int> StartingOffsets;
|
|
|
|
public StringPool(ReadOnlySpan<byte> bytes)
|
|
{
|
|
Data = new MemoryStream();
|
|
Data.Write(bytes);
|
|
StartingOffsets = new List<int>
|
|
{
|
|
0,
|
|
};
|
|
for (var i = 0; i < bytes.Length; ++i)
|
|
{
|
|
if (bytes[i] == 0)
|
|
StartingOffsets.Add(i + 1);
|
|
}
|
|
|
|
if (StartingOffsets[^1] == bytes.Length)
|
|
StartingOffsets.RemoveAt(StartingOffsets.Count - 1);
|
|
else
|
|
Data.WriteByte(0);
|
|
}
|
|
|
|
public string GetString(int offset, int size)
|
|
=> Encoding.UTF8.GetString(Data.GetBuffer().AsSpan().Slice(offset, size));
|
|
|
|
public string GetNullTerminatedString(int offset)
|
|
{
|
|
var str = Data.GetBuffer().AsSpan()[offset..];
|
|
var size = str.IndexOf((byte)0);
|
|
if (size >= 0)
|
|
str = str[..size];
|
|
return Encoding.UTF8.GetString(str);
|
|
}
|
|
|
|
public (int, int) FindOrAddString(string str)
|
|
{
|
|
var dataSpan = Data.GetBuffer().AsSpan();
|
|
var bytes = Encoding.UTF8.GetBytes(str);
|
|
foreach (var offset in StartingOffsets)
|
|
{
|
|
if (offset + bytes.Length > Data.Length)
|
|
break;
|
|
|
|
var strSpan = dataSpan[offset..];
|
|
var match = true;
|
|
for (var i = 0; i < bytes.Length; ++i)
|
|
{
|
|
if (strSpan[i] != bytes[i])
|
|
{
|
|
match = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (match && strSpan[bytes.Length] == 0)
|
|
return (offset, bytes.Length);
|
|
}
|
|
|
|
Data.Seek(0L, SeekOrigin.End);
|
|
var newOffset = (int)Data.Position;
|
|
StartingOffsets.Add(newOffset);
|
|
Data.Write(bytes);
|
|
Data.WriteByte(0);
|
|
return (newOffset, bytes.Length);
|
|
}
|
|
}
|
|
}
|