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()
|
||||
{
|
||||
AllocationTableEntry freeList = ReadEntry(FreeListEntryIndex);
|
||||
return EntryIndexToBlock(freeList.GetNext());
|
||||
return EntryIndexToBlock(GetFreeListEntryIndex());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -89,11 +99,35 @@ namespace LibHac.IO.Save
|
|||
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>
|
||||
/// Combines 2 lists into one list. The second list will be attached to the end of the first list.
|
||||
/// </summary>
|
||||
/// <param name="frontListBlockIndex">The index of the first block.</param>
|
||||
/// <param name="backListBlockIndex">The index of the second block.</param>
|
||||
/// <param name="frontListBlockIndex">The index of the start block of the first list.</param>
|
||||
/// <param name="backListBlockIndex">The index of the start block of the second list.</param>
|
||||
public void Join(int frontListBlockIndex, int backListBlockIndex)
|
||||
{
|
||||
int frontEntryIndex = BlockToEntryIndex(frontListBlockIndex);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace LibHac.IO.Save
|
||||
|
@ -43,7 +44,7 @@ namespace LibHac.IO.Save
|
|||
|
||||
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
|
||||
if (!success)
|
||||
|
@ -140,7 +141,7 @@ namespace LibHac.IO.Save
|
|||
|
||||
DirectoryTable.GetValue(prevIndex, out TableEntry<SaveFindPosition> parentEntry);
|
||||
|
||||
fileEntry.NextSibling = (int)parentEntry.Value.NextFile;
|
||||
fileEntry.NextSibling = parentEntry.Value.NextFile;
|
||||
parentEntry.Value.NextFile = index;
|
||||
|
||||
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)
|
||||
{
|
||||
if (!FindPathRecursive(Util.GetUtf8Bytes(path), out SaveEntryKey key))
|
||||
|
|
|
@ -51,7 +51,19 @@ namespace LibHac.IO.Save
|
|||
|
||||
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)
|
||||
|
|
|
@ -32,6 +32,6 @@ namespace LibHac.IO.Save
|
|||
/// <summary>The ID of the next directory to be enumerated.</summary>
|
||||
public int NextDirectory;
|
||||
/// <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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int index = GetIndexFromKey(ref key).Index;
|
||||
|
@ -201,6 +213,19 @@ namespace LibHac.IO.Save
|
|||
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()
|
||||
{
|
||||
Span<byte> buf = stackalloc byte[sizeof(int)];
|
||||
|
|
Loading…
Reference in a new issue