mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add new IFile
This commit is contained in:
parent
064da36453
commit
e1ff89060c
3 changed files with 218 additions and 7 deletions
|
@ -132,13 +132,6 @@ namespace LibHac.Fs
|
|||
None = 0
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum WriteOptionFlag
|
||||
{
|
||||
None = 0,
|
||||
Flush = 1
|
||||
}
|
||||
|
||||
public enum OperationId
|
||||
{
|
||||
Clear = 0,
|
||||
|
|
179
src/LibHac/Fs/Fsa/IFile2.cs
Normal file
179
src/LibHac/Fs/Fsa/IFile2.cs
Normal file
|
@ -0,0 +1,179 @@
|
|||
using System;
|
||||
using LibHac.Diag;
|
||||
|
||||
namespace LibHac.Fs.Fsa
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public abstract class IFile2 : IDisposable
|
||||
{
|
||||
public Result Read(out long bytesRead, long offset, Span<byte> destination, in ReadOption option)
|
||||
{
|
||||
if (destination.IsEmpty)
|
||||
{
|
||||
bytesRead = 0;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
if (offset < 0)
|
||||
{
|
||||
bytesRead = 0;
|
||||
return ResultFs.OutOfRange.Log();
|
||||
}
|
||||
|
||||
if (long.MaxValue - offset < destination.Length)
|
||||
{
|
||||
bytesRead = 0;
|
||||
return ResultFs.OutOfRange.Log();
|
||||
}
|
||||
|
||||
return DoRead(out bytesRead, offset, destination, in option);
|
||||
}
|
||||
|
||||
public Result Read(out long bytesRead, long offset, Span<byte> destination)
|
||||
{
|
||||
return Read(out bytesRead, offset, destination, ReadOption.None);
|
||||
}
|
||||
|
||||
public Result Write(long offset, ReadOnlySpan<byte> source, in WriteOption option)
|
||||
{
|
||||
if (source.IsEmpty)
|
||||
{
|
||||
if (option.HasFlushFlag())
|
||||
{
|
||||
Result rc = Flush();
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
if (offset < 0)
|
||||
return ResultFs.OutOfRange.Log();
|
||||
|
||||
if (long.MaxValue - offset < source.Length)
|
||||
return ResultFs.OutOfRange.Log();
|
||||
|
||||
return DoWrite(offset, source, in option);
|
||||
}
|
||||
|
||||
public Result Flush()
|
||||
{
|
||||
return DoFlush();
|
||||
}
|
||||
|
||||
public Result SetSize(long size)
|
||||
{
|
||||
if (size < 0)
|
||||
return ResultFs.OutOfRange.Log();
|
||||
|
||||
return DoSetSize(size);
|
||||
}
|
||||
|
||||
public Result GetSize(out long size)
|
||||
{
|
||||
return DoGetSize(out size);
|
||||
}
|
||||
|
||||
public Result OperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
return DoOperateRange(outBuffer, operationId, offset, size, inBuffer);
|
||||
}
|
||||
|
||||
public Result OperateRange(OperationId operationId, long offset, long size)
|
||||
{
|
||||
return DoOperateRange(Span<byte>.Empty, operationId, offset, size, ReadOnlySpan<byte>.Empty);
|
||||
}
|
||||
|
||||
protected Result DryRead(out long readableBytes, long offset, long size, in ReadOption option,
|
||||
OpenMode openMode)
|
||||
{
|
||||
// Check that we can read.
|
||||
if (!openMode.HasFlag(OpenMode.Read))
|
||||
{
|
||||
readableBytes = default;
|
||||
return ResultFs.InvalidOpenModeForRead.Log();
|
||||
}
|
||||
|
||||
// Get the file size, and validate our offset.
|
||||
Result rc = GetSize(out long fileSize);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
readableBytes = default;
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (offset > fileSize)
|
||||
{
|
||||
readableBytes = default;
|
||||
return ResultFs.OutOfRange.Log();
|
||||
}
|
||||
|
||||
readableBytes = Math.Min(fileSize - offset, size);
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected Result DrySetSize(long size, OpenMode openMode)
|
||||
{
|
||||
// Check that we can write.
|
||||
if (!openMode.HasFlag(OpenMode.Write))
|
||||
return ResultFs.InvalidOpenModeForWrite.Log();
|
||||
|
||||
Assert.AssertTrue(size >= 0);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected Result DryWrite(out bool needsAppend, long offset, long size, in WriteOption option,
|
||||
OpenMode openMode)
|
||||
{
|
||||
// Check that we can write.
|
||||
if (!openMode.HasFlag(OpenMode.Write))
|
||||
{
|
||||
needsAppend = default;
|
||||
return ResultFs.InvalidOpenModeForWrite.Log();
|
||||
}
|
||||
|
||||
// Get the file size.
|
||||
Result rc = GetSize(out long fileSize);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
needsAppend = default;
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (fileSize < offset + size)
|
||||
{
|
||||
if (!openMode.HasFlag(OpenMode.AllowAppend))
|
||||
{
|
||||
needsAppend = default;
|
||||
return ResultFs.FileExtensionWithoutOpenModeAllowAppend.Log();
|
||||
}
|
||||
|
||||
needsAppend = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
needsAppend = false;
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected abstract Result DoRead(out long bytesRead, long offset, Span<byte> destination, in ReadOption option);
|
||||
protected abstract Result DoWrite(long offset, ReadOnlySpan<byte> source, in WriteOption option);
|
||||
protected abstract Result DoFlush();
|
||||
protected abstract Result DoSetSize(long size);
|
||||
protected abstract Result DoGetSize(out long size);
|
||||
protected abstract Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
ReadOnlySpan<byte> inBuffer);
|
||||
|
||||
protected virtual void Dispose(bool disposing) { }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
39
src/LibHac/Fs/IFile2.cs
Normal file
39
src/LibHac/Fs/IFile2.cs
Normal file
|
@ -0,0 +1,39 @@
|
|||
using System;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
public readonly struct ReadOption
|
||||
{
|
||||
public readonly int Value;
|
||||
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
private ReadOption(int value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public static ReadOption None => default;
|
||||
}
|
||||
|
||||
public readonly struct WriteOption
|
||||
{
|
||||
public readonly WriteOptionFlag Flags;
|
||||
|
||||
private WriteOption(WriteOptionFlag flags)
|
||||
{
|
||||
Flags = flags;
|
||||
}
|
||||
|
||||
public bool HasFlushFlag() => Flags.HasFlag(WriteOptionFlag.Flush);
|
||||
|
||||
public static WriteOption None => default;
|
||||
public static WriteOption Flush => new WriteOption(WriteOptionFlag.Flush);
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum WriteOptionFlag
|
||||
{
|
||||
None = 0,
|
||||
Flush = 1
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue