mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add DeleteFile to savedata
This commit is contained in:
parent
b1997806c1
commit
9c0e6030e5
5 changed files with 129 additions and 9 deletions
|
@ -62,13 +62,23 @@ namespace LibHac.IO.Save
|
||||||
|
|
||||||
public int GetFreeListBlockIndex()
|
public int GetFreeListBlockIndex()
|
||||||
{
|
{
|
||||||
AllocationTableEntry freeList = ReadEntry(FreeListEntryIndex);
|
return EntryIndexToBlock(GetFreeListEntryIndex());
|
||||||
return EntryIndexToBlock(freeList.GetNext());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetFreeListBlockIndex(int headBlockIndex)
|
public void SetFreeListBlockIndex(int headBlockIndex)
|
||||||
{
|
{
|
||||||
var freeList = new AllocationTableEntry() { Next = BlockToEntryIndex(headBlockIndex) };
|
SetFreeListEntryIndex(BlockToEntryIndex(headBlockIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetFreeListEntryIndex()
|
||||||
|
{
|
||||||
|
AllocationTableEntry freeList = ReadEntry(FreeListEntryIndex);
|
||||||
|
return freeList.GetNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetFreeListEntryIndex(int headBlockIndex)
|
||||||
|
{
|
||||||
|
var freeList = new AllocationTableEntry { Next = headBlockIndex };
|
||||||
WriteEntry(FreeListEntryIndex, freeList);
|
WriteEntry(FreeListEntryIndex, freeList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,11 +99,35 @@ namespace LibHac.IO.Save
|
||||||
return freeList;
|
return freeList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Free(int listBlockIndex)
|
||||||
|
{
|
||||||
|
int listEntryIndex = BlockToEntryIndex(listBlockIndex);
|
||||||
|
AllocationTableEntry listEntry = ReadEntry(listEntryIndex);
|
||||||
|
|
||||||
|
if (!listEntry.IsListStart())
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(listBlockIndex), "The block to free must be the start of a list.");
|
||||||
|
}
|
||||||
|
|
||||||
|
int freeListIndex = GetFreeListEntryIndex();
|
||||||
|
|
||||||
|
// Free list is empty
|
||||||
|
if (freeListIndex == 0)
|
||||||
|
{
|
||||||
|
SetFreeListEntryIndex(listEntryIndex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Join(listBlockIndex, EntryIndexToBlock(freeListIndex));
|
||||||
|
|
||||||
|
SetFreeListBlockIndex(listBlockIndex);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Combines 2 lists into one list. The second list will be attached to the end of the first list.
|
/// Combines 2 lists into one list. The second list will be attached to the end of the first list.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="frontListBlockIndex">The index of the first block.</param>
|
/// <param name="frontListBlockIndex">The index of the start block of the first list.</param>
|
||||||
/// <param name="backListBlockIndex">The index of the second block.</param>
|
/// <param name="backListBlockIndex">The index of the start block of the second list.</param>
|
||||||
public void Join(int frontListBlockIndex, int backListBlockIndex)
|
public void Join(int frontListBlockIndex, int backListBlockIndex)
|
||||||
{
|
{
|
||||||
int frontEntryIndex = BlockToEntryIndex(frontListBlockIndex);
|
int frontEntryIndex = BlockToEntryIndex(frontListBlockIndex);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace LibHac.IO.Save
|
namespace LibHac.IO.Save
|
||||||
|
@ -43,7 +44,7 @@ namespace LibHac.IO.Save
|
||||||
|
|
||||||
Span<byte> nameBytes = stackalloc byte[FileTable.MaxNameLength];
|
Span<byte> nameBytes = stackalloc byte[FileTable.MaxNameLength];
|
||||||
|
|
||||||
bool success = FileTable.TryGetValue((int)position.NextFile, out TableEntry<SaveFileInfo> entry, ref nameBytes);
|
bool success = FileTable.TryGetValue(position.NextFile, out TableEntry<SaveFileInfo> entry, ref nameBytes);
|
||||||
|
|
||||||
// todo error message
|
// todo error message
|
||||||
if (!success)
|
if (!success)
|
||||||
|
@ -140,7 +141,7 @@ namespace LibHac.IO.Save
|
||||||
|
|
||||||
DirectoryTable.GetValue(prevIndex, out TableEntry<SaveFindPosition> parentEntry);
|
DirectoryTable.GetValue(prevIndex, out TableEntry<SaveFindPosition> parentEntry);
|
||||||
|
|
||||||
fileEntry.NextSibling = (int)parentEntry.Value.NextFile;
|
fileEntry.NextSibling = parentEntry.Value.NextFile;
|
||||||
parentEntry.Value.NextFile = index;
|
parentEntry.Value.NextFile = index;
|
||||||
|
|
||||||
DirectoryTable.SetValue(prevIndex, ref parentEntry);
|
DirectoryTable.SetValue(prevIndex, ref parentEntry);
|
||||||
|
@ -151,6 +152,54 @@ namespace LibHac.IO.Save
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DeleteFile(string path)
|
||||||
|
{
|
||||||
|
path = PathTools.Normalize(path);
|
||||||
|
ReadOnlySpan<byte> pathBytes = Util.GetUtf8Bytes(path);
|
||||||
|
|
||||||
|
FindPathRecursive(pathBytes, out SaveEntryKey key);
|
||||||
|
int parentIndex = key.Parent;
|
||||||
|
|
||||||
|
DirectoryTable.GetValue(parentIndex, out TableEntry<SaveFindPosition> parentEntry);
|
||||||
|
|
||||||
|
int toDeleteIndex = FileTable.GetIndexFromKey(ref key).Index;
|
||||||
|
if (toDeleteIndex < 0) throw new FileNotFoundException();
|
||||||
|
|
||||||
|
FileTable.GetValue(toDeleteIndex, out TableEntry<SaveFileInfo> toDeleteEntry);
|
||||||
|
|
||||||
|
if (parentEntry.Value.NextFile == toDeleteIndex)
|
||||||
|
{
|
||||||
|
parentEntry.Value.NextFile = toDeleteEntry.NextSibling;
|
||||||
|
DirectoryTable.SetValue(parentIndex, ref parentEntry);
|
||||||
|
FileTable.Remove(ref key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int prevIndex = parentEntry.Value.NextFile;
|
||||||
|
FileTable.GetValue(prevIndex, out TableEntry<SaveFileInfo> prevEntry);
|
||||||
|
int curIndex = prevEntry.NextSibling;
|
||||||
|
|
||||||
|
while (curIndex != 0)
|
||||||
|
{
|
||||||
|
FileTable.GetValue(curIndex, out TableEntry<SaveFileInfo> curEntry);
|
||||||
|
|
||||||
|
if (curIndex == toDeleteIndex)
|
||||||
|
{
|
||||||
|
prevEntry.NextSibling = curEntry.NextSibling;
|
||||||
|
FileTable.SetValue(prevIndex, ref prevEntry);
|
||||||
|
|
||||||
|
FileTable.Remove(ref key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
prevIndex = curIndex;
|
||||||
|
prevEntry = curEntry;
|
||||||
|
curIndex = prevEntry.NextSibling;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new FileNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
public bool TryOpenDirectory(string path, out SaveFindPosition position)
|
public bool TryOpenDirectory(string path, out SaveFindPosition position)
|
||||||
{
|
{
|
||||||
if (!FindPathRecursive(Util.GetUtf8Bytes(path), out SaveEntryKey key))
|
if (!FindPathRecursive(Util.GetUtf8Bytes(path), out SaveEntryKey key))
|
||||||
|
|
|
@ -51,7 +51,19 @@ namespace LibHac.IO.Save
|
||||||
|
|
||||||
public void DeleteFile(string path)
|
public void DeleteFile(string path)
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
path = PathTools.Normalize(path);
|
||||||
|
|
||||||
|
if (!FileTable.TryOpenFile(path, out SaveFileInfo fileInfo))
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileInfo.StartBlock != int.MinValue)
|
||||||
|
{
|
||||||
|
AllocationTable.Free(fileInfo.StartBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
FileTable.DeleteFile(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDirectory OpenDirectory(string path, OpenDirectoryMode mode)
|
public IDirectory OpenDirectory(string path, OpenDirectoryMode mode)
|
||||||
|
|
|
@ -32,6 +32,6 @@ namespace LibHac.IO.Save
|
||||||
/// <summary>The ID of the next directory to be enumerated.</summary>
|
/// <summary>The ID of the next directory to be enumerated.</summary>
|
||||||
public int NextDirectory;
|
public int NextDirectory;
|
||||||
/// <summary>The ID of the next file to be enumerated.</summary>
|
/// <summary>The ID of the next file to be enumerated.</summary>
|
||||||
public long NextFile;
|
public int NextFile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,6 +112,18 @@ namespace LibHac.IO.Save
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Free(int entryIndex)
|
||||||
|
{
|
||||||
|
ReadEntry(FreeListHeadIndex, out SaveFsEntry freeEntry);
|
||||||
|
ReadEntry(entryIndex, out SaveFsEntry entry);
|
||||||
|
|
||||||
|
entry.Next = freeEntry.Next;
|
||||||
|
freeEntry.Next = entryIndex;
|
||||||
|
|
||||||
|
WriteEntry(FreeListHeadIndex, ref freeEntry);
|
||||||
|
WriteEntry(entryIndex, ref entry);
|
||||||
|
}
|
||||||
|
|
||||||
public bool TryGetValue(ref SaveEntryKey key, out T value)
|
public bool TryGetValue(ref SaveEntryKey key, out T value)
|
||||||
{
|
{
|
||||||
int index = GetIndexFromKey(ref key).Index;
|
int index = GetIndexFromKey(ref key).Index;
|
||||||
|
@ -201,6 +213,19 @@ namespace LibHac.IO.Save
|
||||||
WriteEntry(index, ref entry);
|
WriteEntry(index, ref entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Remove(ref SaveEntryKey key)
|
||||||
|
{
|
||||||
|
(int index, int previousIndex) = GetIndexFromKey(ref key);
|
||||||
|
|
||||||
|
ReadEntry(previousIndex, out SaveFsEntry prevEntry);
|
||||||
|
ReadEntry(index, out SaveFsEntry entryToDel);
|
||||||
|
|
||||||
|
prevEntry.Next = entryToDel.Next;
|
||||||
|
WriteEntry(previousIndex, ref prevEntry);
|
||||||
|
|
||||||
|
Free(index);
|
||||||
|
}
|
||||||
|
|
||||||
private int GetListCapacity()
|
private int GetListCapacity()
|
||||||
{
|
{
|
||||||
Span<byte> buf = stackalloc byte[sizeof(int)];
|
Span<byte> buf = stackalloc byte[sizeof(int)];
|
||||||
|
|
Loading…
Reference in a new issue