mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2025-02-09 13:14:46 +01:00
Add new assert system
Mostly imitates nnsdk's assert system. The assert handler object is global because passing around a HorizonClient object just to do asserts would be annoying
This commit is contained in:
parent
12575da37d
commit
7269c0a215
@ -335,7 +335,7 @@ namespace LibHac.Boot
|
||||
|
||||
private bool VerifyPk11Sizes()
|
||||
{
|
||||
Assert.True(IsDecrypted);
|
||||
Assert.SdkRequires(IsDecrypted);
|
||||
|
||||
int pk11Size = Unsafe.SizeOf<Package1Pk11Header>() + GetSectionSize(Package1Section.WarmBoot) +
|
||||
GetSectionSize(Package1Section.Bootloader) + GetSectionSize(Package1Section.SecureMonitor);
|
||||
|
@ -493,8 +493,8 @@ namespace LibHac.Common.Keys
|
||||
// of the file which will be treated as the end of a line.
|
||||
if (state == ReaderState.Value || state == ReaderState.WhiteSpace2)
|
||||
{
|
||||
Assert.True(i == buffer.Length);
|
||||
Assert.True(reader.HasReadEndOfFile);
|
||||
Assert.SdkEqual(i, buffer.Length);
|
||||
Assert.SdkAssert(reader.HasReadEndOfFile);
|
||||
|
||||
// WhiteSpace2 will have already set this value
|
||||
if (state == ReaderState.Value)
|
||||
@ -506,8 +506,8 @@ namespace LibHac.Common.Keys
|
||||
// Same situation as the two above states
|
||||
if (state == ReaderState.Comment)
|
||||
{
|
||||
Assert.True(i == buffer.Length);
|
||||
Assert.True(reader.HasReadEndOfFile);
|
||||
Assert.SdkEqual(i, buffer.Length);
|
||||
Assert.SdkAssert(reader.HasReadEndOfFile);
|
||||
|
||||
keyLength = i - keyOffset;
|
||||
state = ReaderState.CommentSuccess;
|
||||
@ -516,8 +516,8 @@ namespace LibHac.Common.Keys
|
||||
// Same as the above states except the final line was empty or whitespace.
|
||||
if (state == ReaderState.Initial)
|
||||
{
|
||||
Assert.True(i == buffer.Length);
|
||||
Assert.True(reader.HasReadEndOfFile);
|
||||
Assert.SdkEqual(i, buffer.Length);
|
||||
Assert.SdkAssert(reader.HasReadEndOfFile);
|
||||
|
||||
reader.BufferPos = i;
|
||||
return ReaderStatus.NoKeyRead;
|
||||
|
@ -48,7 +48,7 @@ namespace LibHac.Common.Keys
|
||||
|
||||
public KeyInfo(int group, KeyType type, string name, KeyGetter retrieveFunc)
|
||||
{
|
||||
Assert.True(IsKeyTypeValid(type));
|
||||
Assert.SdkRequires(IsKeyTypeValid(type));
|
||||
|
||||
Name = name;
|
||||
RangeType = KeyRangeType.Single;
|
||||
@ -61,7 +61,7 @@ namespace LibHac.Common.Keys
|
||||
|
||||
public KeyInfo(int group, KeyType type, string name, byte rangeStart, byte rangeEnd, KeyGetter retrieveFunc)
|
||||
{
|
||||
Assert.True(IsKeyTypeValid(type));
|
||||
Assert.SdkRequires(IsKeyTypeValid(type));
|
||||
|
||||
Name = name;
|
||||
RangeType = KeyRangeType.Range;
|
||||
@ -87,7 +87,7 @@ namespace LibHac.Common.Keys
|
||||
|
||||
private bool MatchesSingle(ReadOnlySpan<char> keyName, out bool isDev)
|
||||
{
|
||||
Assert.Equal((int)KeyRangeType.Single, (int)RangeType);
|
||||
Assert.SdkRequiresEqual((int)KeyRangeType.Single, (int)RangeType);
|
||||
|
||||
isDev = false;
|
||||
|
||||
@ -113,7 +113,7 @@ namespace LibHac.Common.Keys
|
||||
|
||||
private bool MatchesRangedKey(ReadOnlySpan<char> keyName, ref int keyIndex, out bool isDev)
|
||||
{
|
||||
Assert.Equal((int)KeyRangeType.Range, (int)RangeType);
|
||||
Assert.SdkRequiresEqual((int)KeyRangeType.Range, (int)RangeType);
|
||||
|
||||
isDev = false;
|
||||
|
||||
|
@ -173,7 +173,7 @@ namespace LibHac.Common
|
||||
// Grow the buffer and try again. The buffer size will at least double each time it grows,
|
||||
// so asking for 0x10 additional bytes actually gets us more than that.
|
||||
Grow(availableBuffer.Length + 0x10);
|
||||
Assert.True(Length + availableBuffer.Length < Capacity);
|
||||
Assert.SdkGreater(Capacity, Length + availableBuffer.Length);
|
||||
}
|
||||
|
||||
PadOutput(bytesWritten);
|
||||
@ -212,7 +212,7 @@ namespace LibHac.Common
|
||||
}
|
||||
|
||||
Grow(availableBuffer.Length + 0x10);
|
||||
Assert.True(Length + availableBuffer.Length < Capacity);
|
||||
Assert.SdkGreater(Capacity, Length + availableBuffer.Length);
|
||||
}
|
||||
|
||||
PadOutput(bytesWritten);
|
||||
@ -251,7 +251,7 @@ namespace LibHac.Common
|
||||
}
|
||||
|
||||
Grow(availableBuffer.Length + 0x10);
|
||||
Assert.True(Length + availableBuffer.Length < Capacity);
|
||||
Assert.SdkGreater(Capacity, Length + availableBuffer.Length);
|
||||
}
|
||||
|
||||
PadOutput(bytesWritten);
|
||||
@ -290,7 +290,7 @@ namespace LibHac.Common
|
||||
}
|
||||
|
||||
Grow(availableBuffer.Length + 0x10);
|
||||
Assert.True(Length + availableBuffer.Length < Capacity);
|
||||
Assert.SdkGreater(Capacity, Length + availableBuffer.Length);
|
||||
}
|
||||
|
||||
PadOutput(bytesWritten);
|
||||
@ -368,7 +368,7 @@ namespace LibHac.Common
|
||||
if (!hasCapacity && AutoExpand)
|
||||
{
|
||||
Grow(requiredAfterPadding);
|
||||
Assert.True(HasCapacity(Length + requiredAfterPadding));
|
||||
Assert.SdkAssert(HasCapacity(Length + requiredAfterPadding));
|
||||
hasCapacity = true;
|
||||
}
|
||||
|
||||
|
@ -296,7 +296,7 @@ namespace LibHac.Crypto
|
||||
|
||||
private static void LeftShiftBytes(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
{
|
||||
Assert.True(output.Length >= input.Length);
|
||||
Assert.SdkRequiresGreaterEqual(output.Length, input.Length);
|
||||
|
||||
byte carry = 0;
|
||||
|
||||
|
@ -3,8 +3,32 @@ using System.Runtime.CompilerServices;
|
||||
|
||||
namespace LibHac.Diag
|
||||
{
|
||||
public ref struct AbortInfo
|
||||
{
|
||||
public AbortReason AbortReason;
|
||||
public string Message;
|
||||
public string Condition;
|
||||
public string FunctionName;
|
||||
public string FileName;
|
||||
public int LineNumber;
|
||||
}
|
||||
|
||||
public enum AbortReason
|
||||
{
|
||||
SdkAssert,
|
||||
SdkRequires,
|
||||
UserAssert,
|
||||
Abort,
|
||||
UnexpectedDefault
|
||||
}
|
||||
|
||||
public static class Abort
|
||||
{
|
||||
internal static void InvokeAbortObserver(in AbortInfo abortInfo)
|
||||
{
|
||||
// Todo
|
||||
}
|
||||
|
||||
[DoesNotReturn]
|
||||
public static void DoAbort(Result result, string message = null)
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
233
src/LibHac/Diag/Impl/AssertImpl.cs
Normal file
233
src/LibHac/Diag/Impl/AssertImpl.cs
Normal file
@ -0,0 +1,233 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.Diag.Impl
|
||||
{
|
||||
internal static class AssertImpl
|
||||
{
|
||||
internal static void InvokeAssertionNotNull(AssertionType assertionType, string valueText, string functionName,
|
||||
string fileName, int lineNumber)
|
||||
{
|
||||
Assert.OnAssertionFailure(assertionType, valueText, functionName, fileName, lineNumber,
|
||||
$"{valueText} must not be nullptr.");
|
||||
}
|
||||
|
||||
internal static void InvokeAssertionNull(AssertionType assertionType, string valueText, string functionName,
|
||||
string fileName, int lineNumber)
|
||||
{
|
||||
Assert.OnAssertionFailure(assertionType, valueText, functionName, fileName, lineNumber,
|
||||
$"{valueText} must be nullptr.");
|
||||
}
|
||||
|
||||
internal static void InvokeAssertionInRange(AssertionType assertionType, int value, int lower, int upper,
|
||||
string valueText, string lowerText, string upperText, string functionName, string fileName, int lineNumber)
|
||||
{
|
||||
string message =
|
||||
string.Format(
|
||||
"{0} must be within the range [{1}, {2})\nThe actual values are as follows.\n{0}: {3}\n{1}: {4}\n{2}: {5}",
|
||||
valueText, lowerText, upperText, value, lower, upper);
|
||||
|
||||
Assert.OnAssertionFailure(assertionType, "RangeCheck", functionName, fileName, lineNumber, message);
|
||||
}
|
||||
|
||||
internal static void InvokeAssertionWithinMinMax(AssertionType assertionType, long value, long min, long max,
|
||||
string valueText, string minText, string maxText, string functionName, string fileName, int lineNumber)
|
||||
{
|
||||
string message =
|
||||
string.Format(
|
||||
"{0} must satisfy the condition min:{1} and max:{2}\nThe actual values are as follows.\n{0}: {3}\n{1}: {4}\n{2}: {5}",
|
||||
valueText, minText, maxText, value, min, max);
|
||||
|
||||
Assert.OnAssertionFailure(assertionType, "MinMaxCheck", functionName, fileName, lineNumber, message);
|
||||
}
|
||||
|
||||
internal static void InvokeAssertionEqual<T>(AssertionType assertionType, T lhs, T rhs, string lhsText,
|
||||
string rhsText, string functionName, string fileName, int lineNumber) where T : IEquatable<T>
|
||||
{
|
||||
string message =
|
||||
string.Format("{0} must be equal to {1}.\nThe actual values are as follows.\n{0}: {2}\n{1}: {3}",
|
||||
lhsText, rhsText, lhs, rhs);
|
||||
|
||||
Assert.OnAssertionFailure(assertionType, "Equal", functionName, fileName, lineNumber, message);
|
||||
}
|
||||
|
||||
internal static void InvokeAssertionNotEqual<T>(AssertionType assertionType, T lhs, T rhs, string lhsText,
|
||||
string rhsText, string functionName, string fileName, int lineNumber) where T : IEquatable<T>
|
||||
{
|
||||
string message =
|
||||
string.Format("{0} must be equal to {1}.\nThe actual values are as follows.\n{0}: {2}\n{1}: {3}",
|
||||
lhsText, rhsText, lhs, rhs);
|
||||
|
||||
Assert.OnAssertionFailure(assertionType, "Equal", functionName, fileName, lineNumber, message);
|
||||
}
|
||||
|
||||
internal static void InvokeAssertionLess<T>(AssertionType assertionType, T lhs, T rhs, string lhsText,
|
||||
string rhsText, string functionName, string fileName, int lineNumber) where T : IComparable<T>
|
||||
{
|
||||
string message =
|
||||
string.Format("{0} must be less than {1}.\nThe actual values are as follows.\n{0}: {2}\n{1}: {3}",
|
||||
lhsText, rhsText, lhs, rhs);
|
||||
|
||||
Assert.OnAssertionFailure(assertionType, "Less", functionName, fileName, lineNumber, message);
|
||||
}
|
||||
|
||||
internal static void InvokeAssertionLessEqual<T>(AssertionType assertionType, T lhs, T rhs, string lhsText,
|
||||
string rhsText, string functionName, string fileName, int lineNumber) where T : IComparable<T>
|
||||
{
|
||||
string message =
|
||||
string.Format(
|
||||
"{0} must be less than or equal to {1}.\nThe actual values are as follows.\n{0}: {2}\n{1}: {3}",
|
||||
lhsText, rhsText, lhs, rhs);
|
||||
|
||||
Assert.OnAssertionFailure(assertionType, "LessEqual", functionName, fileName, lineNumber, message);
|
||||
}
|
||||
|
||||
internal static void InvokeAssertionGreater<T>(AssertionType assertionType, T lhs, T rhs, string lhsText,
|
||||
string rhsText, string functionName, string fileName, int lineNumber) where T : IComparable<T>
|
||||
{
|
||||
string message =
|
||||
string.Format("{0} must be greater than {1}.\nThe actual values are as follows.\n{0}: {2}\n{1}: {3}",
|
||||
lhsText, rhsText, lhs, rhs);
|
||||
|
||||
Assert.OnAssertionFailure(assertionType, "Greater", functionName, fileName, lineNumber, message);
|
||||
}
|
||||
|
||||
internal static void InvokeAssertionGreaterEqual<T>(AssertionType assertionType, T lhs, T rhs, string lhsText,
|
||||
string rhsText, string functionName, string fileName, int lineNumber) where T : IComparable<T>
|
||||
{
|
||||
string message =
|
||||
string.Format(
|
||||
"{0} must be greater than or equal to {1}.\nThe actual values are as follows.\n{0}: {2}\n{1}: {3}",
|
||||
lhsText, rhsText, lhs, rhs);
|
||||
|
||||
Assert.OnAssertionFailure(assertionType, "GreaterEqual", functionName, fileName, lineNumber, message);
|
||||
}
|
||||
|
||||
internal static void InvokeAssertionAligned(AssertionType assertionType, ulong value, int alignment,
|
||||
string valueText, string alignmentText, string functionName, string fileName, int lineNumber)
|
||||
{
|
||||
string message =
|
||||
string.Format("{0} must be {1}-bytes aligned.\nThe actual values are as follows.\n{0}: {2}\n{1}: {3}",
|
||||
valueText, alignmentText, value, alignment);
|
||||
|
||||
Assert.OnAssertionFailure(assertionType, "Aligned", functionName, fileName, lineNumber, message);
|
||||
}
|
||||
|
||||
public static bool Null<T>(T item) where T : class
|
||||
{
|
||||
return item is null;
|
||||
}
|
||||
|
||||
public static bool Null<T>(ref T item)
|
||||
{
|
||||
return Unsafe.IsNullRef(ref item);
|
||||
}
|
||||
|
||||
public static bool NotNull<T>(T item) where T : class
|
||||
{
|
||||
return item is not null;
|
||||
}
|
||||
|
||||
public static bool NotNull<T>(ref T item)
|
||||
{
|
||||
return !Unsafe.IsNullRef(ref item);
|
||||
}
|
||||
|
||||
public static bool NotNull<T>(Span<T> span)
|
||||
{
|
||||
return !Unsafe.IsNullRef(ref MemoryMarshal.GetReference(span));
|
||||
}
|
||||
|
||||
public static bool NotNull<T>(ReadOnlySpan<T> span)
|
||||
{
|
||||
return !Unsafe.IsNullRef(ref MemoryMarshal.GetReference(span));
|
||||
}
|
||||
|
||||
public static bool WithinRange(int value, int lowerInclusive, int upperExclusive)
|
||||
{
|
||||
return lowerInclusive <= value && value < upperExclusive;
|
||||
}
|
||||
|
||||
public static bool WithinRange(long value, long lowerInclusive, long upperExclusive)
|
||||
{
|
||||
return lowerInclusive <= value && value < upperExclusive;
|
||||
}
|
||||
|
||||
public static bool WithinMinMax(int value, int min, int max)
|
||||
{
|
||||
return min <= value && value <= max;
|
||||
}
|
||||
|
||||
public static bool WithinMinMax(long value, long min, long max)
|
||||
{
|
||||
return min <= value && value <= max;
|
||||
}
|
||||
|
||||
public static bool Equal<T>(T lhs, T rhs) where T : IEquatable<T>
|
||||
{
|
||||
return lhs.Equals(rhs);
|
||||
}
|
||||
|
||||
public static bool Equal<T>(ref T lhs, ref T rhs) where T : IEquatable<T>
|
||||
{
|
||||
return lhs.Equals(rhs);
|
||||
}
|
||||
|
||||
public static bool NotEqual<T>(T lhs, T rhs) where T : IEquatable<T>
|
||||
{
|
||||
return !lhs.Equals(rhs);
|
||||
}
|
||||
|
||||
public static bool NotEqual<T>(ref T lhs, ref T rhs) where T : IEquatable<T>
|
||||
{
|
||||
return !lhs.Equals(rhs);
|
||||
}
|
||||
|
||||
public static bool Less<T>(T lhs, T rhs) where T : IComparable<T>
|
||||
{
|
||||
return lhs.CompareTo(rhs) < 0;
|
||||
}
|
||||
|
||||
public static bool Less<T>(ref T lhs, ref T rhs) where T : IComparable<T>
|
||||
{
|
||||
return lhs.CompareTo(rhs) < 0;
|
||||
}
|
||||
|
||||
public static bool LessEqual<T>(T lhs, T rhs) where T : IComparable<T>
|
||||
{
|
||||
return lhs.CompareTo(rhs) <= 0;
|
||||
}
|
||||
|
||||
public static bool LessEqual<T>(ref T lhs, ref T rhs) where T : IComparable<T>
|
||||
{
|
||||
return lhs.CompareTo(rhs) <= 0;
|
||||
}
|
||||
|
||||
public static bool Greater<T>(T lhs, T rhs) where T : IComparable<T>
|
||||
{
|
||||
return lhs.CompareTo(rhs) > 0;
|
||||
}
|
||||
|
||||
public static bool Greater<T>(ref T lhs, ref T rhs) where T : IComparable<T>
|
||||
{
|
||||
return lhs.CompareTo(rhs) > 0;
|
||||
}
|
||||
|
||||
public static bool GreaterEqual<T>(T lhs, T rhs) where T : IComparable<T>
|
||||
{
|
||||
return lhs.CompareTo(rhs) >= 0;
|
||||
}
|
||||
|
||||
public static bool GreaterEqual<T>(ref T lhs, ref T rhs) where T : IComparable<T>
|
||||
{
|
||||
return lhs.CompareTo(rhs) >= 0;
|
||||
}
|
||||
|
||||
public static bool IsAligned(ulong value, int alignment)
|
||||
{
|
||||
return Alignment.IsAlignedPow2(value, (uint)alignment);
|
||||
}
|
||||
}
|
||||
}
|
@ -23,7 +23,7 @@ namespace LibHac.Diag.Impl
|
||||
|
||||
public void RegisterObserver(TObserver observerHolder)
|
||||
{
|
||||
Assert.False(observerHolder.IsRegistered);
|
||||
Assert.SdkRequires(!observerHolder.IsRegistered);
|
||||
|
||||
using ScopedLock<ReaderWriterLock> lk = ScopedLock.Lock(ref _rwLock);
|
||||
|
||||
@ -33,7 +33,7 @@ namespace LibHac.Diag.Impl
|
||||
|
||||
public void UnregisterObserver(TObserver observerHolder)
|
||||
{
|
||||
Assert.True(observerHolder.IsRegistered);
|
||||
Assert.SdkRequires(observerHolder.IsRegistered);
|
||||
|
||||
using ScopedLock<ReaderWriterLock> lk = ScopedLock.Lock(ref _rwLock);
|
||||
|
||||
@ -91,7 +91,7 @@ namespace LibHac.Diag.Impl
|
||||
|
||||
public void RegisterObserver(LogObserverHolder observerHolder)
|
||||
{
|
||||
Assert.False(observerHolder.IsRegistered);
|
||||
Assert.SdkRequires(!observerHolder.IsRegistered);
|
||||
|
||||
using ScopedLock<ReaderWriterLock> lk = ScopedLock.Lock(ref _rwLock);
|
||||
|
||||
@ -101,7 +101,7 @@ namespace LibHac.Diag.Impl
|
||||
|
||||
public void UnregisterObserver(LogObserverHolder observerHolder)
|
||||
{
|
||||
Assert.True(observerHolder.IsRegistered);
|
||||
Assert.SdkRequires(observerHolder.IsRegistered);
|
||||
|
||||
using ScopedLock<ReaderWriterLock> lk = ScopedLock.Lock(ref _rwLock);
|
||||
|
||||
|
@ -139,7 +139,8 @@ namespace LibHac.Fs.Impl
|
||||
private ReadOnlySpan<byte> ToValueString(int value)
|
||||
{
|
||||
bool success = Utf8Formatter.TryFormat(value, _buffer.Bytes, out int length);
|
||||
Assert.True(success && length < _buffer.Bytes.Length);
|
||||
Assert.SdkAssert(success);
|
||||
Assert.SdkLess(length, _buffer.Bytes.Length);
|
||||
_buffer[length] = 0;
|
||||
|
||||
return _buffer.Bytes;
|
||||
@ -480,13 +481,13 @@ namespace LibHac.Fs.Impl
|
||||
|
||||
public void RegisterCallback(AccessLogPrinterCallback callback)
|
||||
{
|
||||
Assert.Null(_callback);
|
||||
Assert.SdkNull(_callback);
|
||||
_callback = callback;
|
||||
}
|
||||
|
||||
public int InvokeCallback(Span<byte> textBuffer)
|
||||
{
|
||||
Assert.True(IsRegisteredCallback());
|
||||
Assert.SdkAssert(IsRegisteredCallback());
|
||||
return _callback(textBuffer);
|
||||
}
|
||||
}
|
||||
@ -658,7 +659,8 @@ namespace LibHac.Fs.Impl
|
||||
|
||||
// We should never receive non-null here.
|
||||
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
|
||||
Assert.True(handle is null);
|
||||
Assert.SdkAssert(handle is null,
|
||||
"Handle type must be FileHandle or DirectoryHandle. Please cast to handle type.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -683,7 +685,7 @@ namespace LibHac.Fs.Impl
|
||||
|
||||
internal static void FlushAccessLog(this FileSystemClientImpl fs)
|
||||
{
|
||||
Assert.True(false, $"Unsupported {nameof(FlushAccessLog)}");
|
||||
Assert.SdkAssert(false, $"Unsupported {nameof(FlushAccessLog)}");
|
||||
}
|
||||
|
||||
internal static void FlushAccessLogOnSdCard(this FileSystemClientImpl fs)
|
||||
|
@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Diag;
|
||||
|
||||
namespace LibHac.Fs.Fsa
|
||||
{
|
||||
@ -181,8 +180,6 @@ namespace LibHac.Fs.Fsa
|
||||
if (!openMode.HasFlag(OpenMode.Write))
|
||||
return ResultFs.WriteUnpermitted.Log();
|
||||
|
||||
Assert.True(size >= 0);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ namespace LibHac.Fs.Impl
|
||||
|
||||
public bool CanAcceptMountName(U8Span name)
|
||||
{
|
||||
Assert.True(_mutex.IsLockedByCurrentThread());
|
||||
Assert.SdkAssert(_mutex.IsLockedByCurrentThread());
|
||||
|
||||
for (LinkedListNode<FileSystemAccessor> currentNode = _fileSystemList.First;
|
||||
currentNode is not null;
|
||||
|
@ -55,7 +55,7 @@ namespace LibHac.Fs.Impl
|
||||
|
||||
public int GetCacheFetchedRegionCount()
|
||||
{
|
||||
Assert.True(_isFileDataCacheUsed);
|
||||
Assert.SdkRequires(_isFileDataCacheUsed);
|
||||
return _regionCount;
|
||||
}
|
||||
|
||||
@ -63,9 +63,9 @@ namespace LibHac.Fs.Impl
|
||||
|
||||
public FileRegion GetCacheFetchedRegion(int index)
|
||||
{
|
||||
Assert.True(IsFileDataCacheUsed());
|
||||
Assert.True(index >= 0);
|
||||
Assert.True(index < _regionCount);
|
||||
Assert.SdkRequires(IsFileDataCacheUsed());
|
||||
Assert.SdkRequiresLessEqual(0, index);
|
||||
Assert.SdkRequiresLess(index, _regionCount);
|
||||
|
||||
return _regions[index];
|
||||
}
|
||||
|
@ -32,14 +32,14 @@ namespace LibHac.Fs.Shim
|
||||
int neededSize =
|
||||
StringUtils.GetLength(GetContentStorageMountName(StorageId), PathTool.MountNameLengthMax) + 2;
|
||||
|
||||
Assert.True(nameBuffer.Length >= neededSize);
|
||||
Assert.SdkRequiresGreaterEqual(nameBuffer.Length, neededSize);
|
||||
|
||||
// Generate the name.
|
||||
var sb = new U8StringBuilder(nameBuffer);
|
||||
sb.Append(GetContentStorageMountName(StorageId))
|
||||
.Append(StringTraits.DriveSeparator);
|
||||
|
||||
Assert.True(sb.Length == neededSize - 1);
|
||||
Assert.SdkEqual(sb.Length, neededSize - 1);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ namespace LibHac.Fs.Shim
|
||||
StringUtils.GetLength(GetGameCardMountNameSuffix(PartitionId), PathTool.MountNameLengthMax) +
|
||||
handleDigitCount + 2;
|
||||
|
||||
Assert.True(nameBuffer.Length >= neededSize);
|
||||
Assert.SdkRequiresGreaterEqual(nameBuffer.Length, neededSize);
|
||||
|
||||
// Generate the name.
|
||||
var sb = new U8StringBuilder(nameBuffer);
|
||||
@ -62,7 +62,7 @@ namespace LibHac.Fs.Shim
|
||||
.AppendFormat(Handle.Value, 'x', (byte)handleDigitCount)
|
||||
.Append(StringTraits.DriveSeparator);
|
||||
|
||||
Assert.True(sb.Length == neededSize - 1);
|
||||
Assert.SdkEqual(sb.Length, neededSize - 1);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ namespace LibHac.Fs.Shim
|
||||
var sb = new U8StringBuilder(nameBuffer);
|
||||
sb.Append(HostRootFileSystemPath).Append(_path.Str);
|
||||
|
||||
Assert.True(sb.Length == requiredNameBufferSize - 1);
|
||||
Assert.SdkEqual(sb.Length, requiredNameBufferSize - 1);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
@ -107,12 +107,12 @@ namespace LibHac.Fs.Shim
|
||||
{
|
||||
const int requiredNameBufferSize = HostRootFileSystemPathLength;
|
||||
|
||||
Assert.True(nameBuffer.Length >= requiredNameBufferSize);
|
||||
Assert.SdkRequiresGreaterEqual(nameBuffer.Length, requiredNameBufferSize);
|
||||
|
||||
var sb = new U8StringBuilder(nameBuffer);
|
||||
sb.Append(HostRootFileSystemPath);
|
||||
|
||||
Assert.True(sb.Length == requiredNameBufferSize - 1);
|
||||
Assert.SdkEqual(sb.Length, requiredNameBufferSize - 1);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
@ -82,9 +82,9 @@ namespace LibHac.Fs
|
||||
Size = size;
|
||||
IsResizable = false;
|
||||
|
||||
Assert.True(IsValid());
|
||||
Assert.True(Offset >= 0);
|
||||
Assert.True(Size >= 0);
|
||||
Assert.SdkRequiresNotNull(baseStorage);
|
||||
Assert.SdkRequiresLessEqual(0, Offset);
|
||||
Assert.SdkRequiresLessEqual(0, Size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -102,9 +102,9 @@ namespace LibHac.Fs
|
||||
Size = size;
|
||||
IsResizable = false;
|
||||
|
||||
Assert.True(IsValid());
|
||||
Assert.True(Offset >= 0);
|
||||
Assert.True(Size >= 0);
|
||||
Assert.SdkRequiresNotNull(sharedBaseStorage);
|
||||
Assert.SdkRequiresLessEqual(0, Offset);
|
||||
Assert.SdkRequiresLessEqual(0, Size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -126,10 +126,10 @@ namespace LibHac.Fs
|
||||
Size = size;
|
||||
IsResizable = false;
|
||||
|
||||
Assert.True(IsValid());
|
||||
Assert.True(Offset >= 0);
|
||||
Assert.True(Size >= 0);
|
||||
Assert.True(other.Size >= offset + size);
|
||||
Assert.SdkRequires(other.IsValid());
|
||||
Assert.SdkRequiresLessEqual(0, Offset);
|
||||
Assert.SdkRequiresLessEqual(0, Size);
|
||||
Assert.SdkRequiresGreaterEqual(other.Size, offset + size);
|
||||
}
|
||||
|
||||
private bool IsValid() => BaseStorage != null;
|
||||
|
@ -197,7 +197,7 @@ namespace LibHac.FsSrv.Impl
|
||||
|
||||
private static int GetResolverIndexFromStorageId(StorageId id)
|
||||
{
|
||||
Assert.True(IsValidStorageId(id));
|
||||
Assert.SdkRequires(IsValidStorageId(id));
|
||||
|
||||
return id switch
|
||||
{
|
||||
|
@ -36,7 +36,7 @@ namespace LibHac.FsSrv.Impl
|
||||
private static Result EnsureDirectoryImpl(IFileSystem fileSystem, Span<byte> path)
|
||||
{
|
||||
// Double check the trailing separators have been trimmed
|
||||
Assert.True(path.Length <= 1 || path[path.Length - 1] != StringTraits.DirectorySeparator);
|
||||
Assert.SdkRequires(path.Length <= 1 || path[path.Length - 1] != StringTraits.DirectorySeparator);
|
||||
|
||||
// Use the root path if the input path is empty
|
||||
var pathToCheck = new U8Span(path.IsEmpty ? FileSystemRootPath : path);
|
||||
@ -91,8 +91,8 @@ namespace LibHac.FsSrv.Impl
|
||||
private static Result EnsureParentDirectoryImpl(IFileSystem fileSystem, Span<byte> path)
|
||||
{
|
||||
// The path should not be empty or have a trailing directory separator
|
||||
Assert.True(path.Length > 0);
|
||||
Assert.NotEqual(StringTraits.DirectorySeparator, path[path.Length - 1]);
|
||||
Assert.SdkRequiresLess(0, path.Length);
|
||||
Assert.SdkRequiresNotEqual(path[path.Length - 1], StringTraits.DirectorySeparator);
|
||||
|
||||
// Make sure the path's not too long
|
||||
if (path.Length > PathTool.EntryNameLengthMax)
|
||||
|
@ -121,7 +121,7 @@ namespace LibHac.FsSrv
|
||||
if (originalResult.IsFailure())
|
||||
return originalResult;
|
||||
|
||||
Assert.True(originalPathNormalizerHasValue);
|
||||
Assert.SdkAssert(originalPathNormalizerHasValue);
|
||||
|
||||
// There is an original version and no patch version. Open the original directly
|
||||
rc = ServiceImpl.OpenFileSystem(out tempFileSystem, originalPathNormalizer.Path, fsType, programId.Value);
|
||||
|
@ -533,7 +533,7 @@ namespace LibHac.FsSrv
|
||||
|
||||
private FlatMapKeyValueStore<SaveDataAttribute>.Iterator GetBeginIterator()
|
||||
{
|
||||
Assert.True(IsKvdbLoaded);
|
||||
Assert.SdkRequires(IsKvdbLoaded);
|
||||
|
||||
return KvDatabase.GetBeginIterator();
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ namespace LibHac.FsSrv
|
||||
|
||||
// ReSharper disable once RedundantAssignment
|
||||
Result rc = _tempIndexer.Indexer.Reset();
|
||||
Assert.True(rc.IsSuccess());
|
||||
Assert.SdkAssert(rc.IsSuccess());
|
||||
}
|
||||
|
||||
public void InvalidateIndexer(SaveDataSpaceId spaceId)
|
||||
|
@ -1,9 +1,12 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
|
||||
#if DEBUG
|
||||
using System.Diagnostics;
|
||||
#endif
|
||||
|
||||
namespace LibHac.FsSrv.Sf
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Size = PathTool.EntryNameLengthMax + 1)]
|
||||
|
@ -124,15 +124,15 @@ namespace LibHac.FsSrv
|
||||
switch (threadType)
|
||||
{
|
||||
case FsStackUsageThreadType.MainThread:
|
||||
Assert.NotNull(_config.MainThreadStackUsageReporter);
|
||||
Assert.SdkRequiresNotNull(_config.MainThreadStackUsageReporter);
|
||||
return _config.MainThreadStackUsageReporter.GetStackUsage();
|
||||
|
||||
case FsStackUsageThreadType.IpcWorker:
|
||||
Assert.NotNull(_config.IpcWorkerThreadStackUsageReporter);
|
||||
Assert.SdkRequiresNotNull(_config.IpcWorkerThreadStackUsageReporter);
|
||||
return _config.IpcWorkerThreadStackUsageReporter.GetStackUsage();
|
||||
|
||||
case FsStackUsageThreadType.PipelineWorker:
|
||||
Assert.NotNull(_config.PipeLineWorkerThreadStackUsageReporter);
|
||||
Assert.SdkRequiresNotNull(_config.PipeLineWorkerThreadStackUsageReporter);
|
||||
return _config.PipeLineWorkerThreadStackUsageReporter.GetStackUsage();
|
||||
|
||||
default:
|
||||
|
@ -31,7 +31,7 @@ namespace LibHac.FsSrv.Storage
|
||||
out ReferenceCountedDisposable<IStorageDeviceManager> deviceManager, StorageDevicePortId portId)
|
||||
{
|
||||
IStorageDeviceManagerFactory factory = storage.GetStorageDeviceManagerFactory(null);
|
||||
Assert.NotNull(factory);
|
||||
Assert.SdkNotNull(factory);
|
||||
|
||||
return factory.Create(out deviceManager, portId);
|
||||
}
|
||||
|
@ -35,11 +35,11 @@ namespace LibHac.FsSystem
|
||||
public Result Initialize(SubStorage nodeStorage, SubStorage entryStorage, int nodeSize, int entrySize,
|
||||
int entryCount)
|
||||
{
|
||||
Assert.True(entrySize >= sizeof(long));
|
||||
Assert.True(nodeSize >= entrySize + Unsafe.SizeOf<NodeHeader>());
|
||||
Assert.True(NodeSizeMin <= nodeSize && nodeSize <= NodeSizeMax);
|
||||
Assert.True(BitUtil.IsPowerOfTwo(nodeSize));
|
||||
Assert.True(!IsInitialized());
|
||||
Assert.SdkRequiresLessEqual(sizeof(long), entrySize);
|
||||
Assert.SdkRequiresLessEqual(entrySize + Unsafe.SizeOf<NodeHeader>(), nodeSize);
|
||||
Assert.SdkRequiresWithinMinMax(nodeSize, NodeSizeMin, NodeSizeMax);
|
||||
Assert.SdkRequires(BitUtil.IsPowerOfTwo(nodeSize));
|
||||
Assert.SdkRequires(!IsInitialized());
|
||||
|
||||
// Ensure valid entry count.
|
||||
if (entryCount <= 0)
|
||||
@ -119,7 +119,7 @@ namespace LibHac.FsSystem
|
||||
|
||||
public Result Find(ref Visitor visitor, long virtualAddress)
|
||||
{
|
||||
Assert.True(IsInitialized());
|
||||
Assert.SdkRequires(IsInitialized());
|
||||
|
||||
if (virtualAddress < 0)
|
||||
return ResultFs.InvalidOffset.Log();
|
||||
@ -137,11 +137,11 @@ namespace LibHac.FsSystem
|
||||
|
||||
public static long QueryNodeStorageSize(long nodeSize, long entrySize, int entryCount)
|
||||
{
|
||||
Assert.True(entrySize >= sizeof(long));
|
||||
Assert.True(nodeSize >= entrySize + Unsafe.SizeOf<NodeHeader>());
|
||||
Assert.True(NodeSizeMin <= nodeSize && nodeSize <= NodeSizeMax);
|
||||
Assert.True(BitUtil.IsPowerOfTwo(nodeSize));
|
||||
Assert.True(entryCount >= 0);
|
||||
Assert.SdkRequiresLessEqual(sizeof(long), entrySize);
|
||||
Assert.SdkRequiresLessEqual(entrySize + Unsafe.SizeOf<NodeHeader>(), nodeSize);
|
||||
Assert.SdkRequiresWithinMinMax(nodeSize, NodeSizeMin, NodeSizeMax);
|
||||
Assert.SdkRequires(BitUtil.IsPowerOfTwo(nodeSize));
|
||||
Assert.SdkRequiresLessEqual(0, entryCount);
|
||||
|
||||
if (entryCount <= 0)
|
||||
return 0;
|
||||
@ -151,11 +151,11 @@ namespace LibHac.FsSystem
|
||||
|
||||
public static long QueryEntryStorageSize(long nodeSize, long entrySize, int entryCount)
|
||||
{
|
||||
Assert.True(entrySize >= sizeof(long));
|
||||
Assert.True(nodeSize >= entrySize + Unsafe.SizeOf<NodeHeader>());
|
||||
Assert.True(NodeSizeMin <= nodeSize && nodeSize <= NodeSizeMax);
|
||||
Assert.True(BitUtil.IsPowerOfTwo(nodeSize));
|
||||
Assert.True(entryCount >= 0);
|
||||
Assert.SdkRequiresLessEqual(sizeof(long), entrySize);
|
||||
Assert.SdkRequiresLessEqual(entrySize + Unsafe.SizeOf<NodeHeader>(), nodeSize);
|
||||
Assert.SdkRequiresWithinMinMax(nodeSize, NodeSizeMin, NodeSizeMax);
|
||||
Assert.SdkRequires(BitUtil.IsPowerOfTwo(nodeSize));
|
||||
Assert.SdkRequiresLessEqual(0, entryCount);
|
||||
|
||||
if (entryCount <= 0)
|
||||
return 0;
|
||||
@ -276,7 +276,7 @@ namespace LibHac.FsSystem
|
||||
|
||||
public bool Allocate(int nodeSize)
|
||||
{
|
||||
Assert.True(_header == null);
|
||||
Assert.SdkRequiresNotNull(_header);
|
||||
|
||||
_header = new long[nodeSize / sizeof(long)];
|
||||
|
||||
@ -298,7 +298,7 @@ namespace LibHac.FsSystem
|
||||
|
||||
public ref NodeHeader GetHeader()
|
||||
{
|
||||
Assert.True(_header.Length / sizeof(long) >= Unsafe.SizeOf<NodeHeader>());
|
||||
Assert.SdkRequiresGreaterEqual(_header.Length / sizeof(long), Unsafe.SizeOf<NodeHeader>());
|
||||
|
||||
return ref Unsafe.As<long, NodeHeader>(ref _header[0]);
|
||||
}
|
||||
@ -322,8 +322,9 @@ namespace LibHac.FsSystem
|
||||
{
|
||||
_buffer = buffer;
|
||||
|
||||
Assert.True(_buffer.Length >= Unsafe.SizeOf<NodeHeader>());
|
||||
Assert.True(_buffer.Length >= Unsafe.SizeOf<NodeHeader>() + GetHeader().Count * Unsafe.SizeOf<TEntry>());
|
||||
Assert.SdkRequiresGreaterEqual(_buffer.Length, Unsafe.SizeOf<NodeHeader>());
|
||||
Assert.SdkRequiresGreaterEqual(_buffer.Length,
|
||||
Unsafe.SizeOf<NodeHeader>() + GetHeader().Count * Unsafe.SizeOf<TEntry>());
|
||||
}
|
||||
|
||||
public int GetCount() => GetHeader().Count;
|
||||
@ -381,8 +382,8 @@ namespace LibHac.FsSystem
|
||||
|
||||
public Result Initialize(BucketTree tree)
|
||||
{
|
||||
Assert.True(tree != null);
|
||||
Assert.True(Tree == null || tree == Tree);
|
||||
Assert.SdkRequiresNotNull(tree);
|
||||
Assert.SdkRequires(Tree == null || tree == Tree);
|
||||
|
||||
if (Entry == null)
|
||||
{
|
||||
|
@ -42,10 +42,10 @@ namespace LibHac.FsSystem
|
||||
public Result Initialize(SubStorage headerStorage, SubStorage nodeStorage, SubStorage entryStorage,
|
||||
int nodeSize, int entrySize, int entryCount)
|
||||
{
|
||||
Assert.True(entrySize >= sizeof(long));
|
||||
Assert.True(nodeSize >= entrySize + Unsafe.SizeOf<NodeHeader>());
|
||||
Assert.True(NodeSizeMin <= nodeSize && nodeSize <= NodeSizeMax);
|
||||
Assert.True(BitUtil.IsPowerOfTwo(nodeSize));
|
||||
Assert.SdkRequiresLessEqual(sizeof(long), entrySize);
|
||||
Assert.SdkRequiresLessEqual(entrySize + Unsafe.SizeOf<NodeHeader>(), nodeSize);
|
||||
Assert.SdkRequiresWithinMinMax(nodeSize, NodeSizeMin, NodeSizeMax);
|
||||
Assert.SdkRequires(BitUtil.IsPowerOfTwo(nodeSize));
|
||||
|
||||
if (headerStorage is null || nodeStorage is null || entryStorage is null)
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
@ -99,7 +99,7 @@ namespace LibHac.FsSystem
|
||||
/// <returns>The <see cref="Result"/> of the operation.</returns>
|
||||
public Result Add<T>(ref T entry) where T : unmanaged
|
||||
{
|
||||
Assert.True(Unsafe.SizeOf<T>() == EntrySize);
|
||||
Assert.SdkRequiresEqual(Unsafe.SizeOf<T>(), EntrySize);
|
||||
|
||||
if (CurrentEntryIndex >= EntryCount)
|
||||
return ResultFs.OutOfRange.Log();
|
||||
|
@ -94,8 +94,9 @@ namespace LibHac.FsSystem.Buffers
|
||||
int size, IBufferManager.BufferAttribute attribute, IsValidBufferFunction isValidBuffer,
|
||||
[CallerMemberName] string callerName = "")
|
||||
{
|
||||
Assert.NotNull(bufferManager);
|
||||
Assert.NotNull(callerName);
|
||||
Assert.SdkNotNullOut(out outBuffer);
|
||||
Assert.SdkNotNull(bufferManager);
|
||||
Assert.SdkNotNull(callerName);
|
||||
|
||||
// Clear the output.
|
||||
outBuffer = new Buffer();
|
||||
@ -135,7 +136,7 @@ namespace LibHac.FsSystem.Buffers
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
|
||||
Assert.True(!tempBuffer.IsNull);
|
||||
Assert.SdkAssert(!tempBuffer.IsNull);
|
||||
outBuffer = tempBuffer;
|
||||
return Result.Success;
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ namespace LibHac.FsSystem
|
||||
|
||||
public PageEntry* PopFront()
|
||||
{
|
||||
Assert.True(EntryCount > 0);
|
||||
Assert.SdkRequires(EntryCount > 0);
|
||||
|
||||
// Get the first entry.
|
||||
PageEntry* pageEntry = FirstPageEntry;
|
||||
@ -51,7 +51,7 @@ namespace LibHac.FsSystem
|
||||
|
||||
// Decrement our count.
|
||||
EntryCount--;
|
||||
Assert.True(EntryCount >= 0);
|
||||
Assert.SdkGreaterEqual(EntryCount, 0);
|
||||
|
||||
// If this was our last page, clear our last entry.
|
||||
if (EntryCount == 0)
|
||||
@ -64,7 +64,7 @@ namespace LibHac.FsSystem
|
||||
|
||||
public void PushBack(PageEntry* pageEntry)
|
||||
{
|
||||
Assert.True(pageEntry != null);
|
||||
Assert.SdkRequires(pageEntry != null);
|
||||
|
||||
// If we're empty, we want to set the first page entry.
|
||||
if (IsEmpty())
|
||||
@ -74,7 +74,7 @@ namespace LibHac.FsSystem
|
||||
else
|
||||
{
|
||||
// We're not empty, so push the page to the back.
|
||||
Assert.True(LastPageEntry != pageEntry);
|
||||
Assert.SdkAssert(LastPageEntry != pageEntry);
|
||||
LastPageEntry->Next = pageEntry;
|
||||
}
|
||||
|
||||
@ -84,12 +84,12 @@ namespace LibHac.FsSystem
|
||||
|
||||
// Increment our entry count.
|
||||
EntryCount++;
|
||||
Assert.True(EntryCount > 0);
|
||||
Assert.SdkGreater(EntryCount, 0);
|
||||
}
|
||||
|
||||
public bool Remove(PageEntry* pageEntry)
|
||||
{
|
||||
Assert.True(pageEntry != null);
|
||||
Assert.SdkRequires(pageEntry != null);
|
||||
|
||||
// If we're empty, we can't remove the page list.
|
||||
if (IsEmpty())
|
||||
@ -128,7 +128,7 @@ namespace LibHac.FsSystem
|
||||
|
||||
// Update our entry count.
|
||||
EntryCount--;
|
||||
Assert.True(EntryCount >= 0);
|
||||
Assert.SdkGreaterEqual(EntryCount, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -162,14 +162,14 @@ namespace LibHac.FsSystem
|
||||
|
||||
public static int GetBlockCountFromOrder(int order)
|
||||
{
|
||||
Assert.True(0 <= order);
|
||||
Assert.True(order < OrderUpperLimit);
|
||||
Assert.SdkRequiresGreaterEqual(order, 0);
|
||||
Assert.SdkRequiresLess(order, OrderUpperLimit);
|
||||
return 1 << order;
|
||||
}
|
||||
|
||||
public static nuint QueryWorkBufferSize(int orderMax)
|
||||
{
|
||||
Assert.InRange(orderMax, 1, OrderUpperLimit);
|
||||
Assert.SdkRequiresInRange(orderMax, 1, OrderUpperLimit);
|
||||
|
||||
var pageListSize = (nint)Unsafe.SizeOf<PageList>();
|
||||
uint pageListAlignment = (uint)Unsafe.SizeOf<nint>();
|
||||
@ -180,9 +180,9 @@ namespace LibHac.FsSystem
|
||||
|
||||
public static int QueryOrderMax(nuint size, nuint blockSize)
|
||||
{
|
||||
Assert.True(size >= blockSize);
|
||||
Assert.True(blockSize >= BlockSizeMin);
|
||||
Assert.True(BitUtil.IsPowerOfTwo(blockSize));
|
||||
Assert.SdkRequiresGreaterEqual(size, blockSize);
|
||||
Assert.SdkRequiresGreaterEqual(blockSize, BlockSizeMin);
|
||||
Assert.SdkRequires(BitUtil.IsPowerOfTwo(blockSize));
|
||||
|
||||
int blockCount = (int)(Alignment.AlignUpPow2(size, (uint)blockSize) / blockSize);
|
||||
for (int order = 1; ; order++)
|
||||
@ -200,14 +200,15 @@ namespace LibHac.FsSystem
|
||||
public Result Initialize(UIntPtr address, nuint size, nuint blockSize, int orderMax, void* workBuffer,
|
||||
nuint workBufferSize)
|
||||
{
|
||||
Assert.True(workBufferSize >= QueryWorkBufferSize(orderMax));
|
||||
Assert.SdkRequiresGreaterEqual(workBufferSize, QueryWorkBufferSize(orderMax));
|
||||
|
||||
uint pageListAlignment = (uint)Unsafe.SizeOf<nint>();
|
||||
var alignedWork = (void*)Alignment.AlignUpPow2((ulong)workBuffer, pageListAlignment);
|
||||
ExternalFreeLists = (PageList*)alignedWork;
|
||||
|
||||
// Note: The original code does not have a buffer size assert after adjusting for alignment.
|
||||
Assert.True(workBufferSize - ((nuint)alignedWork - (nuint)workBuffer) >= QueryWorkBufferSize(orderMax));
|
||||
Assert.SdkRequiresGreaterEqual(workBufferSize - ((nuint)alignedWork - (nuint)workBuffer),
|
||||
QueryWorkBufferSize(orderMax));
|
||||
|
||||
return Initialize(address, size, blockSize, orderMax);
|
||||
}
|
||||
@ -219,14 +220,14 @@ namespace LibHac.FsSystem
|
||||
|
||||
public Result Initialize(UIntPtr address, nuint size, nuint blockSize, int orderMax)
|
||||
{
|
||||
Assert.True(FreeLists == null);
|
||||
Assert.True(address != UIntPtr.Zero);
|
||||
Assert.True(Alignment.IsAlignedPow2(address.ToUInt64(), (uint)BufferAlignment));
|
||||
Assert.True(blockSize >= BlockSizeMin);
|
||||
Assert.True(BitUtil.IsPowerOfTwo(blockSize));
|
||||
Assert.True(size >= blockSize);
|
||||
Assert.True(orderMax > 0);
|
||||
Assert.True(orderMax < OrderUpperLimit);
|
||||
Assert.SdkRequires(FreeLists == null);
|
||||
Assert.SdkRequiresNotEqual(address, UIntPtr.Zero);
|
||||
Assert.SdkRequiresAligned(address.ToUInt64(), (int)BufferAlignment);
|
||||
Assert.SdkRequiresGreaterEqual(blockSize, BlockSizeMin);
|
||||
Assert.SdkRequires(BitUtil.IsPowerOfTwo(blockSize));
|
||||
Assert.SdkRequiresGreaterEqual(size, blockSize);
|
||||
Assert.SdkRequiresGreater(orderMax, 0);
|
||||
Assert.SdkRequiresLess(orderMax, OrderUpperLimit);
|
||||
|
||||
// Set up our basic member variables
|
||||
BlockSize = blockSize;
|
||||
@ -239,12 +240,12 @@ namespace LibHac.FsSystem
|
||||
// Determine page sizes
|
||||
nuint maxPageSize = BlockSize << OrderMax;
|
||||
nuint maxPageCount = (nuint)Alignment.AlignUp(HeapSize, (uint)maxPageSize) / maxPageSize;
|
||||
Assert.True(maxPageCount > 0);
|
||||
Assert.SdkGreater((int)maxPageCount, 0);
|
||||
|
||||
// Setup the free lists
|
||||
if (ExternalFreeLists != null)
|
||||
{
|
||||
Assert.Null(InternalFreeLists);
|
||||
Assert.SdkAssert(InternalFreeLists == null);
|
||||
FreeLists = ExternalFreeLists;
|
||||
}
|
||||
else
|
||||
@ -268,7 +269,7 @@ namespace LibHac.FsSystem
|
||||
{
|
||||
nuint remaining = HeapSize - (maxPageCount - 1) * maxPageSize;
|
||||
nuint curAddress = HeapStart - (maxPageCount - 1) * maxPageSize;
|
||||
Assert.True(Alignment.IsAlignedPow2(remaining, (uint)BlockSize));
|
||||
Assert.SdkAligned(remaining, (int)BlockSize);
|
||||
|
||||
do
|
||||
{
|
||||
@ -276,12 +277,12 @@ namespace LibHac.FsSystem
|
||||
int order = GetOrderFromBytes(remaining + 1);
|
||||
if (order < 0)
|
||||
{
|
||||
Assert.True(GetOrderFromBytes(remaining) == orderMax);
|
||||
Assert.SdkEqual(OrderMax, GetOrderFromBytes(remaining));
|
||||
order = OrderMax + 1;
|
||||
}
|
||||
|
||||
Assert.True(0 < order);
|
||||
Assert.True(order <= OrderMax + 1);
|
||||
Assert.SdkGreater(order, 0);
|
||||
Assert.SdkLessEqual(order, OrderMax + 1);
|
||||
|
||||
// Add to the correct free list.
|
||||
FreeLists[order - 1].PushBack(GetPageEntryFromAddress(curAddress));
|
||||
@ -299,9 +300,9 @@ namespace LibHac.FsSystem
|
||||
|
||||
public void* AllocateByOrder(int order)
|
||||
{
|
||||
Assert.True(FreeLists != null);
|
||||
Assert.True(order >= 0);
|
||||
Assert.True(order <= GetOrderMax());
|
||||
Assert.SdkRequires(FreeLists != null);
|
||||
Assert.SdkRequiresGreaterEqual(order, 0);
|
||||
Assert.SdkRequiresLessEqual(order, GetOrderMax());
|
||||
|
||||
// Get the page entry.
|
||||
PageEntry* pageEntry = GetFreePageEntry(order);
|
||||
@ -309,7 +310,7 @@ namespace LibHac.FsSystem
|
||||
if (pageEntry != null)
|
||||
{
|
||||
// Ensure we're allocating an unlinked page.
|
||||
Assert.True(pageEntry->Next == null);
|
||||
Assert.SdkAssert(pageEntry->Next == null);
|
||||
|
||||
// Return the address for this entry.
|
||||
return (void*)GetAddressFromPageEntry(pageEntry);
|
||||
@ -322,20 +323,20 @@ namespace LibHac.FsSystem
|
||||
|
||||
public void Free(void* pointer, int order)
|
||||
{
|
||||
Assert.True(FreeLists != null);
|
||||
Assert.True(order >= 0);
|
||||
Assert.True(order <= GetOrderMax());
|
||||
Assert.SdkRequires(FreeLists != null);
|
||||
Assert.SdkRequiresGreaterEqual(order, 0);
|
||||
Assert.SdkRequiresLessEqual(order, GetOrderMax());
|
||||
|
||||
// Allow Free(null)
|
||||
if (pointer == null)
|
||||
return;
|
||||
|
||||
// Ensure the pointer is block aligned.
|
||||
Assert.True(Alignment.IsAlignedPow2((nuint)pointer - HeapStart, (uint)GetBlockSize()));
|
||||
Assert.SdkAligned((nuint)pointer - HeapStart, (int)GetBlockSize());
|
||||
|
||||
// Get the page entry.
|
||||
PageEntry* pageEntry = GetPageEntryFromAddress((UIntPtr)pointer);
|
||||
Assert.True(IsAlignedToOrder(pageEntry, order));
|
||||
Assert.SdkAssert(IsAlignedToOrder(pageEntry, order));
|
||||
|
||||
/* Reinsert into the free lists. */
|
||||
JoinBuddies(pageEntry, order);
|
||||
@ -343,13 +344,13 @@ namespace LibHac.FsSystem
|
||||
|
||||
public nuint GetTotalFreeSize()
|
||||
{
|
||||
Assert.True(FreeLists != null);
|
||||
Assert.SdkRequires(FreeLists != null);
|
||||
return TotalFreeSize;
|
||||
}
|
||||
|
||||
public nuint GetAllocatableSizeMax()
|
||||
{
|
||||
Assert.True(FreeLists != null);
|
||||
Assert.SdkRequires(FreeLists != null);
|
||||
|
||||
// The maximum allocatable size is a chunk from the biggest non-empty order.
|
||||
for (int order = GetOrderMax(); order >= 0; order--)
|
||||
@ -366,43 +367,43 @@ namespace LibHac.FsSystem
|
||||
|
||||
public void Dump()
|
||||
{
|
||||
Assert.True(FreeLists != null);
|
||||
Assert.SdkRequires(FreeLists != null);
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public int GetOrderFromBytes(nuint size)
|
||||
{
|
||||
Assert.True(FreeLists != null);
|
||||
Assert.SdkRequires(FreeLists != null);
|
||||
return GetOrderFromBlockCount(GetBlockCountFromSize(size));
|
||||
}
|
||||
|
||||
public nuint GetBytesFromOrder(int order)
|
||||
{
|
||||
Assert.True(FreeLists != null);
|
||||
Assert.True(order >= 0);
|
||||
Assert.True(order <= GetOrderMax());
|
||||
Assert.SdkRequires(FreeLists != null);
|
||||
Assert.SdkRequiresGreaterEqual(order, 0);
|
||||
Assert.SdkRequiresLessEqual(order, GetOrderMax());
|
||||
|
||||
return GetBlockSize() << order;
|
||||
}
|
||||
|
||||
public int GetOrderMax()
|
||||
{
|
||||
Assert.True(FreeLists != null);
|
||||
Assert.SdkRequires(FreeLists != null);
|
||||
return OrderMax;
|
||||
}
|
||||
|
||||
public nuint GetBlockSize()
|
||||
{
|
||||
Assert.True(FreeLists != null);
|
||||
Assert.SdkRequires(FreeLists != null);
|
||||
return BlockSize;
|
||||
}
|
||||
|
||||
private void DivideBuddies(PageEntry* pageEntry, int requiredOrder, int chosenOrder)
|
||||
{
|
||||
Assert.True(FreeLists != null);
|
||||
Assert.True(requiredOrder >= 0);
|
||||
Assert.True(chosenOrder >= requiredOrder);
|
||||
Assert.True(chosenOrder <= GetOrderMax());
|
||||
Assert.SdkRequires(FreeLists != null);
|
||||
Assert.SdkRequiresGreaterEqual(requiredOrder, 0);
|
||||
Assert.SdkRequiresGreaterEqual(chosenOrder, requiredOrder);
|
||||
Assert.SdkRequiresLessEqual(chosenOrder, GetOrderMax());
|
||||
|
||||
// Start at the end of the entry.
|
||||
nuint address = GetAddressFromPageEntry(pageEntry) + GetBytesFromOrder(chosenOrder);
|
||||
@ -421,9 +422,9 @@ namespace LibHac.FsSystem
|
||||
|
||||
private void JoinBuddies(PageEntry* pageEntry, int order)
|
||||
{
|
||||
Assert.True(pageEntry != null);
|
||||
Assert.True(order >= 0);
|
||||
Assert.True(order <= GetOrderMax());
|
||||
Assert.SdkRequires(FreeLists != null);
|
||||
Assert.SdkRequiresGreaterEqual(order, 0);
|
||||
Assert.SdkRequiresLessEqual(order, GetOrderMax());
|
||||
|
||||
PageEntry* curEntry = pageEntry;
|
||||
int curOrder = order;
|
||||
@ -460,9 +461,9 @@ namespace LibHac.FsSystem
|
||||
|
||||
private PageEntry* GetBuddy(PageEntry* pageEntry, int order)
|
||||
{
|
||||
Assert.True(pageEntry != null);
|
||||
Assert.True(order >= 0);
|
||||
Assert.True(order <= GetOrderMax());
|
||||
Assert.SdkRequires(FreeLists != null);
|
||||
Assert.SdkRequiresGreaterEqual(order, 0);
|
||||
Assert.SdkRequiresLessEqual(order, GetOrderMax());
|
||||
|
||||
nuint address = GetAddressFromPageEntry(pageEntry);
|
||||
nuint offset = (nuint)GetBlockCountFromOrder(order) * GetBlockSize();
|
||||
@ -482,8 +483,8 @@ namespace LibHac.FsSystem
|
||||
|
||||
private PageEntry* GetFreePageEntry(int order)
|
||||
{
|
||||
Assert.True(order >= 0);
|
||||
Assert.True(order <= GetOrderMax());
|
||||
Assert.SdkRequiresGreaterEqual(order, 0);
|
||||
Assert.SdkRequiresLessEqual(order, GetOrderMax());
|
||||
|
||||
// Try orders from low to high until we find a free page entry.
|
||||
for (int curOrder = order; curOrder <= GetOrderMax(); curOrder++)
|
||||
@ -493,14 +494,14 @@ namespace LibHac.FsSystem
|
||||
{
|
||||
// The current list isn't empty, so grab an entry from it.
|
||||
PageEntry* pageEntry = freeList.PopFront();
|
||||
Assert.True(pageEntry != null);
|
||||
Assert.SdkAssert(pageEntry != null);
|
||||
|
||||
// Update size bookkeeping.
|
||||
TotalFreeSize -= GetBytesFromOrder(curOrder);
|
||||
|
||||
// If we allocated more memory than needed, free the unneeded portion.
|
||||
DivideBuddies(pageEntry, order, curOrder);
|
||||
Assert.True(pageEntry->Next == null);
|
||||
Assert.SdkAssert(pageEntry->Next == null);
|
||||
|
||||
// Return the newly-divided entry.
|
||||
return pageEntry;
|
||||
@ -513,7 +514,7 @@ namespace LibHac.FsSystem
|
||||
|
||||
private int GetOrderFromBlockCount(int blockCount)
|
||||
{
|
||||
Assert.True(blockCount >= 0);
|
||||
Assert.SdkRequiresGreaterEqual(blockCount, 0);
|
||||
|
||||
// Return the first order with a big enough block count.
|
||||
for (int order = 0; order <= GetOrderMax(); ++order)
|
||||
@ -537,17 +538,17 @@ namespace LibHac.FsSystem
|
||||
{
|
||||
var address = new UIntPtr(pageEntry);
|
||||
|
||||
Assert.True((nuint)HeapStart <= address);
|
||||
Assert.True(address < HeapStart + HeapSize);
|
||||
Assert.True(Alignment.IsAlignedPow2((nuint)address - HeapStart, (uint)GetBlockSize()));
|
||||
Assert.SdkRequiresGreaterEqual(address, HeapStart);
|
||||
Assert.SdkRequiresLess((nuint)address, HeapStart + HeapSize);
|
||||
Assert.SdkRequiresAligned((nuint)address - HeapStart, (int)GetBlockSize());
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
private PageEntry* GetPageEntryFromAddress(UIntPtr address)
|
||||
{
|
||||
Assert.True((nuint)HeapStart <= address);
|
||||
Assert.True(address < HeapStart + HeapSize);
|
||||
Assert.SdkRequiresGreaterEqual(address, HeapStart);
|
||||
Assert.SdkRequiresLess((nuint)address, HeapStart + HeapSize);
|
||||
|
||||
ulong blockStart = (ulong)HeapStart +
|
||||
Alignment.AlignDownPow2((nuint)address - HeapStart, (uint)GetBlockSize());
|
||||
@ -558,9 +559,9 @@ namespace LibHac.FsSystem
|
||||
{
|
||||
var address = (nuint)pageEntry;
|
||||
|
||||
Assert.True(HeapStart <= address);
|
||||
Assert.True(address < HeapStart + HeapSize);
|
||||
Assert.True(Alignment.IsAlignedPow2(address - HeapStart, (uint)GetBlockSize()));
|
||||
Assert.SdkRequiresGreaterEqual(address, (nuint)HeapStart);
|
||||
Assert.SdkRequiresLess(address, HeapStart + HeapSize);
|
||||
Assert.SdkRequiresAligned(address - HeapStart, (int)GetBlockSize());
|
||||
|
||||
return (int)((address - HeapStart) / GetBlockSize());
|
||||
}
|
||||
@ -616,7 +617,7 @@ namespace LibHac.FsSystem
|
||||
|
||||
public Buffer AllocateBufferByOrder(int order)
|
||||
{
|
||||
Assert.True(!HeapBuffer.IsEmpty);
|
||||
Assert.SdkRequires(!HeapBuffer.IsEmpty);
|
||||
|
||||
void* address = AllocateByOrder(order);
|
||||
|
||||
@ -624,11 +625,11 @@ namespace LibHac.FsSystem
|
||||
return Buffer.Empty;
|
||||
|
||||
nuint size = GetBytesFromOrder(order);
|
||||
Assert.True(size <= int.MaxValue);
|
||||
Assert.SdkLessEqual(size, (nuint)int.MaxValue);
|
||||
|
||||
// Get the offset relative to the heap start
|
||||
nuint offset = (nuint)address - (nuint)PinnedHeapMemoryHandle.Pointer;
|
||||
Assert.True(offset <= (nuint)HeapBuffer.Length);
|
||||
Assert.SdkLessEqual(offset, (nuint)HeapBuffer.Length);
|
||||
|
||||
// Get a slice of the Memory<byte> containing the entire heap
|
||||
return new Buffer(HeapBuffer.Slice((int)offset, (int)size));
|
||||
@ -636,8 +637,8 @@ namespace LibHac.FsSystem
|
||||
|
||||
public void Free(Buffer buffer)
|
||||
{
|
||||
Assert.True(!HeapBuffer.IsEmpty);
|
||||
Assert.True(!buffer.IsNull);
|
||||
Assert.SdkRequires(!HeapBuffer.IsEmpty);
|
||||
Assert.SdkRequires(!buffer.IsNull);
|
||||
|
||||
int order = GetOrderFromBytes((nuint)buffer.Length);
|
||||
void* pointer = Unsafe.AsPointer(ref MemoryMarshal.GetReference(buffer.Span));
|
||||
|
@ -56,7 +56,7 @@ namespace LibHac.FsSystem
|
||||
public void AddCacheSize(int diff) => _cacheSize += diff;
|
||||
public void SubtractCacheSize(int diff)
|
||||
{
|
||||
Assert.True(_cacheSize >= diff);
|
||||
Assert.SdkRequiresGreaterEqual(_cacheSize, diff);
|
||||
_cacheSize -= diff;
|
||||
}
|
||||
}
|
||||
@ -75,7 +75,7 @@ namespace LibHac.FsSystem
|
||||
// This function is left here anyway for completion's sake.
|
||||
public static int QueryWorkBufferSize(int maxCacheCount)
|
||||
{
|
||||
Assert.True(maxCacheCount > 0);
|
||||
Assert.SdkRequiresGreater(maxCacheCount, 0);
|
||||
|
||||
int entryAlignment = sizeof(CacheHandle);
|
||||
int attrInfoAlignment = Unsafe.SizeOf<nuint>();
|
||||
@ -89,7 +89,7 @@ namespace LibHac.FsSystem
|
||||
public Result Initialize(int maxCacheCount)
|
||||
{
|
||||
// Validate pre-conditions.
|
||||
Assert.True(Entries == null);
|
||||
Assert.SdkRequiresNull(Entries);
|
||||
|
||||
// Note: We don't have the option of using an external Entry buffer like the original C++ code
|
||||
// because Entry includes managed references so we can't cast a byte* to Entry* without pinning.
|
||||
@ -106,7 +106,7 @@ namespace LibHac.FsSystem
|
||||
EntryCount = 0;
|
||||
EntryCountMax = maxCacheCount;
|
||||
|
||||
Assert.True(Entries != null);
|
||||
Assert.SdkNotNull(Entries);
|
||||
|
||||
CacheCountMin = maxCacheCount / 16;
|
||||
CacheSizeMin = CacheCountMin * 0x100;
|
||||
@ -131,8 +131,8 @@ namespace LibHac.FsSystem
|
||||
UnsafeHelpers.SkipParamInit(out handle);
|
||||
|
||||
// Validate pre-conditions.
|
||||
Assert.True(Entries != null);
|
||||
Assert.True(!Unsafe.IsNullRef(ref handle));
|
||||
Assert.SdkRequiresNotNull(Entries);
|
||||
Assert.SdkRequiresNotNull(ref handle);
|
||||
|
||||
// Get the entry.
|
||||
ref Entry entry = ref AcquireEntry(buffer, attr);
|
||||
@ -165,8 +165,8 @@ namespace LibHac.FsSystem
|
||||
{
|
||||
// Validate pre-conditions.
|
||||
Unsafe.SkipInit(out buffer);
|
||||
Assert.True(Entries != null);
|
||||
Assert.True(!Unsafe.IsNullRef(ref buffer));
|
||||
Assert.SdkRequiresNotNull(Entries);
|
||||
Assert.SdkRequiresNotNull(ref buffer);
|
||||
|
||||
UnsafeHelpers.SkipParamInit(out buffer);
|
||||
|
||||
@ -189,8 +189,8 @@ namespace LibHac.FsSystem
|
||||
{
|
||||
// Validate pre-conditions.
|
||||
Unsafe.SkipInit(out buffer);
|
||||
Assert.True(Entries != null);
|
||||
Assert.True(!Unsafe.IsNullRef(ref buffer));
|
||||
Assert.SdkRequiresNotNull(Entries);
|
||||
Assert.SdkRequiresNotNull(ref buffer);
|
||||
|
||||
UnsafeHelpers.SkipParamInit(out buffer);
|
||||
|
||||
@ -203,7 +203,7 @@ namespace LibHac.FsSystem
|
||||
static bool CanUnregister(CacheHandleTable table, ref Entry entry)
|
||||
{
|
||||
ref AttrInfo attrInfo = ref table.FindAttrInfo(entry.GetBufferAttribute());
|
||||
Assert.True(!Unsafe.IsNullRef(ref attrInfo));
|
||||
Assert.SdkNotNull(ref attrInfo);
|
||||
|
||||
int ccm = table.GetCacheCountMin(entry.GetBufferAttribute());
|
||||
int csm = table.GetCacheSizeMin(entry.GetBufferAttribute());
|
||||
@ -227,32 +227,33 @@ namespace LibHac.FsSystem
|
||||
entry = ref Entries[0];
|
||||
}
|
||||
|
||||
Assert.True(!Unsafe.IsNullRef(ref entry));
|
||||
Assert.SdkNotNull(ref entry);
|
||||
UnregisterCore(out buffer, ref entry);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void UnregisterCore(out Buffer buffer, ref Entry entry)
|
||||
{
|
||||
|
||||
// Validate pre-conditions.
|
||||
Unsafe.SkipInit(out buffer);
|
||||
Assert.True(Entries != null);
|
||||
Assert.True(!Unsafe.IsNullRef(ref buffer));
|
||||
Assert.True(!Unsafe.IsNullRef(ref entry));
|
||||
Assert.SdkRequiresNotNull(Entries);
|
||||
Assert.SdkRequiresNotNull(ref buffer);
|
||||
Assert.SdkRequiresNotNull(ref entry);
|
||||
|
||||
UnsafeHelpers.SkipParamInit(out buffer);
|
||||
|
||||
// Get the attribute info.
|
||||
ref AttrInfo attrInfo = ref FindAttrInfo(entry.GetBufferAttribute());
|
||||
Assert.True(!Unsafe.IsNullRef(ref attrInfo));
|
||||
Assert.True(attrInfo.GetCacheCount() > 0);
|
||||
Assert.True(attrInfo.GetCacheSize() >= entry.GetSize());
|
||||
Assert.SdkNotNull(ref attrInfo);
|
||||
Assert.SdkGreater(attrInfo.GetCacheCount(), 0);
|
||||
Assert.SdkGreaterEqual(attrInfo.GetCacheSize(), entry.GetSize());
|
||||
|
||||
// Release from the attr info.
|
||||
attrInfo.DecrementCacheCount();
|
||||
attrInfo.SubtractCacheSize(entry.GetSize());
|
||||
|
||||
// Release from cached size.
|
||||
Assert.True(TotalCacheSize >= entry.GetSize());
|
||||
Assert.SdkGreaterEqual(TotalCacheSize, entry.GetSize());
|
||||
TotalCacheSize -= entry.GetSize();
|
||||
|
||||
// Release the entry.
|
||||
@ -262,7 +263,7 @@ namespace LibHac.FsSystem
|
||||
|
||||
public CacheHandle PublishCacheHandle()
|
||||
{
|
||||
Assert.True(Entries != null);
|
||||
Assert.SdkRequires(Entries != null);
|
||||
return ++CurrentHandle;
|
||||
}
|
||||
|
||||
@ -274,7 +275,7 @@ namespace LibHac.FsSystem
|
||||
private ref Entry AcquireEntry(Buffer buffer, BufferAttribute attr)
|
||||
{
|
||||
// Validate pre-conditions.
|
||||
Assert.True(Entries != null);
|
||||
Assert.SdkRequiresNotNull(Entries);
|
||||
|
||||
ref Entry entry = ref Unsafe.NullRef<Entry>();
|
||||
if (EntryCount < EntryCountMax)
|
||||
@ -282,7 +283,7 @@ namespace LibHac.FsSystem
|
||||
entry = ref Entries[EntryCount];
|
||||
entry.Initialize(PublishCacheHandle(), buffer, attr);
|
||||
EntryCount++;
|
||||
Assert.True(EntryCount == 1 || Entries[EntryCount - 2].GetHandle() < entry.GetHandle());
|
||||
Assert.SdkAssert(EntryCount == 1 || Entries[EntryCount - 2].GetHandle() < entry.GetHandle());
|
||||
}
|
||||
|
||||
return ref entry;
|
||||
@ -291,13 +292,13 @@ namespace LibHac.FsSystem
|
||||
private void ReleaseEntry(ref Entry entry)
|
||||
{
|
||||
// Validate pre-conditions.
|
||||
Assert.True(Entries != null);
|
||||
Assert.True(!Unsafe.IsNullRef(ref entry));
|
||||
Assert.SdkRequiresNotNull(Entries);
|
||||
Assert.SdkRequiresNotNull(ref entry);
|
||||
|
||||
// Ensure the entry is valid.
|
||||
Span<Entry> entryBuffer = Entries;
|
||||
Assert.True(!Unsafe.IsAddressLessThan(ref entry, ref MemoryMarshal.GetReference(entryBuffer)));
|
||||
Assert.True(Unsafe.IsAddressLessThan(ref entry,
|
||||
Assert.SdkAssert(!Unsafe.IsAddressLessThan(ref entry, ref MemoryMarshal.GetReference(entryBuffer)));
|
||||
Assert.SdkAssert(Unsafe.IsAddressLessThan(ref entry,
|
||||
ref Unsafe.Add(ref MemoryMarshal.GetReference(entryBuffer), entryBuffer.Length)));
|
||||
|
||||
// Get the index of the entry.
|
||||
@ -378,7 +379,7 @@ namespace LibHac.FsSystem
|
||||
private Buffer AllocateBufferImpl(int size, BufferAttribute attribute)
|
||||
{
|
||||
int order = BuddyHeap.GetOrderFromBytes((nuint)size);
|
||||
Assert.True(order >= 0);
|
||||
Assert.SdkAssert(order >= 0);
|
||||
|
||||
// Allocate space on the heap
|
||||
Buffer buffer;
|
||||
@ -397,7 +398,7 @@ namespace LibHac.FsSystem
|
||||
|
||||
// Successfully allocated a buffer.
|
||||
int allocatedSize = (int)BuddyHeap.GetBytesFromOrder(order);
|
||||
Assert.True(size <= allocatedSize);
|
||||
Assert.SdkAssert(size <= allocatedSize);
|
||||
|
||||
// Update heap stats
|
||||
int freeSize = (int)BuddyHeap.GetTotalFreeSize();
|
||||
@ -419,7 +420,7 @@ namespace LibHac.FsSystem
|
||||
|
||||
private void DeallocateBufferImpl(Buffer buffer)
|
||||
{
|
||||
Assert.True(BitUtil.IsPowerOfTwo(buffer.Length));
|
||||
Assert.SdkRequires(BitUtil.IsPowerOfTwo(buffer.Length));
|
||||
|
||||
BuddyHeap.Free(buffer);
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ namespace LibHac.FsSystem
|
||||
|
||||
public static Result FromSpan(out FsPath fsPath, ReadOnlySpan<byte> path)
|
||||
{
|
||||
Unsafe.SkipInit(out fsPath);
|
||||
UnsafeHelpers.SkipParamInit(out fsPath);
|
||||
|
||||
// Ensure null terminator even if the creation fails for safety
|
||||
fsPath.Str[MaxLength] = 0;
|
||||
|
@ -71,22 +71,22 @@ namespace LibHac.FsSystem
|
||||
|
||||
public void SetStorage(int index, SubStorage storage)
|
||||
{
|
||||
Assert.InRange(index, 0, StorageCount);
|
||||
Assert.SdkRequiresInRange(index, 0, StorageCount);
|
||||
DataStorage[index] = storage;
|
||||
}
|
||||
|
||||
public void SetStorage(int index, IStorage storage, long offset, long size)
|
||||
{
|
||||
Assert.InRange(index, 0, StorageCount);
|
||||
Assert.SdkRequiresInRange(index, 0, StorageCount);
|
||||
DataStorage[index] = new SubStorage(storage, offset, size);
|
||||
}
|
||||
|
||||
public Result GetEntryList(Span<Entry> entryBuffer, out int outputEntryCount, long offset, long size)
|
||||
{
|
||||
// Validate pre-conditions
|
||||
Assert.True(offset >= 0);
|
||||
Assert.True(size >= 0);
|
||||
Assert.True(IsInitialized());
|
||||
Assert.SdkRequiresLessEqual(0, offset);
|
||||
Assert.SdkRequiresLessEqual(0, size);
|
||||
Assert.SdkRequires(IsInitialized());
|
||||
|
||||
// Clear the out count
|
||||
outputEntryCount = 0;
|
||||
@ -153,8 +153,8 @@ namespace LibHac.FsSystem
|
||||
protected override unsafe Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
// Validate pre-conditions
|
||||
Assert.True(offset >= 0);
|
||||
Assert.True(IsInitialized());
|
||||
Assert.SdkRequiresLessEqual(0, offset);
|
||||
Assert.SdkRequires(IsInitialized());
|
||||
|
||||
// Succeed if there's nothing to read
|
||||
if (destination.Length == 0)
|
||||
@ -206,9 +206,9 @@ namespace LibHac.FsSystem
|
||||
private Result OperatePerEntry(long offset, long size, OperateFunc func)
|
||||
{
|
||||
// Validate preconditions
|
||||
Assert.True(offset >= 0);
|
||||
Assert.True(size >= 0);
|
||||
Assert.True(IsInitialized());
|
||||
Assert.SdkRequiresLessEqual(0, offset);
|
||||
Assert.SdkRequiresLessEqual(0, size);
|
||||
Assert.SdkRequires(IsInitialized());
|
||||
|
||||
// Succeed if there's nothing to operate on
|
||||
if (size == 0)
|
||||
@ -272,12 +272,12 @@ namespace LibHac.FsSystem
|
||||
// Get the offset of the entry in the data we read
|
||||
long dataOffset = currentOffset - currentEntryOffset;
|
||||
long dataSize = nextEntryOffset - currentEntryOffset - dataOffset;
|
||||
Assert.True(dataSize > 0);
|
||||
Assert.SdkLess(0, dataSize);
|
||||
|
||||
// Determine how much is left
|
||||
long remainingSize = endOffset - currentOffset;
|
||||
long currentSize = Math.Min(remainingSize, dataSize);
|
||||
Assert.True(currentSize <= size);
|
||||
Assert.SdkLessEqual(currentSize, size);
|
||||
|
||||
{
|
||||
SubStorage currentStorage = DataStorage[currentEntry.StorageIndex];
|
||||
|
@ -659,7 +659,7 @@ namespace LibHac.FsSystem.NcaUtils
|
||||
{
|
||||
// NCA0 encrypts the entire NCA body using AES-XTS instead of
|
||||
// using different encryption types and IVs for each section.
|
||||
Assert.Equal(0, Header.Version);
|
||||
Assert.SdkEqual(0, Header.Version);
|
||||
|
||||
if (openEncrypted == IsEncrypted)
|
||||
{
|
||||
|
@ -254,7 +254,7 @@ namespace LibHac.FsSystem.NcaUtils
|
||||
|
||||
private static bool CheckIfDecrypted(ReadOnlySpan<byte> header)
|
||||
{
|
||||
Assert.True(header.Length >= 0x400);
|
||||
Assert.SdkRequiresGreaterEqual(header.Length, 0x400);
|
||||
|
||||
// Check the magic value
|
||||
if (header[0x200] != 'N' || header[0x201] != 'C' || header[0x202] != 'A')
|
||||
|
@ -33,13 +33,13 @@ namespace LibHac.FsSystem
|
||||
|
||||
public Span<byte> GetBuffer()
|
||||
{
|
||||
Assert.NotNull(Array);
|
||||
Assert.SdkRequiresNotNull(Array);
|
||||
return Array.AsSpan(0, Length);
|
||||
}
|
||||
|
||||
public int GetSize()
|
||||
{
|
||||
Assert.NotNull(Array);
|
||||
Assert.SdkRequiresNotNull(Array);
|
||||
return Length;
|
||||
}
|
||||
|
||||
@ -56,10 +56,10 @@ namespace LibHac.FsSystem
|
||||
|
||||
private void AllocateCore(int idealSize, int requiredSize, bool enableLargeCapacity)
|
||||
{
|
||||
Assert.Null(Array);
|
||||
Assert.SdkRequiresNull(Array);
|
||||
|
||||
// Check that we can allocate this size.
|
||||
Assert.True(requiredSize <= GetAllocatableSizeMaxCore(enableLargeCapacity));
|
||||
Assert.SdkRequiresLessEqual(requiredSize, GetAllocatableSizeMaxCore(enableLargeCapacity));
|
||||
|
||||
int targetSize = Math.Min(Math.Max(idealSize, requiredSize),
|
||||
GetAllocatableSizeMaxCore(enableLargeCapacity));
|
||||
@ -80,17 +80,17 @@ namespace LibHac.FsSystem
|
||||
{
|
||||
// Shrink the buffer to empty.
|
||||
Shrink(0);
|
||||
Assert.Null(Array);
|
||||
Assert.SdkNull(Array);
|
||||
}
|
||||
|
||||
public void Shrink(int idealSize)
|
||||
{
|
||||
Assert.True(idealSize <= GetAllocatableSizeMaxCore(true));
|
||||
Assert.SdkRequiresLessEqual(idealSize, GetAllocatableSizeMaxCore(true));
|
||||
|
||||
// Check if we actually need to shrink.
|
||||
if (Length > idealSize)
|
||||
{
|
||||
Assert.NotNull(Array);
|
||||
Assert.SdkRequiresNotNull(Array);
|
||||
|
||||
// Pretend we shrank the buffer.
|
||||
Length = idealSize;
|
||||
|
@ -61,8 +61,8 @@ namespace LibHac.FsSystem.Save
|
||||
PrevIndex = InvalidIndex;
|
||||
// End default constructor code
|
||||
|
||||
Assert.NotNull(bufferedStorage);
|
||||
Assert.True(BufferedStorage == null);
|
||||
Assert.SdkRequiresNotNull(bufferedStorage);
|
||||
Assert.SdkRequires(BufferedStorage == null);
|
||||
|
||||
BufferedStorage = bufferedStorage;
|
||||
Link();
|
||||
@ -70,9 +70,9 @@ namespace LibHac.FsSystem.Save
|
||||
|
||||
public void FinalizeObject()
|
||||
{
|
||||
Assert.NotNull(BufferedStorage);
|
||||
Assert.NotNull(BufferedStorage.BufferManager);
|
||||
Assert.Equal(0, ReferenceCount);
|
||||
Assert.SdkRequiresNotNull(BufferedStorage);
|
||||
Assert.SdkRequiresNotNull(BufferedStorage.BufferManager);
|
||||
Assert.SdkRequiresEqual(0, ReferenceCount);
|
||||
|
||||
// If we're valid, acquire our cache handle and free our buffer.
|
||||
if (IsValid())
|
||||
@ -80,7 +80,7 @@ namespace LibHac.FsSystem.Save
|
||||
IBufferManager bufferManager = BufferedStorage.BufferManager;
|
||||
if (!_isDirty)
|
||||
{
|
||||
Assert.True(MemoryRange.IsNull);
|
||||
Assert.SdkAssert(MemoryRange.IsNull);
|
||||
MemoryRange = bufferManager.AcquireCache(CacheHandle);
|
||||
}
|
||||
|
||||
@ -107,15 +107,15 @@ namespace LibHac.FsSystem.Save
|
||||
/// </summary>
|
||||
public void Link()
|
||||
{
|
||||
Assert.NotNull(BufferedStorage);
|
||||
Assert.NotNull(BufferedStorage.BufferManager);
|
||||
Assert.True(ReferenceCount > 0);
|
||||
Assert.SdkRequiresNotNull(BufferedStorage);
|
||||
Assert.SdkRequiresNotNull(BufferedStorage.BufferManager);
|
||||
Assert.SdkRequiresLess(0, ReferenceCount);
|
||||
|
||||
ReferenceCount--;
|
||||
if (ReferenceCount == 0)
|
||||
{
|
||||
Assert.True(NextIndex == InvalidIndex);
|
||||
Assert.True(PrevIndex == InvalidIndex);
|
||||
Assert.SdkAssert(NextIndex == InvalidIndex);
|
||||
Assert.SdkAssert(PrevIndex == InvalidIndex);
|
||||
|
||||
// If the fetch list is empty we can simply add it as the only cache in the list.
|
||||
if (BufferedStorage.NextFetchCacheIndex == InvalidIndex)
|
||||
@ -140,8 +140,8 @@ namespace LibHac.FsSystem.Save
|
||||
} while (cache.Index != BufferedStorage.NextFetchCacheIndex);
|
||||
|
||||
// Verify the end of the fetch list loops back to the start.
|
||||
Assert.True(BufferedStorage.NextFetchCache.PrevIndex != InvalidIndex);
|
||||
Assert.Equal(BufferedStorage.NextFetchCache.Prev.NextIndex,
|
||||
Assert.SdkAssert(BufferedStorage.NextFetchCache.PrevIndex != InvalidIndex);
|
||||
Assert.SdkEqual(BufferedStorage.NextFetchCache.Prev.NextIndex,
|
||||
BufferedStorage.NextFetchCacheIndex);
|
||||
|
||||
// Link into the fetch list.
|
||||
@ -190,17 +190,17 @@ namespace LibHac.FsSystem.Save
|
||||
/// </summary>
|
||||
public void Unlink()
|
||||
{
|
||||
Assert.NotNull(BufferedStorage);
|
||||
Assert.True(ReferenceCount >= 0);
|
||||
Assert.SdkRequiresNotNull(BufferedStorage);
|
||||
Assert.SdkRequiresGreaterEqual(ReferenceCount, 0);
|
||||
|
||||
ReferenceCount++;
|
||||
if (ReferenceCount == 1)
|
||||
{
|
||||
// If we're the first to grab this Cache, the Cache should be in the BufferedStorage's fetch list.
|
||||
Assert.True(NextIndex != InvalidIndex);
|
||||
Assert.True(PrevIndex != InvalidIndex);
|
||||
Assert.True(Next.PrevIndex == Index);
|
||||
Assert.True(Prev.NextIndex == Index);
|
||||
Assert.SdkNotEqual(NextIndex, InvalidIndex);
|
||||
Assert.SdkNotEqual(PrevIndex, InvalidIndex);
|
||||
Assert.SdkEqual(Next.PrevIndex, Index);
|
||||
Assert.SdkEqual(Prev.NextIndex, Index);
|
||||
|
||||
// Set the new fetch list head if this Cache is the current head
|
||||
if (BufferedStorage.NextFetchCacheIndex == Index)
|
||||
@ -224,8 +224,8 @@ namespace LibHac.FsSystem.Save
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.True(NextIndex == InvalidIndex);
|
||||
Assert.True(PrevIndex == InvalidIndex);
|
||||
Assert.SdkEqual(NextIndex, InvalidIndex);
|
||||
Assert.SdkEqual(PrevIndex, InvalidIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -238,18 +238,18 @@ namespace LibHac.FsSystem.Save
|
||||
/// <param name="buffer">The buffer in which to place the read data.</param>
|
||||
public void Read(long offset, Span<byte> buffer)
|
||||
{
|
||||
Assert.NotNull(BufferedStorage);
|
||||
Assert.True(NextIndex == InvalidIndex);
|
||||
Assert.True(PrevIndex == InvalidIndex);
|
||||
Assert.True(IsValid());
|
||||
Assert.True(Hits(offset, 1));
|
||||
Assert.True(!MemoryRange.IsNull);
|
||||
Assert.SdkRequiresNotNull(BufferedStorage);
|
||||
Assert.SdkRequiresEqual(NextIndex, InvalidIndex);
|
||||
Assert.SdkRequiresEqual(PrevIndex, InvalidIndex);
|
||||
Assert.SdkRequires(IsValid());
|
||||
Assert.SdkRequires(Hits(offset, 1));
|
||||
Assert.SdkRequires(!MemoryRange.IsNull);
|
||||
|
||||
long readOffset = offset - Offset;
|
||||
long readableOffsetMax = BufferedStorage.BlockSize - buffer.Length;
|
||||
|
||||
Assert.True(readOffset >= 0);
|
||||
Assert.True(readOffset <= readableOffsetMax);
|
||||
Assert.SdkLessEqual(0, readOffset);
|
||||
Assert.SdkLessEqual(readOffset, readableOffsetMax);
|
||||
|
||||
Span<byte> cacheBuffer = MemoryRange.Span.Slice((int)readOffset, buffer.Length);
|
||||
cacheBuffer.CopyTo(buffer);
|
||||
@ -264,18 +264,18 @@ namespace LibHac.FsSystem.Save
|
||||
/// <param name="buffer">The buffer containing the data to be written.</param>
|
||||
public void Write(long offset, ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
Assert.NotNull(BufferedStorage);
|
||||
Assert.True(NextIndex == InvalidIndex);
|
||||
Assert.True(PrevIndex == InvalidIndex);
|
||||
Assert.True(IsValid());
|
||||
Assert.True(Hits(offset, 1));
|
||||
Assert.True(!MemoryRange.IsNull);
|
||||
Assert.SdkRequiresNotNull(BufferedStorage);
|
||||
Assert.SdkRequiresEqual(NextIndex, InvalidIndex);
|
||||
Assert.SdkRequiresEqual(PrevIndex, InvalidIndex);
|
||||
Assert.SdkRequires(IsValid());
|
||||
Assert.SdkRequires(Hits(offset, 1));
|
||||
Assert.SdkRequires(!MemoryRange.IsNull);
|
||||
|
||||
long writeOffset = offset - Offset;
|
||||
long writableOffsetMax = BufferedStorage.BlockSize - buffer.Length;
|
||||
|
||||
Assert.True(writeOffset >= 0);
|
||||
Assert.True(writeOffset <= writableOffsetMax);
|
||||
Assert.SdkLessEqual(0, writeOffset);
|
||||
Assert.SdkLessEqual(writeOffset, writableOffsetMax);
|
||||
|
||||
Span<byte> cacheBuffer = MemoryRange.Span.Slice((int)writeOffset, buffer.Length);
|
||||
buffer.CopyTo(cacheBuffer);
|
||||
@ -289,14 +289,14 @@ namespace LibHac.FsSystem.Save
|
||||
/// <returns>The <see cref="Result"/> of the operation.</returns>
|
||||
public Result Flush()
|
||||
{
|
||||
Assert.NotNull(BufferedStorage);
|
||||
Assert.True(NextIndex == InvalidIndex);
|
||||
Assert.True(PrevIndex == InvalidIndex);
|
||||
Assert.True(IsValid());
|
||||
Assert.SdkRequiresNotNull(BufferedStorage);
|
||||
Assert.SdkRequiresEqual(NextIndex, InvalidIndex);
|
||||
Assert.SdkRequiresEqual(PrevIndex, InvalidIndex);
|
||||
Assert.SdkRequires(IsValid());
|
||||
|
||||
if (_isDirty)
|
||||
{
|
||||
Assert.True(!MemoryRange.IsNull);
|
||||
Assert.SdkRequires(!MemoryRange.IsNull);
|
||||
|
||||
long baseSize = BufferedStorage.BaseStorageSize;
|
||||
long blockSize = BufferedStorage.BlockSize;
|
||||
@ -304,7 +304,7 @@ namespace LibHac.FsSystem.Save
|
||||
|
||||
SubStorage baseStorage = BufferedStorage.BaseStorage;
|
||||
Span<byte> cacheBuffer = MemoryRange.Span;
|
||||
Assert.True(flushSize == cacheBuffer.Length);
|
||||
Assert.SdkEqual(flushSize, cacheBuffer.Length);
|
||||
|
||||
Result rc = baseStorage.Write(Offset, cacheBuffer);
|
||||
if (rc.IsFailure()) return rc;
|
||||
@ -327,12 +327,12 @@ namespace LibHac.FsSystem.Save
|
||||
/// <see cref="Cache"/> is prepared to fetch; <see langword="false"/> if not.</returns>
|
||||
public (Result Result, bool IsPrepared) PrepareFetch()
|
||||
{
|
||||
Assert.NotNull(BufferedStorage);
|
||||
Assert.NotNull(BufferedStorage.BufferManager);
|
||||
Assert.True(NextIndex == InvalidIndex);
|
||||
Assert.True(PrevIndex == InvalidIndex);
|
||||
Assert.True(IsValid());
|
||||
Assert.True(Monitor.IsEntered(BufferedStorage.Locker));
|
||||
Assert.SdkRequiresNotNull(BufferedStorage);
|
||||
Assert.SdkRequiresNotNull(BufferedStorage.BufferManager);
|
||||
Assert.SdkRequiresEqual(NextIndex, InvalidIndex);
|
||||
Assert.SdkRequiresEqual(PrevIndex, InvalidIndex);
|
||||
Assert.SdkRequires(IsValid());
|
||||
Assert.SdkRequires(Monitor.IsEntered(BufferedStorage.Locker));
|
||||
|
||||
(Result Result, bool IsPrepared) result = (Result.Success, false);
|
||||
|
||||
@ -357,13 +357,13 @@ namespace LibHac.FsSystem.Save
|
||||
/// </summary>
|
||||
public void UnprepareFetch()
|
||||
{
|
||||
Assert.NotNull(BufferedStorage);
|
||||
Assert.NotNull(BufferedStorage.BufferManager);
|
||||
Assert.True(NextIndex == InvalidIndex);
|
||||
Assert.True(PrevIndex == InvalidIndex);
|
||||
Assert.True(!IsValid());
|
||||
Assert.True(!_isDirty);
|
||||
Assert.True(Monitor.IsEntered(BufferedStorage.Locker));
|
||||
Assert.SdkRequiresNotNull(BufferedStorage);
|
||||
Assert.SdkRequiresNotNull(BufferedStorage.BufferManager);
|
||||
Assert.SdkRequiresEqual(NextIndex, InvalidIndex);
|
||||
Assert.SdkRequiresEqual(PrevIndex, InvalidIndex);
|
||||
Assert.SdkRequires(!IsValid());
|
||||
Assert.SdkRequires(!_isDirty);
|
||||
Assert.SdkRequires(Monitor.IsEntered(BufferedStorage.Locker));
|
||||
|
||||
_isValid = true;
|
||||
ReferenceCount = 1;
|
||||
@ -377,12 +377,12 @@ namespace LibHac.FsSystem.Save
|
||||
/// <see cref="ResultFs.BufferAllocationFailed"/>: A buffer could not be allocated.</returns>
|
||||
public Result Fetch(long offset)
|
||||
{
|
||||
Assert.NotNull(BufferedStorage);
|
||||
Assert.NotNull(BufferedStorage.BufferManager);
|
||||
Assert.True(NextIndex == InvalidIndex);
|
||||
Assert.True(PrevIndex == InvalidIndex);
|
||||
Assert.True(!IsValid());
|
||||
Assert.True(!_isDirty);
|
||||
Assert.SdkRequiresNotNull(BufferedStorage);
|
||||
Assert.SdkRequiresNotNull(BufferedStorage.BufferManager);
|
||||
Assert.SdkRequiresEqual(NextIndex, InvalidIndex);
|
||||
Assert.SdkRequiresEqual(PrevIndex, InvalidIndex);
|
||||
Assert.SdkRequires(!IsValid());
|
||||
Assert.SdkRequires(!_isDirty);
|
||||
|
||||
Result rc;
|
||||
|
||||
@ -399,7 +399,7 @@ namespace LibHac.FsSystem.Save
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
Offset = fetchParam.Offset;
|
||||
Assert.True(Hits(offset, 1));
|
||||
Assert.SdkAssert(Hits(offset, 1));
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
@ -415,13 +415,13 @@ namespace LibHac.FsSystem.Save
|
||||
/// <see cref="ResultFs.BufferAllocationFailed"/>: A buffer could not be allocated.</returns>
|
||||
public Result FetchFromBuffer(long offset, ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
Assert.NotNull(BufferedStorage);
|
||||
Assert.NotNull(BufferedStorage.BufferManager);
|
||||
Assert.True(NextIndex == InvalidIndex);
|
||||
Assert.True(PrevIndex == InvalidIndex);
|
||||
Assert.True(!IsValid());
|
||||
Assert.True(!_isDirty);
|
||||
Assert.True(Alignment.IsAlignedPow2(offset, (uint)BufferedStorage.BlockSize));
|
||||
Assert.SdkRequiresNotNull(BufferedStorage);
|
||||
Assert.SdkRequiresNotNull(BufferedStorage.BufferManager);
|
||||
Assert.SdkRequiresEqual(NextIndex, InvalidIndex);
|
||||
Assert.SdkRequiresEqual(PrevIndex, InvalidIndex);
|
||||
Assert.SdkRequires(!IsValid());
|
||||
Assert.SdkRequires(!_isDirty);
|
||||
Assert.SdkRequiresAligned((ulong)offset, (int)BufferedStorage.BlockSize);
|
||||
|
||||
// Make sure this Cache has an allocated buffer
|
||||
if (MemoryRange.IsNull)
|
||||
@ -431,12 +431,12 @@ namespace LibHac.FsSystem.Save
|
||||
}
|
||||
|
||||
CalcFetchParameter(out FetchParameter fetchParam, offset);
|
||||
Assert.Equal(fetchParam.Offset, offset);
|
||||
Assert.True(fetchParam.Buffer.Length <= buffer.Length);
|
||||
Assert.SdkEqual(fetchParam.Offset, offset);
|
||||
Assert.SdkLessEqual(fetchParam.Buffer.Length, buffer.Length);
|
||||
|
||||
buffer.Slice(0, fetchParam.Buffer.Length).CopyTo(fetchParam.Buffer);
|
||||
Offset = fetchParam.Offset;
|
||||
Assert.True(Hits(offset, 1));
|
||||
Assert.SdkAssert(Hits(offset, 1));
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
@ -448,9 +448,9 @@ namespace LibHac.FsSystem.Save
|
||||
/// <see langword="false"/> if the buffer has been evicted from the <see cref="IBufferManager"/> cache.</returns>
|
||||
public bool TryAcquireCache()
|
||||
{
|
||||
Assert.NotNull(BufferedStorage);
|
||||
Assert.NotNull(BufferedStorage.BufferManager);
|
||||
Assert.True(IsValid());
|
||||
Assert.SdkRequiresNotNull(BufferedStorage);
|
||||
Assert.SdkRequiresNotNull(BufferedStorage.BufferManager);
|
||||
Assert.SdkRequires(IsValid());
|
||||
|
||||
if (!MemoryRange.IsNull)
|
||||
return true;
|
||||
@ -465,7 +465,7 @@ namespace LibHac.FsSystem.Save
|
||||
/// </summary>
|
||||
public void Invalidate()
|
||||
{
|
||||
Assert.NotNull(BufferedStorage);
|
||||
Assert.SdkRequiresNotNull(BufferedStorage);
|
||||
_isValid = false;
|
||||
}
|
||||
|
||||
@ -476,7 +476,7 @@ namespace LibHac.FsSystem.Save
|
||||
/// or if anybody currently has a reference to this Cache. Otherwise, <see langword="false"/>.</returns>
|
||||
public bool IsValid()
|
||||
{
|
||||
Assert.NotNull(BufferedStorage);
|
||||
Assert.SdkRequiresNotNull(BufferedStorage);
|
||||
|
||||
return _isValid || ReferenceCount > 0;
|
||||
}
|
||||
@ -489,7 +489,7 @@ namespace LibHac.FsSystem.Save
|
||||
/// Otherwise, <see langword="false"/>.</returns>
|
||||
public bool IsDirty()
|
||||
{
|
||||
Assert.NotNull(BufferedStorage);
|
||||
Assert.SdkRequiresNotNull(BufferedStorage);
|
||||
|
||||
return _isDirty;
|
||||
}
|
||||
@ -503,7 +503,7 @@ namespace LibHac.FsSystem.Save
|
||||
/// Otherwise, <see langword="false"/>.</returns>
|
||||
public bool Hits(long offset, long size)
|
||||
{
|
||||
Assert.NotNull(BufferedStorage);
|
||||
Assert.SdkRequiresNotNull(BufferedStorage);
|
||||
|
||||
long blockSize = BufferedStorage.BlockSize;
|
||||
return (offset < Offset + blockSize) && (Offset < offset + size);
|
||||
@ -518,7 +518,7 @@ namespace LibHac.FsSystem.Save
|
||||
private Result AllocateFetchBuffer()
|
||||
{
|
||||
IBufferManager bufferManager = BufferedStorage.BufferManager;
|
||||
Assert.True(bufferManager.AcquireCache(CacheHandle).IsNull);
|
||||
Assert.SdkAssert(bufferManager.AcquireCache(CacheHandle).IsNull);
|
||||
|
||||
Result rc = BufferManagerUtility.AllocateBufferUsingBufferManagerContext(out Buffer bufferTemp,
|
||||
bufferManager, (int)BufferedStorage.BlockSize, new IBufferManager.BufferAttribute(),
|
||||
@ -545,8 +545,8 @@ namespace LibHac.FsSystem.Save
|
||||
long cacheSize = Math.Min(blockSize, remainingSize);
|
||||
Span<byte> cacheBuffer = MemoryRange.Span.Slice(0, (int)cacheSize);
|
||||
|
||||
Assert.True(offset >= 0);
|
||||
Assert.True(offset < baseSize);
|
||||
Assert.SdkLessEqual(0, offset);
|
||||
Assert.SdkLess(offset, baseSize);
|
||||
|
||||
fetchParam = new FetchParameter
|
||||
{
|
||||
@ -569,7 +569,7 @@ namespace LibHac.FsSystem.Save
|
||||
|
||||
public SharedCache(BufferedStorage bufferedStorage)
|
||||
{
|
||||
Assert.NotNull(bufferedStorage);
|
||||
Assert.SdkRequiresNotNull(bufferedStorage);
|
||||
Cache = default;
|
||||
StartCache = new Ref<Cache>(ref bufferedStorage.NextAcquireCache);
|
||||
BufferedStorage = bufferedStorage;
|
||||
@ -593,23 +593,23 @@ namespace LibHac.FsSystem.Save
|
||||
/// or if all matching Caches have already been iterated.</returns>
|
||||
public bool AcquireNextOverlappedCache(long offset, long size)
|
||||
{
|
||||
Assert.NotNull(BufferedStorage);
|
||||
Assert.SdkRequiresNotNull(BufferedStorage);
|
||||
|
||||
bool isFirst = Cache.IsNull;
|
||||
ref Cache start = ref isFirst ? ref StartCache.Value : ref Unsafe.Add(ref Cache.Value, 1);
|
||||
|
||||
// Make sure the Cache instance is in-range.
|
||||
Assert.False(Unsafe.IsAddressLessThan(ref start,
|
||||
Assert.SdkAssert(!Unsafe.IsAddressLessThan(ref start,
|
||||
ref MemoryMarshal.GetArrayDataReference(BufferedStorage.Caches)));
|
||||
|
||||
Assert.False(Unsafe.IsAddressGreaterThan(ref start,
|
||||
Assert.SdkAssert(!Unsafe.IsAddressGreaterThan(ref start,
|
||||
ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(BufferedStorage.Caches),
|
||||
BufferedStorage.CacheCount)));
|
||||
|
||||
lock (BufferedStorage.Locker)
|
||||
{
|
||||
Release();
|
||||
Assert.True(Cache.IsNull);
|
||||
Assert.SdkAssert(Cache.IsNull);
|
||||
|
||||
for (ref Cache cache = ref start; ; cache = ref Unsafe.Add(ref cache, 1))
|
||||
{
|
||||
@ -650,7 +650,7 @@ namespace LibHac.FsSystem.Save
|
||||
/// or if all dirty Caches have already been iterated.</returns>
|
||||
public bool AcquireNextDirtyCache()
|
||||
{
|
||||
Assert.NotNull(BufferedStorage);
|
||||
Assert.SdkRequiresNotNull(BufferedStorage);
|
||||
|
||||
ref Cache start = ref Cache.IsNull
|
||||
? ref MemoryMarshal.GetArrayDataReference(BufferedStorage.Caches)
|
||||
@ -660,13 +660,13 @@ namespace LibHac.FsSystem.Save
|
||||
BufferedStorage.CacheCount);
|
||||
|
||||
// Validate the range.
|
||||
Assert.False(Unsafe.IsAddressLessThan(ref start,
|
||||
Assert.SdkAssert(!Unsafe.IsAddressLessThan(ref start,
|
||||
ref MemoryMarshal.GetArrayDataReference(BufferedStorage.Caches)));
|
||||
|
||||
Assert.False(Unsafe.IsAddressGreaterThan(ref start, ref end));
|
||||
Assert.SdkAssert(!Unsafe.IsAddressGreaterThan(ref start, ref end));
|
||||
|
||||
Release();
|
||||
Assert.True(Cache.IsNull);
|
||||
Assert.SdkAssert(Cache.IsNull);
|
||||
|
||||
// Find the next dirty Cache
|
||||
for (ref Cache cache = ref start;
|
||||
@ -693,7 +693,7 @@ namespace LibHac.FsSystem.Save
|
||||
/// or if all valid Caches have already been iterated.</returns>
|
||||
public bool AcquireNextValidCache()
|
||||
{
|
||||
Assert.NotNull(BufferedStorage);
|
||||
Assert.SdkRequiresNotNull(BufferedStorage);
|
||||
|
||||
ref Cache start = ref Cache.IsNull
|
||||
? ref MemoryMarshal.GetArrayDataReference(BufferedStorage.Caches)
|
||||
@ -703,13 +703,13 @@ namespace LibHac.FsSystem.Save
|
||||
BufferedStorage.CacheCount);
|
||||
|
||||
// Validate the range.
|
||||
Assert.False(Unsafe.IsAddressLessThan(ref start,
|
||||
Assert.SdkAssert(!Unsafe.IsAddressLessThan(ref start,
|
||||
ref MemoryMarshal.GetArrayDataReference(BufferedStorage.Caches)));
|
||||
|
||||
Assert.False(Unsafe.IsAddressGreaterThan(ref start, ref end));
|
||||
Assert.SdkAssert(!Unsafe.IsAddressGreaterThan(ref start, ref end));
|
||||
|
||||
Release();
|
||||
Assert.True(Cache.IsNull);
|
||||
Assert.SdkAssert(Cache.IsNull);
|
||||
|
||||
// Find the next valid Cache
|
||||
for (ref Cache cache = ref start;
|
||||
@ -736,12 +736,12 @@ namespace LibHac.FsSystem.Save
|
||||
/// Otherwise, <see langword="false"/>.</returns>
|
||||
public bool AcquireFetchableCache()
|
||||
{
|
||||
Assert.NotNull(BufferedStorage);
|
||||
Assert.SdkRequiresNotNull(BufferedStorage);
|
||||
|
||||
lock (BufferedStorage.Locker)
|
||||
{
|
||||
Release();
|
||||
Assert.True(Cache.IsNull);
|
||||
Assert.SdkAssert(Cache.IsNull);
|
||||
|
||||
Cache = new Ref<Cache>(ref BufferedStorage.NextFetchCache);
|
||||
|
||||
@ -766,7 +766,7 @@ namespace LibHac.FsSystem.Save
|
||||
/// <param name="buffer">The buffer in which to place the read data.</param>
|
||||
public void Read(long offset, Span<byte> buffer)
|
||||
{
|
||||
Assert.True(!Cache.IsNull);
|
||||
Assert.SdkRequires(!Cache.IsNull);
|
||||
Cache.Value.Read(offset, buffer);
|
||||
}
|
||||
|
||||
@ -779,7 +779,7 @@ namespace LibHac.FsSystem.Save
|
||||
/// <param name="buffer">The buffer containing the data to be written.</param>
|
||||
public void Write(long offset, ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
Assert.True(!Cache.IsNull);
|
||||
Assert.SdkRequires(!Cache.IsNull);
|
||||
Cache.Value.Write(offset, buffer);
|
||||
}
|
||||
|
||||
@ -790,7 +790,7 @@ namespace LibHac.FsSystem.Save
|
||||
/// <returns>The <see cref="Result"/> of the operation.</returns>
|
||||
public Result Flush()
|
||||
{
|
||||
Assert.True(!Cache.IsNull);
|
||||
Assert.SdkRequires(!Cache.IsNull);
|
||||
return Cache.Value.Flush();
|
||||
}
|
||||
|
||||
@ -800,7 +800,7 @@ namespace LibHac.FsSystem.Save
|
||||
/// </summary>
|
||||
public void Invalidate()
|
||||
{
|
||||
Assert.True(!Cache.IsNull);
|
||||
Assert.SdkRequires(!Cache.IsNull);
|
||||
Cache.Value.Invalidate();
|
||||
}
|
||||
|
||||
@ -813,7 +813,7 @@ namespace LibHac.FsSystem.Save
|
||||
/// covers any of the input range. Otherwise, <see langword="false"/>.</returns>
|
||||
public bool Hits(long offset, long size)
|
||||
{
|
||||
Assert.True(!Cache.IsNull);
|
||||
Assert.SdkRequires(!Cache.IsNull);
|
||||
return Cache.Value.Hits(offset, size);
|
||||
}
|
||||
|
||||
@ -825,10 +825,10 @@ namespace LibHac.FsSystem.Save
|
||||
if (!Cache.IsNull)
|
||||
{
|
||||
// Make sure the Cache instance is in-range.
|
||||
Assert.False(Unsafe.IsAddressLessThan(ref Cache.Value,
|
||||
Assert.SdkAssert(!Unsafe.IsAddressLessThan(ref Cache.Value,
|
||||
ref MemoryMarshal.GetArrayDataReference(BufferedStorage.Caches)));
|
||||
|
||||
Assert.False(Unsafe.IsAddressGreaterThan(ref Cache.Value,
|
||||
Assert.SdkAssert(!Unsafe.IsAddressGreaterThan(ref Cache.Value,
|
||||
ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(BufferedStorage.Caches),
|
||||
BufferedStorage.CacheCount)));
|
||||
|
||||
@ -850,7 +850,7 @@ namespace LibHac.FsSystem.Save
|
||||
|
||||
public UniqueCache(BufferedStorage bufferedStorage)
|
||||
{
|
||||
Assert.NotNull(bufferedStorage);
|
||||
Assert.SdkRequiresNotNull(bufferedStorage);
|
||||
Cache = default;
|
||||
BufferedStorage = bufferedStorage;
|
||||
}
|
||||
@ -878,8 +878,8 @@ namespace LibHac.FsSystem.Save
|
||||
/// access to the <see cref="Cache"/> was gained; <see langword="false"/> if not.</returns>
|
||||
public (Result Result, bool wasUpgradeSuccessful) Upgrade(in SharedCache sharedCache)
|
||||
{
|
||||
Assert.True(BufferedStorage == sharedCache.BufferedStorage);
|
||||
Assert.True(!sharedCache.Cache.IsNull);
|
||||
Assert.SdkRequires(BufferedStorage == sharedCache.BufferedStorage);
|
||||
Assert.SdkRequires(!sharedCache.Cache.IsNull);
|
||||
|
||||
lock (BufferedStorage.Locker)
|
||||
{
|
||||
@ -901,7 +901,7 @@ namespace LibHac.FsSystem.Save
|
||||
/// <see cref="ResultFs.BufferAllocationFailed"/>: A buffer could not be allocated.</returns>
|
||||
public Result Fetch(long offset)
|
||||
{
|
||||
Assert.True(!Cache.IsNull);
|
||||
Assert.SdkRequires(!Cache.IsNull);
|
||||
|
||||
return Cache.Value.Fetch(offset);
|
||||
}
|
||||
@ -917,7 +917,7 @@ namespace LibHac.FsSystem.Save
|
||||
/// <see cref="ResultFs.BufferAllocationFailed"/>: A buffer could not be allocated.</returns>
|
||||
public Result FetchFromBuffer(long offset, ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
Assert.True(!Cache.IsNull);
|
||||
Assert.SdkRequires(!Cache.IsNull);
|
||||
|
||||
return Cache.Value.FetchFromBuffer(offset, buffer);
|
||||
}
|
||||
@ -987,11 +987,11 @@ namespace LibHac.FsSystem.Save
|
||||
/// <returns></returns>
|
||||
public Result Initialize(SubStorage baseStorage, IBufferManager bufferManager, int blockSize, int cacheCount)
|
||||
{
|
||||
Assert.NotNull(baseStorage);
|
||||
Assert.NotNull(bufferManager);
|
||||
Assert.True(blockSize > 0);
|
||||
Assert.True(BitUtil.IsPowerOfTwo(blockSize));
|
||||
Assert.True(cacheCount > 0);
|
||||
Assert.SdkRequiresNotNull(baseStorage);
|
||||
Assert.SdkRequiresNotNull(bufferManager);
|
||||
Assert.SdkRequiresLess(0, blockSize);
|
||||
Assert.SdkRequires(BitUtil.IsPowerOfTwo(blockSize));
|
||||
Assert.SdkRequiresLess(0, cacheCount);
|
||||
|
||||
// Get the base storage size.
|
||||
Result rc = baseStorage.GetSize(out _baseStorageSize);
|
||||
@ -1055,7 +1055,7 @@ namespace LibHac.FsSystem.Save
|
||||
|
||||
protected override Result DoRead(long offset, Span<byte> destination)
|
||||
{
|
||||
Assert.True(IsInitialized());
|
||||
Assert.SdkRequires(IsInitialized());
|
||||
|
||||
// Succeed if zero size.
|
||||
if (destination.Length == 0)
|
||||
@ -1067,7 +1067,7 @@ namespace LibHac.FsSystem.Save
|
||||
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
Assert.True(IsInitialized());
|
||||
Assert.SdkRequires(IsInitialized());
|
||||
|
||||
// Succeed if zero size.
|
||||
if (source.Length == 0)
|
||||
@ -1079,7 +1079,7 @@ namespace LibHac.FsSystem.Save
|
||||
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
Assert.True(IsInitialized());
|
||||
Assert.SdkRequires(IsInitialized());
|
||||
|
||||
size = BaseStorageSize;
|
||||
return Result.Success;
|
||||
@ -1087,7 +1087,7 @@ namespace LibHac.FsSystem.Save
|
||||
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
Assert.True(IsInitialized());
|
||||
Assert.SdkRequires(IsInitialized());
|
||||
|
||||
Result rc;
|
||||
long prevSize = BaseStorageSize;
|
||||
@ -1108,7 +1108,7 @@ namespace LibHac.FsSystem.Save
|
||||
cache.Invalidate();
|
||||
}
|
||||
|
||||
Assert.True(!cache.AcquireNextOverlappedCache(invalidateOffset, invalidateSize));
|
||||
Assert.SdkAssert(!cache.AcquireNextOverlappedCache(invalidateOffset, invalidateSize));
|
||||
}
|
||||
}
|
||||
else if (size < prevSize)
|
||||
@ -1146,7 +1146,7 @@ namespace LibHac.FsSystem.Save
|
||||
protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
Assert.True(IsInitialized());
|
||||
Assert.SdkRequires(IsInitialized());
|
||||
|
||||
// Invalidate caches if needed.
|
||||
if (operationId == OperationId.InvalidateCache)
|
||||
@ -1162,7 +1162,7 @@ namespace LibHac.FsSystem.Save
|
||||
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
Assert.True(IsInitialized());
|
||||
Assert.SdkRequires(IsInitialized());
|
||||
|
||||
// Flush caches.
|
||||
using var cache = new SharedCache(this);
|
||||
@ -1181,7 +1181,7 @@ namespace LibHac.FsSystem.Save
|
||||
/// </summary>
|
||||
public void InvalidateCaches()
|
||||
{
|
||||
Assert.True(IsInitialized());
|
||||
Assert.SdkRequires(IsInitialized());
|
||||
|
||||
using var cache = new SharedCache(this);
|
||||
while (cache.AcquireNextValidCache())
|
||||
@ -1252,7 +1252,8 @@ namespace LibHac.FsSystem.Save
|
||||
/// <returns>The <see cref="Result"/> of the operation.</returns>
|
||||
private Result ReadCore(long offset, Span<byte> destination)
|
||||
{
|
||||
Assert.NotNull(Caches);
|
||||
Assert.SdkRequiresNotNull(Caches);
|
||||
Assert.SdkRequiresNotNull(destination);
|
||||
|
||||
// Validate the offset.
|
||||
long baseStorageSize = BaseStorageSize;
|
||||
@ -1469,7 +1470,7 @@ namespace LibHac.FsSystem.Save
|
||||
}
|
||||
|
||||
long currentOffset = currentOffsetEnd - currentSize;
|
||||
Assert.True(currentOffset >= 0);
|
||||
Assert.SdkGreaterEqual(currentOffset, 0);
|
||||
|
||||
using var cache = new SharedCache(this);
|
||||
|
||||
@ -1617,7 +1618,8 @@ namespace LibHac.FsSystem.Save
|
||||
|
||||
private Result WriteCore(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
Assert.NotNull(Caches);
|
||||
Assert.SdkRequiresNotNull(Caches);
|
||||
Assert.SdkRequiresNotNull(source);
|
||||
|
||||
// Validate the offset.
|
||||
long baseStorageSize = BaseStorageSize;
|
||||
|
@ -80,7 +80,7 @@ namespace LibHac.FsSystem
|
||||
Shared.Move(out _semaphore, ref semaphore);
|
||||
Shared.Move(out _pinnedObject, ref pinnedObject);
|
||||
|
||||
Assert.True(_semaphore.IsLocked);
|
||||
Assert.SdkAssert(_semaphore.IsLocked);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
@ -64,7 +64,7 @@ namespace LibHac.Kernel
|
||||
private static Result GetKipOffsets(out (int offset, int size)[] kipOffsets, IStorage iniStorage,
|
||||
int processCount)
|
||||
{
|
||||
Assert.True(processCount <= MaxProcessCount);
|
||||
Assert.SdkRequiresLessEqual(processCount, MaxProcessCount);
|
||||
|
||||
UnsafeHelpers.SkipParamInit(out kipOffsets);
|
||||
|
||||
|
@ -410,8 +410,8 @@ namespace LibHac.Kvdb
|
||||
public Result Initialize(int capacity, MemoryResource memoryResource)
|
||||
{
|
||||
// Initialize must only be called once.
|
||||
Assert.Null(_entries);
|
||||
Assert.NotNull(memoryResource);
|
||||
Assert.SdkRequiresNull(_entries);
|
||||
Assert.SdkRequiresNotNull(memoryResource);
|
||||
|
||||
// FS uses the provided MemoryResource to allocate the KeyValue array.
|
||||
// We can't do that here because the array will contain managed references.
|
||||
@ -487,7 +487,7 @@ namespace LibHac.Kvdb
|
||||
if (_count > 0)
|
||||
{
|
||||
// The key being added must be greater than the last key in the list.
|
||||
Assert.True(key.CompareTo(_entries[_count - 1].Key) > 0);
|
||||
Assert.SdkGreater(key, _entries[_count - 1].Key);
|
||||
}
|
||||
|
||||
_entries[_count] = new KeyValue(in key, value);
|
||||
@ -671,7 +671,7 @@ namespace LibHac.Kvdb
|
||||
// An entry was added. entryIndex is the index of the new entry.
|
||||
|
||||
// Only one entry can be added at a time.
|
||||
Assert.Equal(newLength, _length + 1);
|
||||
Assert.SdkEqual(newLength, _length + 1);
|
||||
|
||||
if (entryIndex <= _index)
|
||||
{
|
||||
@ -687,7 +687,7 @@ namespace LibHac.Kvdb
|
||||
// An entry was removed. entryIndex is the index where the removed entry used to be.
|
||||
|
||||
// Only one entry can be removed at a time.
|
||||
Assert.Equal(newLength, _length - 1);
|
||||
Assert.SdkEqual(newLength, _length - 1);
|
||||
|
||||
if (entryIndex < _index)
|
||||
{
|
||||
|
@ -75,7 +75,7 @@ namespace LibHac.Kvdb
|
||||
UnsafeHelpers.SkipParamInit(out count);
|
||||
|
||||
// This should only be called at the start of reading stream.
|
||||
Assert.True(_offset == 0);
|
||||
Assert.SdkRequiresEqual(_offset, 0);
|
||||
|
||||
// Read and validate header.
|
||||
var header = new KeyValueArchiveHeader();
|
||||
@ -95,7 +95,7 @@ namespace LibHac.Kvdb
|
||||
UnsafeHelpers.SkipParamInit(out keySize, out valueSize);
|
||||
|
||||
// This should only be called after ReadEntryCount.
|
||||
Assert.NotEqual(_offset, 0);
|
||||
Assert.SdkNotEqual(_offset, 0);
|
||||
|
||||
// Peek the next entry header.
|
||||
Unsafe.SkipInit(out KeyValueArchiveEntryHeader header);
|
||||
@ -115,7 +115,7 @@ namespace LibHac.Kvdb
|
||||
public Result ReadKeyValue(Span<byte> keyBuffer, Span<byte> valueBuffer)
|
||||
{
|
||||
// This should only be called after ReadEntryCount.
|
||||
Assert.NotEqual(_offset, 0);
|
||||
Assert.SdkNotEqual(_offset, 0);
|
||||
|
||||
// Read the next entry header.
|
||||
Unsafe.SkipInit(out KeyValueArchiveEntryHeader header);
|
||||
@ -127,8 +127,8 @@ namespace LibHac.Kvdb
|
||||
return ResultKvdb.InvalidKeyValue.Log();
|
||||
|
||||
// Key size and Value size must be correct.
|
||||
Assert.Equal(keyBuffer.Length, header.KeySize);
|
||||
Assert.Equal(valueBuffer.Length, header.ValueSize);
|
||||
Assert.SdkEqual(keyBuffer.Length, header.KeySize);
|
||||
Assert.SdkEqual(valueBuffer.Length, header.ValueSize);
|
||||
|
||||
rc = Read(keyBuffer);
|
||||
if (rc.IsFailure()) return rc;
|
||||
@ -176,8 +176,8 @@ namespace LibHac.Kvdb
|
||||
private void Write(ReadOnlySpan<byte> source)
|
||||
{
|
||||
// Bounds check.
|
||||
Assert.True(_offset + source.Length <= _buffer.Length &&
|
||||
_offset + source.Length > _offset);
|
||||
Abort.DoAbortUnless(_offset + source.Length <= _buffer.Length &&
|
||||
_offset + source.Length > _offset);
|
||||
|
||||
source.CopyTo(_buffer.Slice(_offset));
|
||||
_offset += source.Length;
|
||||
@ -186,7 +186,7 @@ namespace LibHac.Kvdb
|
||||
public void WriteHeader(int entryCount)
|
||||
{
|
||||
// This should only be called at start of write.
|
||||
Assert.Equal(_offset, 0);
|
||||
Assert.SdkEqual(_offset, 0);
|
||||
|
||||
var header = new KeyValueArchiveHeader(entryCount);
|
||||
Write(SpanHelpers.AsByteSpan(ref header));
|
||||
@ -195,7 +195,7 @@ namespace LibHac.Kvdb
|
||||
public void WriteEntry(ReadOnlySpan<byte> key, ReadOnlySpan<byte> value)
|
||||
{
|
||||
// This should only be called after writing header.
|
||||
Assert.NotEqual(_offset, 0);
|
||||
Assert.SdkNotEqual(_offset, 0);
|
||||
|
||||
var header = new KeyValueArchiveEntryHeader(key.Length, value.Length);
|
||||
Write(SpanHelpers.AsByteSpan(ref header));
|
||||
|
@ -29,6 +29,10 @@
|
||||
<NoWarn>$(NoWarn);1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<DefineConstants>$(DefineConstants);ENABLE_ASSERTS</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Condition="Exists('ResultNameResolver.Generated.cs')" Remove="ResultNameResolver.Archive.cs" />
|
||||
<Compile Condition="Exists('Common\Keys\DefaultKeySet.Generated.cs')" Remove="Common\Keys\DefaultKeySet.Empty.cs" />
|
||||
|
@ -24,7 +24,7 @@ namespace LibHac.Lr
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void InitEmpty(out Path path)
|
||||
{
|
||||
Unsafe.SkipInit(out path);
|
||||
UnsafeHelpers.SkipParamInit(out path);
|
||||
SpanHelpers.AsByteSpan(ref path)[0] = 0;
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ namespace LibHac.Os.Impl
|
||||
|
||||
public void Signal()
|
||||
{
|
||||
Assert.False(Monitor.IsEntered(_obj));
|
||||
Assert.SdkRequires(!Monitor.IsEntered(_obj));
|
||||
|
||||
Monitor.Enter(_obj);
|
||||
Monitor.Pulse(_obj);
|
||||
@ -21,7 +21,7 @@ namespace LibHac.Os.Impl
|
||||
|
||||
public void Broadcast()
|
||||
{
|
||||
Assert.False(Monitor.IsEntered(_obj));
|
||||
Assert.SdkRequires(!Monitor.IsEntered(_obj));
|
||||
|
||||
Monitor.Enter(_obj);
|
||||
Monitor.PulseAll(_obj);
|
||||
@ -30,7 +30,7 @@ namespace LibHac.Os.Impl
|
||||
|
||||
public void Wait(ref InternalCriticalSection cs)
|
||||
{
|
||||
Assert.False(Monitor.IsEntered(_obj));
|
||||
Assert.SdkRequires(!Monitor.IsEntered(_obj));
|
||||
Abort.DoAbortUnless(cs.IsLockedByCurrentThread());
|
||||
|
||||
// Monitor.Wait doesn't allow specifying a separate mutex object. Workaround this by manually
|
||||
@ -45,7 +45,7 @@ namespace LibHac.Os.Impl
|
||||
|
||||
public ConditionVariableStatus TimedWait(ref InternalCriticalSection cs, in TimeoutHelper timeoutHelper)
|
||||
{
|
||||
Assert.False(Monitor.IsEntered(_obj));
|
||||
Assert.SdkRequires(!Monitor.IsEntered(_obj));
|
||||
Abort.DoAbortUnless(cs.IsLockedByCurrentThread());
|
||||
|
||||
TimeSpan remainingTime = timeoutHelper.GetTimeLeftOnTarget();
|
||||
|
@ -13,7 +13,7 @@ namespace LibHac.Os.Impl
|
||||
// If we already own the lock, no additional action is needed
|
||||
if (rwLock.OwnerThread == Environment.CurrentManagedThreadId)
|
||||
{
|
||||
Assert.True(GetWriteLocked(in GetLockCount(ref rwLock)) == 1);
|
||||
Assert.SdkEqual(GetWriteLocked(in GetLockCount(ref rwLock)), 1u);
|
||||
}
|
||||
// Otherwise we might need to block until we can acquire the read lock
|
||||
else
|
||||
@ -27,8 +27,8 @@ namespace LibHac.Os.Impl
|
||||
DecReadLockWaiterCount(ref GetLockCount(ref rwLock));
|
||||
}
|
||||
|
||||
Assert.True(GetWriteLockCount(in rwLock) == 0);
|
||||
Assert.True(rwLock.OwnerThread == 0);
|
||||
Assert.SdkEqual(GetWriteLockCount(in rwLock), 0u);
|
||||
Assert.SdkEqual(rwLock.OwnerThread, 0);
|
||||
}
|
||||
|
||||
IncReadLockCount(ref GetLockCount(ref rwLock));
|
||||
@ -41,7 +41,7 @@ namespace LibHac.Os.Impl
|
||||
// Acquire the lock if we already have write access
|
||||
if (rwLock.OwnerThread == Environment.CurrentManagedThreadId)
|
||||
{
|
||||
Assert.True(GetWriteLocked(in GetLockCount(ref rwLock)) == 1);
|
||||
Assert.SdkEqual(GetWriteLocked(in GetLockCount(ref rwLock)), 1u);
|
||||
|
||||
IncReadLockCount(ref GetLockCount(ref rwLock));
|
||||
return true;
|
||||
@ -55,8 +55,8 @@ namespace LibHac.Os.Impl
|
||||
}
|
||||
|
||||
// Otherwise acquire the lock
|
||||
Assert.True(GetWriteLockCount(in rwLock) == 0);
|
||||
Assert.True(rwLock.OwnerThread == 0);
|
||||
Assert.SdkEqual(GetWriteLockCount(in rwLock), 0u);
|
||||
Assert.SdkEqual(rwLock.OwnerThread, 0);
|
||||
|
||||
IncReadLockCount(ref GetLockCount(ref rwLock));
|
||||
return true;
|
||||
@ -66,13 +66,13 @@ namespace LibHac.Os.Impl
|
||||
{
|
||||
using ScopedLock<InternalCriticalSection> lk = ScopedLock.Lock(ref GetLockCount(ref rwLock).Cs);
|
||||
|
||||
Assert.True(GetReadLockCount(in GetLockCount(ref rwLock)) > 0);
|
||||
DecReadLockWaiterCount(ref GetLockCount(ref rwLock));
|
||||
Assert.SdkLess(0u, GetReadLockCount(in GetLockCount(ref rwLock)));
|
||||
DecReadLockCount(ref GetLockCount(ref rwLock));
|
||||
|
||||
// If we own the lock, check if we need to release ownership and signal any waiting threads
|
||||
if (rwLock.OwnerThread == Environment.CurrentManagedThreadId)
|
||||
{
|
||||
Assert.True(GetWriteLocked(in GetLockCount(ref rwLock)) == 1);
|
||||
Assert.SdkEqual(GetWriteLocked(in GetLockCount(ref rwLock)), 1u);
|
||||
|
||||
// Return if we still hold any locks
|
||||
if (GetWriteLockCount(in rwLock) != 0 || GetReadLockCount(in GetLockCount(ref rwLock)) != 0)
|
||||
@ -98,9 +98,9 @@ namespace LibHac.Os.Impl
|
||||
// Otherwise we need to signal the next writer if we were the only reader
|
||||
else
|
||||
{
|
||||
Assert.True(GetWriteLockCount(in rwLock) == 0);
|
||||
Assert.True(GetWriteLocked(in GetLockCount(ref rwLock)) == 0);
|
||||
Assert.True(rwLock.OwnerThread == 0);
|
||||
Assert.SdkEqual(GetWriteLockCount(in rwLock), 0u);
|
||||
Assert.SdkEqual(GetWriteLocked(in GetLockCount(ref rwLock)), 0u);
|
||||
Assert.SdkEqual(rwLock.OwnerThread, 0);
|
||||
|
||||
// Signal the next writer if no readers are left
|
||||
if (GetReadLockCount(in GetLockCount(ref rwLock)) == 0 &&
|
||||
@ -121,7 +121,7 @@ namespace LibHac.Os.Impl
|
||||
// Increase the write lock count if we already own the lock
|
||||
if (rwLock.OwnerThread == currentThread)
|
||||
{
|
||||
Assert.True(GetWriteLocked(in GetLockCount(ref rwLock)) == 1);
|
||||
Assert.SdkEqual(GetWriteLocked(in GetLockCount(ref rwLock)), 1u);
|
||||
|
||||
IncWriteLockCount(ref rwLock);
|
||||
return;
|
||||
@ -136,8 +136,8 @@ namespace LibHac.Os.Impl
|
||||
DecWriteLockWaiterCount(ref GetLockCount(ref rwLock));
|
||||
}
|
||||
|
||||
Assert.True(GetWriteLockCount(in rwLock) == 0);
|
||||
Assert.True(rwLock.OwnerThread == 0);
|
||||
Assert.SdkEqual(GetWriteLockCount(in rwLock), 0u);
|
||||
Assert.SdkEqual(rwLock.OwnerThread, 0);
|
||||
|
||||
// Acquire the lock
|
||||
IncWriteLockCount(ref rwLock);
|
||||
@ -154,7 +154,7 @@ namespace LibHac.Os.Impl
|
||||
// Acquire the lock if we already have write access
|
||||
if (rwLock.OwnerThread == currentThread)
|
||||
{
|
||||
Assert.True(GetWriteLocked(in GetLockCount(ref rwLock)) == 1);
|
||||
Assert.SdkEqual(GetWriteLocked(in GetLockCount(ref rwLock)), 1u);
|
||||
|
||||
IncWriteLockCount(ref rwLock);
|
||||
return true;
|
||||
@ -168,8 +168,8 @@ namespace LibHac.Os.Impl
|
||||
}
|
||||
|
||||
// Otherwise acquire the lock
|
||||
Assert.True(GetWriteLockCount(in rwLock) == 0);
|
||||
Assert.True(rwLock.OwnerThread == 0);
|
||||
Assert.SdkEqual(GetWriteLockCount(in rwLock), 0u);
|
||||
Assert.SdkEqual(rwLock.OwnerThread, 0);
|
||||
|
||||
IncWriteLockCount(ref rwLock);
|
||||
SetWriteLocked(ref GetLockCount(ref rwLock));
|
||||
@ -181,9 +181,9 @@ namespace LibHac.Os.Impl
|
||||
{
|
||||
using ScopedLock<InternalCriticalSection> lk = ScopedLock.Lock(ref GetLockCount(ref rwLock).Cs);
|
||||
|
||||
Assert.True(GetWriteLockCount(in rwLock) > 0);
|
||||
Assert.True(GetWriteLocked(in GetLockCount(ref rwLock)) != 0);
|
||||
Assert.True(rwLock.OwnerThread == Environment.CurrentManagedThreadId);
|
||||
Assert.SdkEqual(GetWriteLockCount(in rwLock), 0u);
|
||||
Assert.SdkNotEqual(GetWriteLocked(in GetLockCount(ref rwLock)), 0u);
|
||||
Assert.SdkEqual(rwLock.OwnerThread, Environment.CurrentManagedThreadId);
|
||||
|
||||
DecWriteLockCount(ref rwLock);
|
||||
|
||||
|
@ -67,56 +67,56 @@ namespace LibHac.Os.Impl
|
||||
public static void IncReadLockCount(ref ReaderWriterLockType.LockCountType lc)
|
||||
{
|
||||
uint readLockCount = lc.Counter.ReadLockCount;
|
||||
Assert.True(readLockCount < ReaderWriterLock.ReaderWriterLockCountMax);
|
||||
Assert.SdkLess(readLockCount, (uint)ReaderWriterLock.ReaderWriterLockCountMax);
|
||||
lc.Counter.ReadLockCount = readLockCount + 1;
|
||||
}
|
||||
|
||||
public static void DecReadLockCount(ref ReaderWriterLockType.LockCountType lc)
|
||||
{
|
||||
uint readLockCount = lc.Counter.ReadLockCount;
|
||||
Assert.True(readLockCount > 0);
|
||||
Assert.SdkGreater(readLockCount, 0u);
|
||||
lc.Counter.ReadLockCount = readLockCount - 1;
|
||||
}
|
||||
|
||||
public static void IncReadLockWaiterCount(ref ReaderWriterLockType.LockCountType lc)
|
||||
{
|
||||
uint readLockWaiterCount = lc.Counter.ReadLockWaiterCount;
|
||||
Assert.True(readLockWaiterCount < ReaderWriterLock.ReadWriteLockWaiterCountMax);
|
||||
Assert.SdkLess(readLockWaiterCount, (uint)ReaderWriterLock.ReaderWriterLockCountMax);
|
||||
lc.Counter.ReadLockWaiterCount = readLockWaiterCount + 1;
|
||||
}
|
||||
|
||||
public static void DecReadLockWaiterCount(ref ReaderWriterLockType.LockCountType lc)
|
||||
{
|
||||
uint readLockWaiterCount = lc.Counter.ReadLockWaiterCount;
|
||||
Assert.True(readLockWaiterCount > 0);
|
||||
Assert.SdkGreater(readLockWaiterCount, 0u);
|
||||
lc.Counter.ReadLockWaiterCount = readLockWaiterCount - 1;
|
||||
}
|
||||
|
||||
public static void IncWriteLockWaiterCount(ref ReaderWriterLockType.LockCountType lc)
|
||||
{
|
||||
uint writeLockWaiterCount = lc.Counter.WriteLockWaiterCount;
|
||||
Assert.True(writeLockWaiterCount < ReaderWriterLock.ReadWriteLockWaiterCountMax);
|
||||
Assert.SdkLess(writeLockWaiterCount, (uint)ReaderWriterLock.ReaderWriterLockCountMax);
|
||||
lc.Counter.WriteLockWaiterCount = writeLockWaiterCount + 1;
|
||||
}
|
||||
|
||||
public static void DecWriteLockWaiterCount(ref ReaderWriterLockType.LockCountType lc)
|
||||
{
|
||||
uint writeLockWaiterCount = lc.Counter.WriteLockWaiterCount;
|
||||
Assert.True(writeLockWaiterCount > 0);
|
||||
Assert.SdkGreater(writeLockWaiterCount, 0u);
|
||||
lc.Counter.WriteLockWaiterCount = writeLockWaiterCount - 1;
|
||||
}
|
||||
|
||||
public static void IncWriteLockCount(ref ReaderWriterLockType rwLock)
|
||||
{
|
||||
uint writeLockCount = rwLock.LockCount.WriteLockCount;
|
||||
Assert.True(writeLockCount < ReaderWriterLock.ReaderWriterLockCountMax);
|
||||
Assert.SdkLess(writeLockCount, (uint)ReaderWriterLock.ReaderWriterLockCountMax);
|
||||
rwLock.LockCount.WriteLockCount = writeLockCount + 1;
|
||||
}
|
||||
|
||||
public static void DecWriteLockCount(ref ReaderWriterLockType rwLock)
|
||||
{
|
||||
uint writeLockCount = rwLock.LockCount.WriteLockCount;
|
||||
Assert.True(writeLockCount > 0);
|
||||
Assert.SdkGreater(writeLockCount, 0u);
|
||||
rwLock.LockCount.WriteLockCount = writeLockCount - 1;
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ namespace LibHac.Os.Impl
|
||||
|
||||
// Get the tick frequency.
|
||||
long tickFreq = GetTickFrequency();
|
||||
Assert.True(tickFreq < MaxTickFrequency);
|
||||
Assert.SdkLess(tickFreq, MaxTickFrequency);
|
||||
|
||||
// Clamp tick to range.
|
||||
if (ticks > GetMaxTick())
|
||||
@ -63,7 +63,7 @@ namespace LibHac.Os.Impl
|
||||
TimeSpan ts = TimeSpan.FromSeconds(seconds) +
|
||||
TimeSpan.FromNanoSeconds(frac * nanoSecondsPerSecond / tickFreq);
|
||||
|
||||
Assert.True(!(ticks > 0 && ts < default(TimeSpan) || ticks < 0 && ts > default(TimeSpan)));
|
||||
Assert.SdkAssert(!(ticks > 0 && ts < default(TimeSpan) || ticks < 0 && ts > default(TimeSpan)));
|
||||
|
||||
return ts;
|
||||
}
|
||||
@ -87,7 +87,7 @@ namespace LibHac.Os.Impl
|
||||
{
|
||||
// Get the tick frequency.
|
||||
long tickFreq = GetTickFrequency();
|
||||
Assert.True(tickFreq < MaxTickFrequency);
|
||||
Assert.SdkLess(tickFreq, MaxTickFrequency);
|
||||
|
||||
// Convert to tick.
|
||||
long nanoSecondsPerSecond = TimeSpan.FromSeconds(1).GetNanoSeconds();
|
||||
|
@ -27,11 +27,11 @@ namespace LibHac.Os
|
||||
|
||||
public static void FinalizeReaderWriterLock(this OsState os, ref ReaderWriterLockType rwLock)
|
||||
{
|
||||
Assert.True(rwLock.LockState == ReaderWriterLockType.State.Initialized);
|
||||
Assert.SdkRequires(rwLock.LockState == ReaderWriterLockType.State.Initialized);
|
||||
|
||||
// Don't allow finalizing a locked lock.
|
||||
Assert.True(ReaderWriterLockImpl.GetReadLockCount(in ReaderWriterLockImpl.GetLockCount(ref rwLock)) == 0);
|
||||
Assert.True(ReaderWriterLockImpl.GetWriteLocked(in ReaderWriterLockImpl.GetLockCount(ref rwLock)) == 0);
|
||||
Assert.SdkRequires(ReaderWriterLockImpl.GetReadLockCount(in ReaderWriterLockImpl.GetLockCount(ref rwLock)) == 0);
|
||||
Assert.SdkRequires(ReaderWriterLockImpl.GetWriteLocked(in ReaderWriterLockImpl.GetLockCount(ref rwLock)) == 0);
|
||||
|
||||
// Mark not initialized.
|
||||
rwLock.LockState = ReaderWriterLockType.State.NotInitialized;
|
||||
@ -42,43 +42,43 @@ namespace LibHac.Os
|
||||
|
||||
public static void AcquireReadLock(this OsState os, ref ReaderWriterLockType rwLock)
|
||||
{
|
||||
Assert.True(rwLock.LockState == ReaderWriterLockType.State.Initialized);
|
||||
Assert.SdkRequires(rwLock.LockState == ReaderWriterLockType.State.Initialized);
|
||||
os.Impl.AcquireReadLockImpl(ref rwLock);
|
||||
}
|
||||
|
||||
public static bool TryAcquireReadLock(this OsState os, ref ReaderWriterLockType rwLock)
|
||||
{
|
||||
Assert.True(rwLock.LockState == ReaderWriterLockType.State.Initialized);
|
||||
Assert.SdkRequires(rwLock.LockState == ReaderWriterLockType.State.Initialized);
|
||||
return os.Impl.TryAcquireReadLockImpl(ref rwLock);
|
||||
}
|
||||
|
||||
public static void ReleaseReadLock(this OsState os, ref ReaderWriterLockType rwLock)
|
||||
{
|
||||
Assert.True(rwLock.LockState == ReaderWriterLockType.State.Initialized);
|
||||
Assert.SdkRequires(rwLock.LockState == ReaderWriterLockType.State.Initialized);
|
||||
os.Impl.ReleaseReadLockImpl(ref rwLock);
|
||||
}
|
||||
|
||||
public static void AcquireWriteLock(this OsState os, ref ReaderWriterLockType rwLock)
|
||||
{
|
||||
Assert.True(rwLock.LockState == ReaderWriterLockType.State.Initialized);
|
||||
Assert.SdkRequires(rwLock.LockState == ReaderWriterLockType.State.Initialized);
|
||||
os.Impl.AcquireWriteLockImpl(ref rwLock);
|
||||
}
|
||||
|
||||
public static bool TryAcquireWriteLock(this OsState os, ref ReaderWriterLockType rwLock)
|
||||
{
|
||||
Assert.True(rwLock.LockState == ReaderWriterLockType.State.Initialized);
|
||||
Assert.SdkRequires(rwLock.LockState == ReaderWriterLockType.State.Initialized);
|
||||
return os.Impl.TryAcquireWriteLockImpl(ref rwLock);
|
||||
}
|
||||
|
||||
public static void ReleaseWriteLock(this OsState os, ref ReaderWriterLockType rwLock)
|
||||
{
|
||||
Assert.True(rwLock.LockState == ReaderWriterLockType.State.Initialized);
|
||||
Assert.SdkRequires(rwLock.LockState == ReaderWriterLockType.State.Initialized);
|
||||
os.Impl.ReleaseWriteLockImpl(ref rwLock);
|
||||
}
|
||||
|
||||
public static bool IsReadLockHeld(this OsState os, in ReaderWriterLockType rwLock)
|
||||
{
|
||||
Assert.True(rwLock.LockState == ReaderWriterLockType.State.Initialized);
|
||||
Assert.SdkRequires(rwLock.LockState == ReaderWriterLockType.State.Initialized);
|
||||
return ReaderWriterLockImpl.GetReadLockCount(in ReaderWriterLockImpl.GetLockCountRo(in rwLock)) != 0;
|
||||
|
||||
}
|
||||
@ -86,14 +86,14 @@ namespace LibHac.Os
|
||||
// Todo: Use Horizon thread APIs
|
||||
public static bool IsWriteLockHeldByCurrentThread(this OsState os, in ReaderWriterLockType rwLock)
|
||||
{
|
||||
Assert.True(rwLock.LockState == ReaderWriterLockType.State.Initialized);
|
||||
Assert.SdkRequires(rwLock.LockState == ReaderWriterLockType.State.Initialized);
|
||||
return rwLock.OwnerThread == Environment.CurrentManagedThreadId &&
|
||||
ReaderWriterLockImpl.GetWriteLockCount(in rwLock) != 0;
|
||||
}
|
||||
|
||||
public static bool IsReaderWriterLockOwnerThread(this OsState os, in ReaderWriterLockType rwLock)
|
||||
{
|
||||
Assert.True(rwLock.LockState == ReaderWriterLockType.State.Initialized);
|
||||
Assert.SdkRequires(rwLock.LockState == ReaderWriterLockType.State.Initialized);
|
||||
return rwLock.OwnerThread == Environment.CurrentManagedThreadId;
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ namespace LibHac.Util
|
||||
|
||||
public static ulong AlignUpPow2(ulong value, uint alignment)
|
||||
{
|
||||
Assert.True(BitUtil.IsPowerOfTwo(alignment));
|
||||
Assert.SdkRequires(BitUtil.IsPowerOfTwo(alignment));
|
||||
|
||||
ulong invMask = alignment - 1;
|
||||
return ((value + invMask) & ~invMask);
|
||||
@ -19,7 +19,7 @@ namespace LibHac.Util
|
||||
|
||||
public static ulong AlignDownPow2(ulong value, uint alignment)
|
||||
{
|
||||
Assert.True(BitUtil.IsPowerOfTwo(alignment));
|
||||
Assert.SdkRequires(BitUtil.IsPowerOfTwo(alignment));
|
||||
|
||||
ulong invMask = alignment - 1;
|
||||
return (value & ~invMask);
|
||||
@ -27,7 +27,7 @@ namespace LibHac.Util
|
||||
|
||||
public static bool IsAlignedPow2(ulong value, uint alignment)
|
||||
{
|
||||
Assert.True(BitUtil.IsPowerOfTwo(alignment));
|
||||
Assert.SdkRequires(BitUtil.IsPowerOfTwo(alignment));
|
||||
|
||||
ulong invMask = alignment - 1;
|
||||
return (value & invMask) == 0;
|
||||
|
@ -14,17 +14,17 @@ namespace LibHac.Util
|
||||
{
|
||||
get
|
||||
{
|
||||
Assert.True(_hasValue);
|
||||
// It's beautiful
|
||||
return ref MemoryMarshal.CreateSpan(ref _value, 1)[0];
|
||||
Assert.SdkRequires(_hasValue);
|
||||
// It's beautiful, working around C# rules
|
||||
return ref MemoryMarshal.GetReference(SpanHelpers.CreateSpan(ref _value, 1));
|
||||
}
|
||||
}
|
||||
public readonly ref readonly T ValueRo
|
||||
{
|
||||
get
|
||||
{
|
||||
Assert.True(_hasValue);
|
||||
return ref SpanHelpers.CreateReadOnlySpan(in _value, 1)[0];
|
||||
Assert.SdkRequires(_hasValue);
|
||||
return ref MemoryMarshal.GetReference(SpanHelpers.CreateReadOnlySpan(in _value, 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user