Add SaveDataFile resizing

This commit is contained in:
Alex Barney 2019-04-20 14:15:00 -04:00
parent 5c84f5c2a4
commit 8914d89b32
3 changed files with 66 additions and 15 deletions

View file

@ -6,7 +6,7 @@ namespace LibHac.IO.Save
{ {
private IStorage BaseStorage { get; } private IStorage BaseStorage { get; }
private int BlockSize { get; } private int BlockSize { get; }
private int InitialBlock { get; } internal int InitialBlock { get; private set; }
private AllocationTable Fat { get; } private AllocationTable Fat { get; }
private long _length; private long _length;
@ -18,7 +18,7 @@ namespace LibHac.IO.Save
Fat = table; Fat = table;
InitialBlock = initialBlock; InitialBlock = initialBlock;
_length = table.GetListLength(initialBlock) * blockSize; _length = initialBlock == -1 ? 0 : table.GetListLength(initialBlock) * blockSize;
} }
protected override void ReadImpl(Span<byte> destination, long offset) protected override void ReadImpl(Span<byte> destination, long offset)
@ -81,5 +81,44 @@ namespace LibHac.IO.Save
} }
public override long GetSize() => _length; public override long GetSize() => _length;
public override void SetSize(long size)
{
int oldBlockCount = (int)Util.DivideByRoundUp(_length, BlockSize);
int newBlockCount = (int)Util.DivideByRoundUp(size, BlockSize);
if (oldBlockCount == newBlockCount) return;
if (oldBlockCount == 0)
{
InitialBlock = Fat.Allocate(newBlockCount);
_length = newBlockCount * BlockSize;
return;
}
if (newBlockCount == 0)
{
Fat.Free(InitialBlock);
InitialBlock = -1;
_length = 0;
return;
}
if (newBlockCount > oldBlockCount)
{
int newBlocks = Fat.Allocate(newBlockCount - oldBlockCount);
Fat.Join(InitialBlock, newBlocks);
}
else
{
int oldBlocks = Fat.Trim(InitialBlock, newBlockCount);
Fat.Free(oldBlocks);
}
_length = newBlockCount * BlockSize;
}
} }
} }

View file

@ -1,18 +1,21 @@
using System; using System;
using System.IO;
namespace LibHac.IO.Save namespace LibHac.IO.Save
{ {
public class SaveDataFile : FileBase public class SaveDataFile : FileBase
{ {
private AllocationTableStorage BaseStorage { get; } private AllocationTableStorage BaseStorage { get; }
private long Offset { get; } private string Path { get; }
private long Size { get; } private HierarchicalSaveFileTable FileTable { get; }
private long Size { get; set; }
public SaveDataFile(AllocationTableStorage baseStorage, long offset, long size, OpenMode mode) public SaveDataFile(AllocationTableStorage baseStorage, string path, HierarchicalSaveFileTable fileTable, long size, OpenMode mode)
{ {
Mode = mode; Mode = mode;
BaseStorage = baseStorage; BaseStorage = baseStorage;
Offset = offset; Path = path;
FileTable = fileTable;
Size = size; Size = size;
} }
@ -20,8 +23,7 @@ namespace LibHac.IO.Save
{ {
int toRead = ValidateReadParamsAndGetSize(destination, offset); int toRead = ValidateReadParamsAndGetSize(destination, offset);
long storageOffset = Offset + offset; BaseStorage.Read(destination.Slice(0, toRead), offset);
BaseStorage.Read(destination.Slice(0, toRead), storageOffset);
return toRead; return toRead;
} }
@ -45,7 +47,22 @@ namespace LibHac.IO.Save
public override void SetSize(long size) public override void SetSize(long size)
{ {
throw new NotImplementedException(); if (size < 0) throw new ArgumentOutOfRangeException(nameof(size));
if (Size == size) return;
BaseStorage.SetSize(size);
if (!FileTable.TryOpenFile(Path, out SaveFileInfo fileInfo))
{
throw new FileNotFoundException();
}
fileInfo.StartBlock = BaseStorage.InitialBlock;
fileInfo.Length = size;
FileTable.AddFile(Path, ref fileInfo);
Size = size;
} }
} }
} }

View file

@ -86,14 +86,9 @@ namespace LibHac.IO.Save
throw new FileNotFoundException(); throw new FileNotFoundException();
} }
if (file.StartBlock < 0)
{
return new NullFile();
}
AllocationTableStorage storage = OpenFatStorage(file.StartBlock); AllocationTableStorage storage = OpenFatStorage(file.StartBlock);
return new SaveDataFile(storage, 0, file.Length, mode); return new SaveDataFile(storage, path, FileTable, file.Length, mode);
} }
public void RenameDirectory(string srcPath, string dstPath) public void RenameDirectory(string srcPath, string dstPath)