diff --git a/src/LibHac/Fs/RomFs/HierarchicalRomFileTable.cs b/src/LibHac/Fs/RomFs/HierarchicalRomFileTable.cs
index a9b7f033..b73b2efd 100644
--- a/src/LibHac/Fs/RomFs/HierarchicalRomFileTable.cs
+++ b/src/LibHac/Fs/RomFs/HierarchicalRomFileTable.cs
@@ -6,11 +6,13 @@ namespace LibHac.Fs.RomFs
///
/// Represents the file table used by the RomFS format.
///
+ /// The type of the value to be stored for each file entry.
///
/// This file table stores the structure of the file tree in a RomFS.
/// Each file or directory entry is stored in the table using its full path as a key.
/// Once added, a file or directory is assigned an ID that can also be used to retrieve it.
- /// Each file entry contains the size of the file and its offset in the RomFS.
+ /// Each file entry contains a structure of type .
+ /// In a standard RomFS, this includes the size of the file and its offset in the RomFS.
/// Each directory entry contains the IDs for its first child file and first child directory.
///
/// The table is represented by four byte arrays. Two of the arrays contain the hash buckets and
@@ -19,13 +21,13 @@ namespace LibHac.Fs.RomFs
/// Once all files have been added to the table, should be called
/// to optimize the size of the table.
///
- public class HierarchicalRomFileTable
+ public class HierarchicalRomFileTable where T : unmanaged
{
private RomFsDictionary FileTable { get; }
private RomFsDictionary DirectoryTable { get; }
///
- /// Initializes a from an existing table.
+ /// Initializes a from an existing table.
///
///
///
@@ -39,17 +41,17 @@ namespace LibHac.Fs.RomFs
}
///
- /// Initializes a new that has the default initial capacity.
+ /// Initializes a new that has the default initial capacity.
///
public HierarchicalRomFileTable() : this(0, 0) { }
///
- /// Initializes a new that has the specified initial capacity.
+ /// Initializes a new that has the specified initial capacity.
///
/// The initial number of directories that the
- /// can contain.
+ /// can contain.
/// The initial number of files that the
- /// can contain.
+ /// can contain.
public HierarchicalRomFileTable(int directoryCapacity, int fileCapacity)
{
FileTable = new RomFsDictionary(fileCapacity);
@@ -78,7 +80,7 @@ namespace LibHac.Fs.RomFs
return FileTable.GetEntryData().ToArray();
}
- public bool TryOpenFile(string path, out RomFileInfo fileInfo)
+ public bool TryOpenFile(string path, out T fileInfo)
{
FindPathRecursive(Util.GetUtf8Bytes(path), out RomEntryKey key);
@@ -92,7 +94,7 @@ namespace LibHac.Fs.RomFs
return false;
}
- public bool TryOpenFile(int fileId, out RomFileInfo fileInfo)
+ public bool TryOpenFile(int fileId, out T fileInfo)
{
if (FileTable.TryGetValue(fileId, out RomKeyValuePair keyValuePair))
{
@@ -153,7 +155,7 @@ namespace LibHac.Fs.RomFs
/// When this method returns, contains the file's name (Not the full path).
/// if the next file was successfully returned.
/// if there are no more files to enumerate.
- public bool FindNextFile(ref FindPosition position, out RomFileInfo info, out string name)
+ public bool FindNextFile(ref FindPosition position, out T info, out string name)
{
if (position.NextFile == -1)
{
@@ -201,7 +203,7 @@ namespace LibHac.Fs.RomFs
///
/// The full path of the file to be added.
/// The file information to be stored.
- public void AddFile(string path, ref RomFileInfo fileInfo)
+ public void AddFile(string path, ref T fileInfo)
{
path = PathTools.Normalize(path);
ReadOnlySpan pathBytes = Util.GetUtf8Bytes(path);
@@ -288,7 +290,7 @@ namespace LibHac.Fs.RomFs
}
}
- private void CreateFileRecursiveInternal(ReadOnlySpan path, ref RomFileInfo fileInfo)
+ private void CreateFileRecursiveInternal(ReadOnlySpan path, ref T fileInfo)
{
var parser = new PathParser(path);
var key = new RomEntryKey();
@@ -367,18 +369,18 @@ namespace LibHac.Fs.RomFs
}
}
- [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct DirectoryRomEntry
{
public int NextSibling;
public FindPosition Pos;
}
- [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct FileRomEntry
{
public int NextSibling;
- public RomFileInfo Info;
+ public T Info;
}
}
}
diff --git a/src/LibHac/Fs/RomFs/RomFsBuilder.cs b/src/LibHac/Fs/RomFs/RomFsBuilder.cs
index caeed1c0..0d745d31 100644
--- a/src/LibHac/Fs/RomFs/RomFsBuilder.cs
+++ b/src/LibHac/Fs/RomFs/RomFsBuilder.cs
@@ -18,7 +18,7 @@ namespace LibHac.Fs.RomFs
private const int HeaderWithPaddingSize = 0x200;
private List Sources { get; } = new List();
- private HierarchicalRomFileTable FileTable { get; } = new HierarchicalRomFileTable();
+ private HierarchicalRomFileTable FileTable { get; } = new HierarchicalRomFileTable();
private long CurrentOffset { get; set; }
///
diff --git a/src/LibHac/Fs/RomFs/RomFsDictionary.cs b/src/LibHac/Fs/RomFs/RomFsDictionary.cs
index 0b414e1e..ef5827f1 100644
--- a/src/LibHac/Fs/RomFs/RomFsDictionary.cs
+++ b/src/LibHac/Fs/RomFs/RomFsDictionary.cs
@@ -5,7 +5,9 @@ using System.Runtime.InteropServices;
namespace LibHac.Fs.RomFs
{
- internal class RomFsDictionary where T : unmanaged
+ // todo: Change constraint to "unmanaged" after updating to
+ // a newer SDK https://github.com/dotnet/csharplang/issues/1937
+ internal class RomFsDictionary where T : struct
{
private int _count;
private int _length;
@@ -266,7 +268,7 @@ namespace LibHac.Fs.RomFs
{
var offsets = new List(_count);
- int nextStructOffset = (sizeof(int) + Marshal.SizeOf()) / 4;
+ int nextStructOffset = (sizeof(int) + Unsafe.SizeOf()) / 4;
Span data = MemoryMarshal.Cast(Entries.AsSpan());
for (int i = 0; i < Buckets.Length; i++)
diff --git a/src/LibHac/Fs/RomFs/RomFsDirectory.cs b/src/LibHac/Fs/RomFs/RomFsDirectory.cs
index f6faa0ec..982ae423 100644
--- a/src/LibHac/Fs/RomFs/RomFsDirectory.cs
+++ b/src/LibHac/Fs/RomFs/RomFsDirectory.cs
@@ -23,7 +23,7 @@ namespace LibHac.Fs.RomFs
public IEnumerable Read()
{
FindPosition position = InitialPosition;
- HierarchicalRomFileTable tab = ParentFileSystem.FileTable;
+ HierarchicalRomFileTable tab = ParentFileSystem.FileTable;
if (Mode.HasFlag(OpenDirectoryMode.Directories))
{
@@ -47,7 +47,7 @@ namespace LibHac.Fs.RomFs
int count = 0;
FindPosition position = InitialPosition;
- HierarchicalRomFileTable tab = ParentFileSystem.FileTable;
+ HierarchicalRomFileTable tab = ParentFileSystem.FileTable;
if (Mode.HasFlag(OpenDirectoryMode.Directories))
{
diff --git a/src/LibHac/Fs/RomFs/RomFsEntries.cs b/src/LibHac/Fs/RomFs/RomFsEntries.cs
index 3bdd1c56..5c12b8cd 100644
--- a/src/LibHac/Fs/RomFs/RomFsEntries.cs
+++ b/src/LibHac/Fs/RomFs/RomFsEntries.cs
@@ -32,7 +32,9 @@ namespace LibHac.Fs.RomFs
}
}
- internal ref struct RomKeyValuePair where T : unmanaged
+ // todo: Change constraint to "unmanaged" after updating to
+ // a newer SDK https://github.com/dotnet/csharplang/issues/1937
+ internal ref struct RomKeyValuePair where T : struct
{
public RomEntryKey Key;
public int Offset;
diff --git a/src/LibHac/Fs/RomFs/RomFsFileSystem.cs b/src/LibHac/Fs/RomFs/RomFsFileSystem.cs
index a74af539..ee944186 100644
--- a/src/LibHac/Fs/RomFs/RomFsFileSystem.cs
+++ b/src/LibHac/Fs/RomFs/RomFsFileSystem.cs
@@ -6,7 +6,7 @@ namespace LibHac.Fs.RomFs
{
public RomfsHeader Header { get; }
- public HierarchicalRomFileTable FileTable { get; }
+ public HierarchicalRomFileTable FileTable { get; }
private IStorage BaseStorage { get; }
public RomFsFileSystem(IStorage storage)
@@ -19,7 +19,7 @@ namespace LibHac.Fs.RomFs
IStorage fileHashTable = storage.Slice(Header.FileHashTableOffset, Header.FileHashTableSize);
IStorage fileEntryTable = storage.Slice(Header.FileMetaTableOffset, Header.FileMetaTableSize);
- FileTable = new HierarchicalRomFileTable(dirHashTable, dirEntryTable, fileHashTable, fileEntryTable);
+ FileTable = new HierarchicalRomFileTable(dirHashTable, dirEntryTable, fileHashTable, fileEntryTable);
}
public DirectoryEntryType GetEntryType(string path)
diff --git a/src/LibHac/Fs/Save/HierarchicalSaveFileTable.cs b/src/LibHac/Fs/Save/HierarchicalSaveFileTable.cs
index 6aec624a..07b8ac5e 100644
--- a/src/LibHac/Fs/Save/HierarchicalSaveFileTable.cs
+++ b/src/LibHac/Fs/Save/HierarchicalSaveFileTable.cs
@@ -416,6 +416,8 @@ namespace LibHac.Fs.Save
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
+ // todo: Change constraint to "unmanaged" after updating to
+ // a newer SDK https://github.com/dotnet/csharplang/issues/1937
private struct TableEntry where T : struct
{
public int NextSibling;
diff --git a/src/LibHac/Fs/Save/SaveFsList.cs b/src/LibHac/Fs/Save/SaveFsList.cs
index 668bb669..0bf9d428 100644
--- a/src/LibHac/Fs/Save/SaveFsList.cs
+++ b/src/LibHac/Fs/Save/SaveFsList.cs
@@ -6,6 +6,8 @@ using System.Runtime.InteropServices;
namespace LibHac.Fs.Save
{
+ // todo: Change constraint to "unmanaged" after updating to
+ // a newer SDK https://github.com/dotnet/csharplang/issues/1937
internal class SaveFsList where T : struct
{
private const int FreeListHeadIndex = 0;
diff --git a/tests/LibHac.Tests/RomFsTests.cs b/tests/LibHac.Tests/RomFsTests.cs
index 05310b2e..bce481ad 100644
--- a/tests/LibHac.Tests/RomFsTests.cs
+++ b/tests/LibHac.Tests/RomFsTests.cs
@@ -11,7 +11,7 @@ namespace LibHac.Tests
{
const string path = "/a/b";
- var table = new HierarchicalRomFileTable();
+ var table = new HierarchicalRomFileTable();
var item = new RomFileInfo { Length = 1, Offset = 1 };
table.AddFile(path, ref item);
@@ -26,7 +26,7 @@ namespace LibHac.Tests
{
const string path = "/a/b";
- var table = new HierarchicalRomFileTable();
+ var table = new HierarchicalRomFileTable();
var originalItem = new RomFileInfo { Length = 1, Offset = 1 };
var newItem = new RomFileInfo { Length = 1, Offset = 1 };
@@ -42,7 +42,7 @@ namespace LibHac.Tests
[Fact]
public void AddingDirectory()
{
- var table = new HierarchicalRomFileTable();
+ var table = new HierarchicalRomFileTable();
var expectedPosition = new FindPosition { NextDirectory = -1, NextFile = -1 };
table.AddDirectory("/dir");
@@ -55,7 +55,7 @@ namespace LibHac.Tests
[Fact]
public void AddingEmptyPathThrows()
{
- var table = new HierarchicalRomFileTable();
+ var table = new HierarchicalRomFileTable();
var item = new RomFileInfo();
Assert.Throws(() => table.AddFile("", ref item));
@@ -64,7 +64,7 @@ namespace LibHac.Tests
[Fact]
public void OpeningNonexistentFileFails()
{
- var table = new HierarchicalRomFileTable();
+ var table = new HierarchicalRomFileTable();
bool success = table.TryOpenFile("/foo", out _);
Assert.False(success);
@@ -73,7 +73,7 @@ namespace LibHac.Tests
[Fact]
public void OpeningNonexistentDirectoryFails()
{
- var table = new HierarchicalRomFileTable();
+ var table = new HierarchicalRomFileTable();
bool success = table.TryOpenDirectory("/foo", out _);
Assert.False(success);
@@ -82,7 +82,7 @@ namespace LibHac.Tests
[Fact]
public void OpeningFileAsDirectoryFails()
{
- var table = new HierarchicalRomFileTable();
+ var table = new HierarchicalRomFileTable();
var fileInfo = new RomFileInfo();
table.AddFile("/file", ref fileInfo);
@@ -93,7 +93,7 @@ namespace LibHac.Tests
[Fact]
public void OpeningDirectoryAsFileFails()
{
- var table = new HierarchicalRomFileTable();
+ var table = new HierarchicalRomFileTable();
table.AddDirectory("/dir");
bool success = table.TryOpenFile("/dir", out _);
@@ -104,7 +104,7 @@ namespace LibHac.Tests
public void ChildFileIteration()
{
const int fileCount = 10;
- var table = new HierarchicalRomFileTable();
+ var table = new HierarchicalRomFileTable();
for (int i = 0; i < fileCount; i++)
{
@@ -134,7 +134,7 @@ namespace LibHac.Tests
[Fact]
public void ChildFileIterationPeek()
{
- var table = new HierarchicalRomFileTable();
+ var table = new HierarchicalRomFileTable();
var itemA = new RomFileInfo { Length = 1, Offset = 1 };
var itemB = new RomFileInfo { Length = 2, Offset = 2 };
@@ -160,7 +160,7 @@ namespace LibHac.Tests
[Fact]
public void AddingCousinFiles()
{
- var table = new HierarchicalRomFileTable();
+ var table = new HierarchicalRomFileTable();
var itemB1 = new RomFileInfo { Length = 1, Offset = 1 };
var itemB2 = new RomFileInfo { Length = 2, Offset = 2 };
@@ -182,7 +182,7 @@ namespace LibHac.Tests
[Fact]
public void AddingSiblingFiles()
{
- var table = new HierarchicalRomFileTable();
+ var table = new HierarchicalRomFileTable();
var itemC1 = new RomFileInfo { Length = 1, Offset = 1 };
var itemC2 = new RomFileInfo { Length = 2, Offset = 2 };