mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
BCAT fixes. Tweak how U8StringBuilder is used
This commit is contained in:
parent
6e4372ce58
commit
f3452bb314
15 changed files with 200 additions and 109 deletions
|
@ -32,7 +32,7 @@ namespace LibHac.Bcat
|
||||||
|
|
||||||
public Result GetServiceCreator(out IServiceCreator serviceCreator, BcatServiceType type)
|
public Result GetServiceCreator(out IServiceCreator serviceCreator, BcatServiceType type)
|
||||||
{
|
{
|
||||||
if ((uint)type < ServiceTypeCount)
|
if ((uint)type >= ServiceTypeCount)
|
||||||
{
|
{
|
||||||
serviceCreator = default;
|
serviceCreator = default;
|
||||||
return ResultLibHac.ArgumentOutOfRange.Log();
|
return ResultLibHac.ArgumentOutOfRange.Log();
|
||||||
|
@ -87,6 +87,9 @@ namespace LibHac.Bcat
|
||||||
if (!rc.IsSuccess())
|
if (!rc.IsSuccess())
|
||||||
throw new HorizonResultException(rc, "Abort");
|
throw new HorizonResultException(rc, "Abort");
|
||||||
|
|
||||||
|
fsClient.SetAccessLogTarget(AccessLogTarget.All);
|
||||||
|
|
||||||
|
FsClient = fsClient;
|
||||||
return fsClient;
|
return fsClient;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace LibHac.Bcat.Detail.Ipc
|
namespace LibHac.Bcat.Detail.Ipc
|
||||||
{
|
{
|
||||||
public interface IDeliveryCacheDirectoryService
|
public interface IDeliveryCacheDirectoryService : IDisposable
|
||||||
{
|
{
|
||||||
Result Open(ref DirectoryName name);
|
Result Open(ref DirectoryName name);
|
||||||
Result Read(out int entriesRead, Span<DeliveryCacheDirectoryEntry> entryBuffer);
|
Result Read(out int entriesRead, Span<DeliveryCacheDirectoryEntry> entryBuffer);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace LibHac.Bcat.Detail.Ipc
|
namespace LibHac.Bcat.Detail.Ipc
|
||||||
{
|
{
|
||||||
public interface IDeliveryCacheFileService
|
public interface IDeliveryCacheFileService : IDisposable
|
||||||
{
|
{
|
||||||
Result Open(ref DirectoryName directoryName, ref FileName fileName);
|
Result Open(ref DirectoryName directoryName, ref FileName fileName);
|
||||||
Result Read(out long bytesRead, long offset, Span<byte> destination);
|
Result Read(out long bytesRead, long offset, Span<byte> destination);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace LibHac.Bcat.Detail.Ipc
|
namespace LibHac.Bcat.Detail.Ipc
|
||||||
{
|
{
|
||||||
public interface IDeliveryCacheStorageService
|
public interface IDeliveryCacheStorageService : IDisposable
|
||||||
{
|
{
|
||||||
Result CreateFileService(out IDeliveryCacheFileService fileService);
|
Result CreateFileService(out IDeliveryCacheFileService fileService);
|
||||||
Result CreateDirectoryService(out IDeliveryCacheDirectoryService directoryService);
|
Result CreateDirectoryService(out IDeliveryCacheDirectoryService directoryService);
|
||||||
|
|
|
@ -48,8 +48,8 @@ namespace LibHac.Bcat.Detail.Service.Core
|
||||||
// Get the mount name
|
// Get the mount name
|
||||||
var mountName = new MountName();
|
var mountName = new MountName();
|
||||||
|
|
||||||
new U8StringBuilder(mountName.Name)
|
var sb = new U8StringBuilder(mountName.Name);
|
||||||
.Append(DeliveryCacheMountNamePrefix)
|
sb.Append(DeliveryCacheMountNamePrefix)
|
||||||
.AppendFormat(index, 'd', 2);
|
.AppendFormat(index, 'd', 2);
|
||||||
|
|
||||||
// Mount the save if enabled
|
// Mount the save if enabled
|
||||||
|
@ -89,8 +89,8 @@ namespace LibHac.Bcat.Detail.Service.Core
|
||||||
{
|
{
|
||||||
var mountName = new MountName();
|
var mountName = new MountName();
|
||||||
|
|
||||||
new U8StringBuilder(mountName.Name)
|
var sb = new U8StringBuilder(mountName.Name);
|
||||||
.Append(DeliveryCacheMountNamePrefix)
|
sb.Append(DeliveryCacheMountNamePrefix)
|
||||||
.AppendFormat(index, 'd', 2);
|
.AppendFormat(index, 'd', 2);
|
||||||
|
|
||||||
// Unmount the entry's savedata
|
// Unmount the entry's savedata
|
||||||
|
@ -115,8 +115,8 @@ namespace LibHac.Bcat.Detail.Service.Core
|
||||||
|
|
||||||
var mountName = new MountName();
|
var mountName = new MountName();
|
||||||
|
|
||||||
new U8StringBuilder(mountName.Name)
|
var sb = new U8StringBuilder(mountName.Name);
|
||||||
.Append(DeliveryCacheMountNamePrefix)
|
sb.Append(DeliveryCacheMountNamePrefix)
|
||||||
.AppendFormat(index, 'd', 2);
|
.AppendFormat(index, 'd', 2);
|
||||||
|
|
||||||
if (!DisableStorage)
|
if (!DisableStorage)
|
||||||
|
@ -215,10 +215,10 @@ namespace LibHac.Bcat.Detail.Service.Core
|
||||||
var sb = new U8StringBuilder(pathBuffer);
|
var sb = new U8StringBuilder(pathBuffer);
|
||||||
AppendMountName(ref sb, applicationId);
|
AppendMountName(ref sb, applicationId);
|
||||||
|
|
||||||
sb.Append(DirectoriesPath);
|
sb.Append(DirectoriesPath)
|
||||||
sb.Append(DirectorySeparator).Append(directoryName.Bytes);
|
.Append(DirectorySeparator).Append(directoryName.Bytes)
|
||||||
sb.Append(DirectorySeparator).Append(FilesDirectoryName);
|
.Append(DirectorySeparator).Append(FilesDirectoryName)
|
||||||
sb.Append(DirectorySeparator).Append(fileName.Bytes);
|
.Append(DirectorySeparator).Append(fileName.Bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,9 +229,9 @@ namespace LibHac.Bcat.Detail.Service.Core
|
||||||
var sb = new U8StringBuilder(pathBuffer);
|
var sb = new U8StringBuilder(pathBuffer);
|
||||||
AppendMountName(ref sb, applicationId);
|
AppendMountName(ref sb, applicationId);
|
||||||
|
|
||||||
sb.Append(DirectoriesPath);
|
sb.Append(DirectoriesPath)
|
||||||
sb.Append(DirectorySeparator).Append(directoryName.Bytes);
|
.Append(DirectorySeparator).Append(directoryName.Bytes)
|
||||||
sb.Append(DirectorySeparator).Append(FilesMetaFileName);
|
.Append(DirectorySeparator).Append(FilesMetaFileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,8 +252,8 @@ namespace LibHac.Bcat.Detail.Service.Core
|
||||||
var sb = new U8StringBuilder(pathBuffer);
|
var sb = new U8StringBuilder(pathBuffer);
|
||||||
AppendMountName(ref sb, applicationId);
|
AppendMountName(ref sb, applicationId);
|
||||||
|
|
||||||
sb.Append(DirectoriesPath);
|
sb.Append(DirectoriesPath)
|
||||||
sb.Append(DirectorySeparator).Append(directoryName.Bytes);
|
.Append(DirectorySeparator).Append(directoryName.Bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,13 @@ using LibHac.Bcat.Detail.Service.Core;
|
||||||
|
|
||||||
namespace LibHac.Bcat.Detail.Service
|
namespace LibHac.Bcat.Detail.Service
|
||||||
{
|
{
|
||||||
internal class DeliveryCacheDirectoryService : IDeliveryCacheDirectoryService, IDisposable
|
internal class DeliveryCacheDirectoryService : IDeliveryCacheDirectoryService
|
||||||
{
|
{
|
||||||
private BcatServer Server { get; }
|
private BcatServer Server { get; }
|
||||||
private object Locker { get; } = new object();
|
private object Locker { get; } = new object();
|
||||||
private DeliveryCacheStorageService Parent { get; }
|
private DeliveryCacheStorageService Parent { get; }
|
||||||
|
|
||||||
|
// ReSharper disable once UnusedAutoPropertyAccessor.Local
|
||||||
private AccessControl Access { get; }
|
private AccessControl Access { get; }
|
||||||
private ulong ApplicationId { get; }
|
private ulong ApplicationId { get; }
|
||||||
private DirectoryName _name;
|
private DirectoryName _name;
|
||||||
|
|
|
@ -6,11 +6,13 @@ using LibHac.Fs;
|
||||||
|
|
||||||
namespace LibHac.Bcat.Detail.Service
|
namespace LibHac.Bcat.Detail.Service
|
||||||
{
|
{
|
||||||
internal class DeliveryCacheFileService : IDeliveryCacheFileService, IDisposable
|
internal class DeliveryCacheFileService : IDeliveryCacheFileService
|
||||||
{
|
{
|
||||||
private BcatServer Server { get; }
|
private BcatServer Server { get; }
|
||||||
private object Locker { get; } = new object();
|
private object Locker { get; } = new object();
|
||||||
private DeliveryCacheStorageService Parent { get; }
|
private DeliveryCacheStorageService Parent { get; }
|
||||||
|
|
||||||
|
// ReSharper disable once UnusedAutoPropertyAccessor.Local
|
||||||
private AccessControl Access { get; }
|
private AccessControl Access { get; }
|
||||||
private ulong ApplicationId { get; }
|
private ulong ApplicationId { get; }
|
||||||
private FileHandle _handle;
|
private FileHandle _handle;
|
||||||
|
|
|
@ -4,12 +4,12 @@ using LibHac.Bcat.Detail.Ipc;
|
||||||
|
|
||||||
namespace LibHac.Bcat.Detail.Service
|
namespace LibHac.Bcat.Detail.Service
|
||||||
{
|
{
|
||||||
internal class DeliveryCacheStorageService : IDeliveryCacheStorageService, IDisposable
|
internal class DeliveryCacheStorageService : IDeliveryCacheStorageService
|
||||||
{
|
{
|
||||||
private const int MaxOpenCount = 8;
|
private const int MaxOpenCount = 8;
|
||||||
private BcatServer Server { get; }
|
private BcatServer Server { get; }
|
||||||
|
|
||||||
public object Locker { get; } = new object();
|
private object Locker { get; } = new object();
|
||||||
private AccessControl Access { get; }
|
private AccessControl Access { get; }
|
||||||
private ulong ApplicationId { get; }
|
private ulong ApplicationId { get; }
|
||||||
private int FileServiceOpenCount { get; set; }
|
private int FileServiceOpenCount { get; set; }
|
||||||
|
|
|
@ -6,6 +6,8 @@ namespace LibHac.Bcat.Detail.Service
|
||||||
internal class ServiceCreator : IServiceCreator
|
internal class ServiceCreator : IServiceCreator
|
||||||
{
|
{
|
||||||
private BcatServer Server { get; }
|
private BcatServer Server { get; }
|
||||||
|
|
||||||
|
// ReSharper disable once UnusedAutoPropertyAccessor.Local
|
||||||
private BcatServiceType ServiceType { get; }
|
private BcatServiceType ServiceType { get; }
|
||||||
private AccessControl AccessControl { get; }
|
private AccessControl AccessControl { get; }
|
||||||
|
|
||||||
|
@ -35,16 +37,9 @@ namespace LibHac.Bcat.Detail.Service
|
||||||
Result rc = Server.GetStorageManager().Open(applicationId.Value);
|
Result rc = Server.GetStorageManager().Open(applicationId.Value);
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// todo: Check if network account required
|
// todo: Check if network account required
|
||||||
|
|
||||||
service = new DeliveryCacheStorageService(Server, applicationId.Value, AccessControl);
|
service = new DeliveryCacheStorageService(Server, applicationId.Value, AccessControl);
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Server.GetStorageManager().Release(applicationId.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,7 +171,7 @@ namespace LibHac.Common
|
||||||
|
|
||||||
public static bool IsAlpha(byte c)
|
public static bool IsAlpha(byte c)
|
||||||
{
|
{
|
||||||
return (c | 0x20u) - (byte)'A' <= 'Z' - 'A';
|
return (c | 0x20u) - (byte)'a' <= 'z' - 'a';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsDigit(byte c)
|
public static bool IsDigit(byte c)
|
||||||
|
|
|
@ -10,18 +10,15 @@ namespace LibHac.Common
|
||||||
{
|
{
|
||||||
private const int NullTerminatorLength = 1;
|
private const int NullTerminatorLength = 1;
|
||||||
|
|
||||||
private readonly Span<byte> _buffer;
|
public Span<byte> Buffer { get; }
|
||||||
private int _length;
|
public int Length { get; private set; }
|
||||||
|
|
||||||
public bool Overflowed { get; private set; }
|
public bool Overflowed { get; private set; }
|
||||||
public readonly int Length => _length;
|
public readonly int Capacity => Buffer.Length - NullTerminatorLength;
|
||||||
public readonly int Capacity => _buffer.Length - NullTerminatorLength;
|
|
||||||
public readonly Span<byte> Buffer => _buffer;
|
|
||||||
|
|
||||||
public U8StringBuilder(Span<byte> buffer)
|
public U8StringBuilder(Span<byte> buffer)
|
||||||
{
|
{
|
||||||
_buffer = buffer;
|
Buffer = buffer;
|
||||||
_length = 0;
|
Length = 0;
|
||||||
Overflowed = false;
|
Overflowed = false;
|
||||||
|
|
||||||
ThrowIfBufferLengthIsZero();
|
ThrowIfBufferLengthIsZero();
|
||||||
|
@ -29,70 +26,69 @@ namespace LibHac.Common
|
||||||
AddNullTerminator();
|
AddNullTerminator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public U8StringBuilder Append(ReadOnlySpan<byte> value)
|
// These functions are internal so they can be called by the extension methods
|
||||||
|
// in U8StringBuilderExtensions. It's not an ideal setup, but it allows append
|
||||||
|
// calls to be chained without accidentally creating a copy of the U8StringBuilder.
|
||||||
|
internal void AppendInternal(ReadOnlySpan<byte> value)
|
||||||
{
|
{
|
||||||
if (Overflowed) return this;
|
if (Overflowed) return;
|
||||||
|
|
||||||
int valueLength = StringUtils.GetLength(value);
|
int valueLength = StringUtils.GetLength(value);
|
||||||
|
|
||||||
if (!HasAdditionalCapacity(valueLength))
|
if (!HasAdditionalCapacity(valueLength))
|
||||||
{
|
{
|
||||||
Overflowed = true;
|
Overflowed = true;
|
||||||
return this;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
value.Slice(0, valueLength).CopyTo(_buffer.Slice(_length));
|
value.Slice(0, valueLength).CopyTo(Buffer.Slice(Length));
|
||||||
_length += valueLength;
|
Length += valueLength;
|
||||||
AddNullTerminator();
|
AddNullTerminator();
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public U8StringBuilder Append(byte value)
|
internal void AppendInternal(byte value)
|
||||||
{
|
{
|
||||||
if (Overflowed) return this;
|
if (Overflowed) return;
|
||||||
|
|
||||||
if (!HasAdditionalCapacity(1))
|
if (!HasAdditionalCapacity(1))
|
||||||
{
|
{
|
||||||
Overflowed = true;
|
Overflowed = true;
|
||||||
return this;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_buffer[_length] = value;
|
Buffer[Length] = value;
|
||||||
_length++;
|
Length++;
|
||||||
AddNullTerminator();
|
AddNullTerminator();
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public U8StringBuilder AppendFormat(byte value, char format = 'G', byte precision = 255) =>
|
internal void AppendFormatInternal(byte value, char format = 'G', byte precision = 255) =>
|
||||||
AppendFormatUInt64(value, format, precision);
|
AppendFormatUInt64(value, format, precision);
|
||||||
|
|
||||||
public U8StringBuilder AppendFormat(sbyte value, char format = 'G', byte precision = 255) =>
|
internal void AppendFormatInternal(sbyte value, char format = 'G', byte precision = 255) =>
|
||||||
AppendFormatInt64(value, 0xff, format, precision);
|
AppendFormatInt64(value, 0xff, format, precision);
|
||||||
|
|
||||||
public U8StringBuilder AppendFormat(ushort value, char format = 'G', byte precision = 255) =>
|
internal void AppendFormatInternal(ushort value, char format = 'G', byte precision = 255) =>
|
||||||
AppendFormatUInt64(value, format, precision);
|
AppendFormatUInt64(value, format, precision);
|
||||||
|
|
||||||
public U8StringBuilder AppendFormat(short value, char format = 'G', byte precision = 255) =>
|
internal void AppendFormatInternal(short value, char format = 'G', byte precision = 255) =>
|
||||||
AppendFormatInt64(value, 0xffff, format, precision);
|
AppendFormatInt64(value, 0xffff, format, precision);
|
||||||
|
|
||||||
public U8StringBuilder AppendFormat(uint value, char format = 'G', byte precision = 255) =>
|
internal void AppendFormatInternal(uint value, char format = 'G', byte precision = 255) =>
|
||||||
AppendFormatUInt64(value, format, precision);
|
AppendFormatUInt64(value, format, precision);
|
||||||
|
|
||||||
public U8StringBuilder AppendFormat(int value, char format = 'G', byte precision = 255) =>
|
internal void AppendFormatInternal(int value, char format = 'G', byte precision = 255) =>
|
||||||
AppendFormatInt64(value, 0xffffff, format, precision);
|
AppendFormatInt64(value, 0xffffff, format, precision);
|
||||||
|
|
||||||
public U8StringBuilder AppendFormat(ulong value, char format = 'G', byte precision = 255) =>
|
internal void AppendFormatInternal(ulong value, char format = 'G', byte precision = 255) =>
|
||||||
AppendFormatUInt64(value, format, precision);
|
AppendFormatUInt64(value, format, precision);
|
||||||
|
|
||||||
public U8StringBuilder AppendFormat(long value, char format = 'G', byte precision = 255) =>
|
internal void AppendFormatInternal(long value, char format = 'G', byte precision = 255) =>
|
||||||
AppendFormatInt64(value, 0xffffffff, format, precision);
|
AppendFormatInt64(value, 0xffffffff, format, precision);
|
||||||
|
|
||||||
public U8StringBuilder AppendFormat(float value, char format = 'G', byte precision = 255) =>
|
internal void AppendFormatInternal(float value, char format = 'G', byte precision = 255) =>
|
||||||
AppendFormatFloat(value, format, precision);
|
AppendFormatFloat(value, format, precision);
|
||||||
|
|
||||||
public U8StringBuilder AppendFormat(double value, char format = 'G', byte precision = 255) =>
|
internal void AppendFormatInternal(double value, char format = 'G', byte precision = 255) =>
|
||||||
AppendFormatDouble(value, format, precision);
|
AppendFormatDouble(value, format, precision);
|
||||||
|
|
||||||
private readonly bool HasCapacity(int requiredCapacity)
|
private readonly bool HasCapacity(int requiredCapacity)
|
||||||
|
@ -102,22 +98,22 @@ namespace LibHac.Common
|
||||||
|
|
||||||
private readonly bool HasAdditionalCapacity(int requiredAdditionalCapacity)
|
private readonly bool HasAdditionalCapacity(int requiredAdditionalCapacity)
|
||||||
{
|
{
|
||||||
return HasCapacity(_length + requiredAdditionalCapacity);
|
return HasCapacity(Length + requiredAdditionalCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddNullTerminator()
|
private void AddNullTerminator()
|
||||||
{
|
{
|
||||||
_buffer[_length] = 0;
|
Buffer[Length] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly void ThrowIfBufferLengthIsZero()
|
private readonly void ThrowIfBufferLengthIsZero()
|
||||||
{
|
{
|
||||||
if (_buffer.Length == 0) throw new ArgumentException("Buffer length must be greater than 0.");
|
if (Buffer.Length == 0) throw new ArgumentException("Buffer length must be greater than 0.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private U8StringBuilder AppendFormatInt64(long value, ulong mask, char format, byte precision)
|
private void AppendFormatInt64(long value, ulong mask, char format, byte precision)
|
||||||
{
|
{
|
||||||
if (Overflowed) return this;
|
if (Overflowed) return;
|
||||||
|
|
||||||
// Remove possible sign extension if needed
|
// Remove possible sign extension if needed
|
||||||
if (mask == 'x' | mask == 'X')
|
if (mask == 'x' | mask == 'X')
|
||||||
|
@ -126,7 +122,7 @@ namespace LibHac.Common
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exclude the null terminator from the buffer because Utf8Formatter doesn't handle it
|
// Exclude the null terminator from the buffer because Utf8Formatter doesn't handle it
|
||||||
Span<byte> availableBuffer = _buffer.Slice(_length, Capacity - _length);
|
Span<byte> availableBuffer = Buffer.Slice(Length, Capacity - Length);
|
||||||
|
|
||||||
bool bufferLargeEnough = Utf8Formatter.TryFormat(value, availableBuffer, out int bytesWritten,
|
bool bufferLargeEnough = Utf8Formatter.TryFormat(value, availableBuffer, out int bytesWritten,
|
||||||
new StandardFormat(format, precision));
|
new StandardFormat(format, precision));
|
||||||
|
@ -134,21 +130,19 @@ namespace LibHac.Common
|
||||||
if (!bufferLargeEnough)
|
if (!bufferLargeEnough)
|
||||||
{
|
{
|
||||||
Overflowed = true;
|
Overflowed = true;
|
||||||
return this;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_length += bytesWritten;
|
Length += bytesWritten;
|
||||||
AddNullTerminator();
|
AddNullTerminator();
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private U8StringBuilder AppendFormatUInt64(ulong value, char format, byte precision)
|
private void AppendFormatUInt64(ulong value, char format, byte precision)
|
||||||
{
|
{
|
||||||
if (Overflowed) return this;
|
if (Overflowed) return;
|
||||||
|
|
||||||
// Exclude the null terminator from the buffer because Utf8Formatter doesn't handle it
|
// Exclude the null terminator from the buffer because Utf8Formatter doesn't handle it
|
||||||
Span<byte> availableBuffer = _buffer.Slice(_length, Capacity - _length);
|
Span<byte> availableBuffer = Buffer.Slice(Length, Capacity - Length);
|
||||||
|
|
||||||
bool bufferLargeEnough = Utf8Formatter.TryFormat(value, availableBuffer, out int bytesWritten,
|
bool bufferLargeEnough = Utf8Formatter.TryFormat(value, availableBuffer, out int bytesWritten,
|
||||||
new StandardFormat(format, precision));
|
new StandardFormat(format, precision));
|
||||||
|
@ -156,21 +150,19 @@ namespace LibHac.Common
|
||||||
if (!bufferLargeEnough)
|
if (!bufferLargeEnough)
|
||||||
{
|
{
|
||||||
Overflowed = true;
|
Overflowed = true;
|
||||||
return this;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_length += bytesWritten;
|
Length += bytesWritten;
|
||||||
AddNullTerminator();
|
AddNullTerminator();
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private U8StringBuilder AppendFormatFloat(float value, char format, byte precision)
|
private void AppendFormatFloat(float value, char format, byte precision)
|
||||||
{
|
{
|
||||||
if (Overflowed) return this;
|
if (Overflowed) return;
|
||||||
|
|
||||||
// Exclude the null terminator from the buffer because Utf8Formatter doesn't handle it
|
// Exclude the null terminator from the buffer because Utf8Formatter doesn't handle it
|
||||||
Span<byte> availableBuffer = _buffer.Slice(_length, Capacity - _length);
|
Span<byte> availableBuffer = Buffer.Slice(Length, Capacity - Length);
|
||||||
|
|
||||||
bool bufferLargeEnough = Utf8Formatter.TryFormat(value, availableBuffer, out int bytesWritten,
|
bool bufferLargeEnough = Utf8Formatter.TryFormat(value, availableBuffer, out int bytesWritten,
|
||||||
new StandardFormat(format, precision));
|
new StandardFormat(format, precision));
|
||||||
|
@ -178,21 +170,19 @@ namespace LibHac.Common
|
||||||
if (!bufferLargeEnough)
|
if (!bufferLargeEnough)
|
||||||
{
|
{
|
||||||
Overflowed = true;
|
Overflowed = true;
|
||||||
return this;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_length += bytesWritten;
|
Length += bytesWritten;
|
||||||
AddNullTerminator();
|
AddNullTerminator();
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private U8StringBuilder AppendFormatDouble(double value, char format, byte precision)
|
private void AppendFormatDouble(double value, char format, byte precision)
|
||||||
{
|
{
|
||||||
if (Overflowed) return this;
|
if (Overflowed) return;
|
||||||
|
|
||||||
// Exclude the null terminator from the buffer because Utf8Formatter doesn't handle it
|
// Exclude the null terminator from the buffer because Utf8Formatter doesn't handle it
|
||||||
Span<byte> availableBuffer = _buffer.Slice(_length, Capacity - _length);
|
Span<byte> availableBuffer = Buffer.Slice(Length, Capacity - Length);
|
||||||
|
|
||||||
bool bufferLargeEnough = Utf8Formatter.TryFormat(value, availableBuffer, out int bytesWritten,
|
bool bufferLargeEnough = Utf8Formatter.TryFormat(value, availableBuffer, out int bytesWritten,
|
||||||
new StandardFormat(format, precision));
|
new StandardFormat(format, precision));
|
||||||
|
@ -200,15 +190,98 @@ namespace LibHac.Common
|
||||||
if (!bufferLargeEnough)
|
if (!bufferLargeEnough)
|
||||||
{
|
{
|
||||||
Overflowed = true;
|
Overflowed = true;
|
||||||
return this;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_length += bytesWritten;
|
Length += bytesWritten;
|
||||||
AddNullTerminator();
|
AddNullTerminator();
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override readonly string ToString() => StringUtils.Utf8ZToString(_buffer);
|
public override readonly string ToString() => StringUtils.Utf8ZToString(Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class U8StringBuilderExtensions
|
||||||
|
{
|
||||||
|
public static ref U8StringBuilder Append(this ref U8StringBuilder sb, ReadOnlySpan<byte> value)
|
||||||
|
{
|
||||||
|
sb.AppendInternal(value);
|
||||||
|
return ref sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ref U8StringBuilder Append(this ref U8StringBuilder sb, byte value)
|
||||||
|
{
|
||||||
|
sb.AppendInternal(value);
|
||||||
|
return ref sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ref U8StringBuilder AppendFormat(this ref U8StringBuilder sb, byte value, char format = 'G',
|
||||||
|
byte precision = 255)
|
||||||
|
{
|
||||||
|
sb.AppendFormatInternal(value, format, precision);
|
||||||
|
return ref sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ref U8StringBuilder AppendFormat(this ref U8StringBuilder sb, sbyte value, char format = 'G',
|
||||||
|
byte precision = 255)
|
||||||
|
{
|
||||||
|
sb.AppendFormatInternal(value, format, precision);
|
||||||
|
return ref sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ref U8StringBuilder AppendFormat(this ref U8StringBuilder sb, ushort value, char format = 'G',
|
||||||
|
byte precision = 255)
|
||||||
|
{
|
||||||
|
sb.AppendFormatInternal(value, format, precision);
|
||||||
|
return ref sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ref U8StringBuilder AppendFormat(this ref U8StringBuilder sb, short value, char format = 'G',
|
||||||
|
byte precision = 255)
|
||||||
|
{
|
||||||
|
sb.AppendFormatInternal(value, format, precision);
|
||||||
|
return ref sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ref U8StringBuilder AppendFormat(this ref U8StringBuilder sb, uint value, char format = 'G',
|
||||||
|
byte precision = 255)
|
||||||
|
{
|
||||||
|
sb.AppendFormatInternal(value, format, precision);
|
||||||
|
return ref sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ref U8StringBuilder AppendFormat(this ref U8StringBuilder sb, int value, char format = 'G',
|
||||||
|
byte precision = 255)
|
||||||
|
{
|
||||||
|
sb.AppendFormatInternal(value, format, precision);
|
||||||
|
return ref sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ref U8StringBuilder AppendFormat(this ref U8StringBuilder sb, ulong value, char format = 'G',
|
||||||
|
byte precision = 255)
|
||||||
|
{
|
||||||
|
sb.AppendFormatInternal(value, format, precision);
|
||||||
|
return ref sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ref U8StringBuilder AppendFormat(this ref U8StringBuilder sb, long value, char format = 'G',
|
||||||
|
byte precision = 255)
|
||||||
|
{
|
||||||
|
sb.AppendFormatInternal(value, format, precision);
|
||||||
|
return ref sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ref U8StringBuilder AppendFormat(this ref U8StringBuilder sb, float value, char format = 'G',
|
||||||
|
byte precision = 255)
|
||||||
|
{
|
||||||
|
sb.AppendFormatInternal(value, format, precision);
|
||||||
|
return ref sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ref U8StringBuilder AppendFormat(this ref U8StringBuilder sb, double value, char format = 'G',
|
||||||
|
byte precision = 255)
|
||||||
|
{
|
||||||
|
sb.AppendFormatInternal(value, format, precision);
|
||||||
|
return ref sb;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,10 @@ namespace LibHac.Fs.Shim
|
||||||
|
|
||||||
Debug.Assert(nameBuffer.Length >= requiredNameBufferSize);
|
Debug.Assert(nameBuffer.Length >= requiredNameBufferSize);
|
||||||
|
|
||||||
// ReSharper disable once RedundantAssignment
|
var sb = new U8StringBuilder(nameBuffer);
|
||||||
int size = new U8StringBuilder(nameBuffer).Append(mountName).Append(StringTraits.DriveSeparator).Length;
|
sb.Append(mountName).Append(StringTraits.DriveSeparator);
|
||||||
Debug.Assert(size == requiredNameBufferSize - 1);
|
|
||||||
|
Debug.Assert(sb.Length == requiredNameBufferSize - 1);
|
||||||
|
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
@ -144,7 +145,8 @@ namespace LibHac.Fs.Shim
|
||||||
? StringTraits.NullTerminator
|
? StringTraits.NullTerminator
|
||||||
: StringTraits.DirectorySeparator;
|
: StringTraits.DirectorySeparator;
|
||||||
|
|
||||||
Result rc = new U8StringBuilder(sfPath.Str).Append(rootPath).Append(endingSeparator).ToSfPath();
|
var sb = new U8StringBuilder(sfPath.Str);
|
||||||
|
Result rc = sb.Append(rootPath).Append(endingSeparator).ToSfPath();
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -43,9 +43,10 @@ namespace LibHac.Fs.Shim
|
||||||
if (nameBuffer.Length < requiredNameBufferSize)
|
if (nameBuffer.Length < requiredNameBufferSize)
|
||||||
return ResultFs.TooLongPath.Log();
|
return ResultFs.TooLongPath.Log();
|
||||||
|
|
||||||
// ReSharper disable once RedundantAssignment
|
var sb = new U8StringBuilder(nameBuffer);
|
||||||
int size = new U8StringBuilder(nameBuffer).Append(HostRootFileSystemPath).Append(_path.Str).Length;
|
sb.Append(HostRootFileSystemPath).Append(_path.Str);
|
||||||
Debug.Assert(size == requiredNameBufferSize - 1);
|
|
||||||
|
Debug.Assert(sb.Length == requiredNameBufferSize - 1);
|
||||||
|
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,10 @@ namespace LibHac.FsSystem
|
||||||
{
|
{
|
||||||
fsPath = new FsPath();
|
fsPath = new FsPath();
|
||||||
|
|
||||||
U8StringBuilder builder = new U8StringBuilder(fsPath.Str).Append(path);
|
var sb = new U8StringBuilder(fsPath.Str);
|
||||||
|
bool overflowed = sb.Append(path).Overflowed;
|
||||||
|
|
||||||
return builder.Overflowed ? ResultFs.TooLongPath.Log() : Result.Success;
|
return overflowed ? ResultFs.TooLongPath.Log() : Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
|
|
@ -10,14 +10,14 @@ namespace LibHac
|
||||||
public class Horizon
|
public class Horizon
|
||||||
{
|
{
|
||||||
internal ITimeSpanGenerator Time { get; }
|
internal ITimeSpanGenerator Time { get; }
|
||||||
private FileSystemServer FileSystemServer { get; set; }
|
public FileSystemServer FileSystemServer { get; private set; }
|
||||||
private BcatServer BcatServer { get; set; }
|
public BcatServer BcatServer { get; private set; }
|
||||||
|
|
||||||
private readonly object _initLocker = new object();
|
private readonly object _initLocker = new object();
|
||||||
|
|
||||||
public Horizon(ITimeSpanGenerator timer)
|
public Horizon(ITimeSpanGenerator timer)
|
||||||
{
|
{
|
||||||
Time = timer;
|
Time = timer ?? new StopWatchTimeSpanGenerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result OpenFileSystemProxyService(out IFileSystemProxy service)
|
public Result OpenFileSystemProxyService(out IFileSystemProxy service)
|
||||||
|
@ -60,6 +60,18 @@ namespace LibHac
|
||||||
return BcatServer.GetServiceCreator(out service, type);
|
return BcatServer.GetServiceCreator(out service, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void InitializeBcatServer()
|
||||||
|
{
|
||||||
|
if (BcatServer != null) return;
|
||||||
|
|
||||||
|
lock (_initLocker)
|
||||||
|
{
|
||||||
|
if (BcatServer != null) return;
|
||||||
|
|
||||||
|
BcatServer = new BcatServer(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void InitializeFileSystemServer(FileSystemCreators fsCreators, IDeviceOperator deviceOperator)
|
public void InitializeFileSystemServer(FileSystemCreators fsCreators, IDeviceOperator deviceOperator)
|
||||||
{
|
{
|
||||||
if (FileSystemServer != null) return;
|
if (FileSystemServer != null) return;
|
||||||
|
|
Loading…
Reference in a new issue