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)
|
||||
{
|
||||
if ((uint)type < ServiceTypeCount)
|
||||
if ((uint)type >= ServiceTypeCount)
|
||||
{
|
||||
serviceCreator = default;
|
||||
return ResultLibHac.ArgumentOutOfRange.Log();
|
||||
|
@ -87,6 +87,9 @@ namespace LibHac.Bcat
|
|||
if (!rc.IsSuccess())
|
||||
throw new HorizonResultException(rc, "Abort");
|
||||
|
||||
fsClient.SetAccessLogTarget(AccessLogTarget.All);
|
||||
|
||||
FsClient = fsClient;
|
||||
return fsClient;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace LibHac.Bcat.Detail.Ipc
|
||||
{
|
||||
public interface IDeliveryCacheDirectoryService
|
||||
public interface IDeliveryCacheDirectoryService : IDisposable
|
||||
{
|
||||
Result Open(ref DirectoryName name);
|
||||
Result Read(out int entriesRead, Span<DeliveryCacheDirectoryEntry> entryBuffer);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace LibHac.Bcat.Detail.Ipc
|
||||
{
|
||||
public interface IDeliveryCacheFileService
|
||||
public interface IDeliveryCacheFileService : IDisposable
|
||||
{
|
||||
Result Open(ref DirectoryName directoryName, ref FileName fileName);
|
||||
Result Read(out long bytesRead, long offset, Span<byte> destination);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace LibHac.Bcat.Detail.Ipc
|
||||
{
|
||||
public interface IDeliveryCacheStorageService
|
||||
public interface IDeliveryCacheStorageService : IDisposable
|
||||
{
|
||||
Result CreateFileService(out IDeliveryCacheFileService fileService);
|
||||
Result CreateDirectoryService(out IDeliveryCacheDirectoryService directoryService);
|
||||
|
|
|
@ -48,8 +48,8 @@ namespace LibHac.Bcat.Detail.Service.Core
|
|||
// Get the mount name
|
||||
var mountName = new MountName();
|
||||
|
||||
new U8StringBuilder(mountName.Name)
|
||||
.Append(DeliveryCacheMountNamePrefix)
|
||||
var sb = new U8StringBuilder(mountName.Name);
|
||||
sb.Append(DeliveryCacheMountNamePrefix)
|
||||
.AppendFormat(index, 'd', 2);
|
||||
|
||||
// Mount the save if enabled
|
||||
|
@ -89,8 +89,8 @@ namespace LibHac.Bcat.Detail.Service.Core
|
|||
{
|
||||
var mountName = new MountName();
|
||||
|
||||
new U8StringBuilder(mountName.Name)
|
||||
.Append(DeliveryCacheMountNamePrefix)
|
||||
var sb = new U8StringBuilder(mountName.Name);
|
||||
sb.Append(DeliveryCacheMountNamePrefix)
|
||||
.AppendFormat(index, 'd', 2);
|
||||
|
||||
// Unmount the entry's savedata
|
||||
|
@ -115,8 +115,8 @@ namespace LibHac.Bcat.Detail.Service.Core
|
|||
|
||||
var mountName = new MountName();
|
||||
|
||||
new U8StringBuilder(mountName.Name)
|
||||
.Append(DeliveryCacheMountNamePrefix)
|
||||
var sb = new U8StringBuilder(mountName.Name);
|
||||
sb.Append(DeliveryCacheMountNamePrefix)
|
||||
.AppendFormat(index, 'd', 2);
|
||||
|
||||
if (!DisableStorage)
|
||||
|
@ -215,10 +215,10 @@ namespace LibHac.Bcat.Detail.Service.Core
|
|||
var sb = new U8StringBuilder(pathBuffer);
|
||||
AppendMountName(ref sb, applicationId);
|
||||
|
||||
sb.Append(DirectoriesPath);
|
||||
sb.Append(DirectorySeparator).Append(directoryName.Bytes);
|
||||
sb.Append(DirectorySeparator).Append(FilesDirectoryName);
|
||||
sb.Append(DirectorySeparator).Append(fileName.Bytes);
|
||||
sb.Append(DirectoriesPath)
|
||||
.Append(DirectorySeparator).Append(directoryName.Bytes)
|
||||
.Append(DirectorySeparator).Append(FilesDirectoryName)
|
||||
.Append(DirectorySeparator).Append(fileName.Bytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,9 +229,9 @@ namespace LibHac.Bcat.Detail.Service.Core
|
|||
var sb = new U8StringBuilder(pathBuffer);
|
||||
AppendMountName(ref sb, applicationId);
|
||||
|
||||
sb.Append(DirectoriesPath);
|
||||
sb.Append(DirectorySeparator).Append(directoryName.Bytes);
|
||||
sb.Append(DirectorySeparator).Append(FilesMetaFileName);
|
||||
sb.Append(DirectoriesPath)
|
||||
.Append(DirectorySeparator).Append(directoryName.Bytes)
|
||||
.Append(DirectorySeparator).Append(FilesMetaFileName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -252,8 +252,8 @@ namespace LibHac.Bcat.Detail.Service.Core
|
|||
var sb = new U8StringBuilder(pathBuffer);
|
||||
AppendMountName(ref sb, applicationId);
|
||||
|
||||
sb.Append(DirectoriesPath);
|
||||
sb.Append(DirectorySeparator).Append(directoryName.Bytes);
|
||||
sb.Append(DirectoriesPath)
|
||||
.Append(DirectorySeparator).Append(directoryName.Bytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,11 +4,13 @@ using LibHac.Bcat.Detail.Service.Core;
|
|||
|
||||
namespace LibHac.Bcat.Detail.Service
|
||||
{
|
||||
internal class DeliveryCacheDirectoryService : IDeliveryCacheDirectoryService, IDisposable
|
||||
internal class DeliveryCacheDirectoryService : IDeliveryCacheDirectoryService
|
||||
{
|
||||
private BcatServer Server { get; }
|
||||
private object Locker { get; } = new object();
|
||||
private DeliveryCacheStorageService Parent { get; }
|
||||
|
||||
// ReSharper disable once UnusedAutoPropertyAccessor.Local
|
||||
private AccessControl Access { get; }
|
||||
private ulong ApplicationId { get; }
|
||||
private DirectoryName _name;
|
||||
|
|
|
@ -6,11 +6,13 @@ using LibHac.Fs;
|
|||
|
||||
namespace LibHac.Bcat.Detail.Service
|
||||
{
|
||||
internal class DeliveryCacheFileService : IDeliveryCacheFileService, IDisposable
|
||||
internal class DeliveryCacheFileService : IDeliveryCacheFileService
|
||||
{
|
||||
private BcatServer Server { get; }
|
||||
private object Locker { get; } = new object();
|
||||
private DeliveryCacheStorageService Parent { get; }
|
||||
|
||||
// ReSharper disable once UnusedAutoPropertyAccessor.Local
|
||||
private AccessControl Access { get; }
|
||||
private ulong ApplicationId { get; }
|
||||
private FileHandle _handle;
|
||||
|
|
|
@ -4,12 +4,12 @@ using LibHac.Bcat.Detail.Ipc;
|
|||
|
||||
namespace LibHac.Bcat.Detail.Service
|
||||
{
|
||||
internal class DeliveryCacheStorageService : IDeliveryCacheStorageService, IDisposable
|
||||
internal class DeliveryCacheStorageService : IDeliveryCacheStorageService
|
||||
{
|
||||
private const int MaxOpenCount = 8;
|
||||
private BcatServer Server { get; }
|
||||
|
||||
public object Locker { get; } = new object();
|
||||
private object Locker { get; } = new object();
|
||||
private AccessControl Access { get; }
|
||||
private ulong ApplicationId { get; }
|
||||
private int FileServiceOpenCount { get; set; }
|
||||
|
|
|
@ -6,6 +6,8 @@ namespace LibHac.Bcat.Detail.Service
|
|||
internal class ServiceCreator : IServiceCreator
|
||||
{
|
||||
private BcatServer Server { get; }
|
||||
|
||||
// ReSharper disable once UnusedAutoPropertyAccessor.Local
|
||||
private BcatServiceType ServiceType { get; }
|
||||
private AccessControl AccessControl { get; }
|
||||
|
||||
|
@ -35,16 +37,9 @@ namespace LibHac.Bcat.Detail.Service
|
|||
Result rc = Server.GetStorageManager().Open(applicationId.Value);
|
||||
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);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Server.GetStorageManager().Release(applicationId.Value);
|
||||
}
|
||||
service = new DeliveryCacheStorageService(Server, applicationId.Value, AccessControl);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
|
|
@ -171,7 +171,7 @@ namespace LibHac.Common
|
|||
|
||||
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)
|
||||
|
|
|
@ -10,18 +10,15 @@ namespace LibHac.Common
|
|||
{
|
||||
private const int NullTerminatorLength = 1;
|
||||
|
||||
private readonly Span<byte> _buffer;
|
||||
private int _length;
|
||||
|
||||
public Span<byte> Buffer { get; }
|
||||
public int Length { get; private set; }
|
||||
public bool Overflowed { get; private set; }
|
||||
public readonly int Length => _length;
|
||||
public readonly int Capacity => _buffer.Length - NullTerminatorLength;
|
||||
public readonly Span<byte> Buffer => _buffer;
|
||||
public readonly int Capacity => Buffer.Length - NullTerminatorLength;
|
||||
|
||||
public U8StringBuilder(Span<byte> buffer)
|
||||
{
|
||||
_buffer = buffer;
|
||||
_length = 0;
|
||||
Buffer = buffer;
|
||||
Length = 0;
|
||||
Overflowed = false;
|
||||
|
||||
ThrowIfBufferLengthIsZero();
|
||||
|
@ -29,70 +26,69 @@ namespace LibHac.Common
|
|||
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);
|
||||
|
||||
if (!HasAdditionalCapacity(valueLength))
|
||||
{
|
||||
Overflowed = true;
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
|
||||
value.Slice(0, valueLength).CopyTo(_buffer.Slice(_length));
|
||||
_length += valueLength;
|
||||
value.Slice(0, valueLength).CopyTo(Buffer.Slice(Length));
|
||||
Length += valueLength;
|
||||
AddNullTerminator();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public U8StringBuilder Append(byte value)
|
||||
internal void AppendInternal(byte value)
|
||||
{
|
||||
if (Overflowed) return this;
|
||||
if (Overflowed) return;
|
||||
|
||||
if (!HasAdditionalCapacity(1))
|
||||
{
|
||||
Overflowed = true;
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
|
||||
_buffer[_length] = value;
|
||||
_length++;
|
||||
Buffer[Length] = value;
|
||||
Length++;
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
private readonly bool HasCapacity(int requiredCapacity)
|
||||
|
@ -102,22 +98,22 @@ namespace LibHac.Common
|
|||
|
||||
private readonly bool HasAdditionalCapacity(int requiredAdditionalCapacity)
|
||||
{
|
||||
return HasCapacity(_length + requiredAdditionalCapacity);
|
||||
return HasCapacity(Length + requiredAdditionalCapacity);
|
||||
}
|
||||
|
||||
private void AddNullTerminator()
|
||||
{
|
||||
_buffer[_length] = 0;
|
||||
Buffer[Length] = 0;
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
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,
|
||||
new StandardFormat(format, precision));
|
||||
|
@ -134,21 +130,19 @@ namespace LibHac.Common
|
|||
if (!bufferLargeEnough)
|
||||
{
|
||||
Overflowed = true;
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
|
||||
_length += bytesWritten;
|
||||
Length += bytesWritten;
|
||||
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
|
||||
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,
|
||||
new StandardFormat(format, precision));
|
||||
|
@ -156,21 +150,19 @@ namespace LibHac.Common
|
|||
if (!bufferLargeEnough)
|
||||
{
|
||||
Overflowed = true;
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
|
||||
_length += bytesWritten;
|
||||
Length += bytesWritten;
|
||||
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
|
||||
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,
|
||||
new StandardFormat(format, precision));
|
||||
|
@ -178,21 +170,19 @@ namespace LibHac.Common
|
|||
if (!bufferLargeEnough)
|
||||
{
|
||||
Overflowed = true;
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
|
||||
_length += bytesWritten;
|
||||
Length += bytesWritten;
|
||||
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
|
||||
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,
|
||||
new StandardFormat(format, precision));
|
||||
|
@ -200,15 +190,98 @@ namespace LibHac.Common
|
|||
if (!bufferLargeEnough)
|
||||
{
|
||||
Overflowed = true;
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
|
||||
_length += bytesWritten;
|
||||
Length += bytesWritten;
|
||||
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);
|
||||
|
||||
// ReSharper disable once RedundantAssignment
|
||||
int size = new U8StringBuilder(nameBuffer).Append(mountName).Append(StringTraits.DriveSeparator).Length;
|
||||
Debug.Assert(size == requiredNameBufferSize - 1);
|
||||
var sb = new U8StringBuilder(nameBuffer);
|
||||
sb.Append(mountName).Append(StringTraits.DriveSeparator);
|
||||
|
||||
Debug.Assert(sb.Length == requiredNameBufferSize - 1);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
@ -144,7 +145,8 @@ namespace LibHac.Fs.Shim
|
|||
? StringTraits.NullTerminator
|
||||
: 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;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -43,9 +43,10 @@ namespace LibHac.Fs.Shim
|
|||
if (nameBuffer.Length < requiredNameBufferSize)
|
||||
return ResultFs.TooLongPath.Log();
|
||||
|
||||
// ReSharper disable once RedundantAssignment
|
||||
int size = new U8StringBuilder(nameBuffer).Append(HostRootFileSystemPath).Append(_path.Str).Length;
|
||||
Debug.Assert(size == requiredNameBufferSize - 1);
|
||||
var sb = new U8StringBuilder(nameBuffer);
|
||||
sb.Append(HostRootFileSystemPath).Append(_path.Str);
|
||||
|
||||
Debug.Assert(sb.Length == requiredNameBufferSize - 1);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
|
|
@ -26,9 +26,10 @@ namespace LibHac.FsSystem
|
|||
{
|
||||
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)]
|
||||
|
|
|
@ -10,14 +10,14 @@ namespace LibHac
|
|||
public class Horizon
|
||||
{
|
||||
internal ITimeSpanGenerator Time { get; }
|
||||
private FileSystemServer FileSystemServer { get; set; }
|
||||
private BcatServer BcatServer { get; set; }
|
||||
public FileSystemServer FileSystemServer { get; private set; }
|
||||
public BcatServer BcatServer { get; private set; }
|
||||
|
||||
private readonly object _initLocker = new object();
|
||||
|
||||
public Horizon(ITimeSpanGenerator timer)
|
||||
{
|
||||
Time = timer;
|
||||
Time = timer ?? new StopWatchTimeSpanGenerator();
|
||||
}
|
||||
|
||||
public Result OpenFileSystemProxyService(out IFileSystemProxy service)
|
||||
|
@ -60,6 +60,18 @@ namespace LibHac
|
|||
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)
|
||||
{
|
||||
if (FileSystemServer != null) return;
|
||||
|
|
Loading…
Reference in a new issue