mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Use generic math in Util.Alignment
This commit is contained in:
parent
7fce26e899
commit
df77de365c
23 changed files with 232 additions and 133 deletions
|
@ -242,11 +242,11 @@ internal static class AssertImpl
|
|||
|
||||
public static bool IsAligned(long value, int alignment)
|
||||
{
|
||||
return Alignment.IsAlignedPow2(value, (uint)alignment);
|
||||
return Alignment.IsAligned(value, (uint)alignment);
|
||||
}
|
||||
|
||||
public static bool IsAligned(ulong value, int alignment)
|
||||
{
|
||||
return Alignment.IsAlignedPow2(value, (uint)alignment);
|
||||
return Alignment.IsAligned(value, (uint)alignment);
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ public static class ApplicationSaveDataManagement
|
|||
|
||||
private static long RoundUpOccupationSize(long size)
|
||||
{
|
||||
return Alignment.AlignUpPow2(size, SaveDataBlockSize);
|
||||
return Alignment.AlignUp(size, SaveDataBlockSize);
|
||||
}
|
||||
|
||||
private static long CalculateSaveDataExtensionContextFileSize(long saveDataSize, long saveDataJournalSize)
|
||||
|
@ -48,10 +48,10 @@ public static class ApplicationSaveDataManagement
|
|||
if (availableSize < saveDataSize || journalSize < saveDataJournalSize)
|
||||
{
|
||||
// Make sure the new sizes are valid
|
||||
if (availableSize < saveDataSize && !Alignment.IsAlignedPow2(saveDataSize, SaveDataExtensionSizeAlignment))
|
||||
if (availableSize < saveDataSize && !Alignment.IsAligned(saveDataSize, SaveDataExtensionSizeAlignment))
|
||||
return ResultFs.ExtensionSizeInvalid.Log();
|
||||
|
||||
if (journalSize < saveDataJournalSize && !Alignment.IsAlignedPow2(saveDataJournalSize, SaveDataExtensionSizeAlignment))
|
||||
if (journalSize < saveDataJournalSize && !Alignment.IsAligned(saveDataJournalSize, SaveDataExtensionSizeAlignment))
|
||||
return ResultFs.ExtensionSizeInvalid.Log();
|
||||
|
||||
long newSaveDataSize = Math.Max(saveDataSize, availableSize);
|
||||
|
|
|
@ -171,7 +171,7 @@ public ref struct Path
|
|||
if (_buffer is not null && _buffer.Length > length)
|
||||
return Result.Success;
|
||||
|
||||
int alignedLength = Alignment.AlignUpPow2(length, WriteBufferAlignmentLength);
|
||||
int alignedLength = Alignment.AlignUp(length, WriteBufferAlignmentLength);
|
||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(alignedLength);
|
||||
|
||||
byte[] oldBuffer = _buffer;
|
||||
|
@ -321,7 +321,7 @@ public ref struct Path
|
|||
{
|
||||
Assert.SdkRequiresNotNull(buffer);
|
||||
Assert.SdkRequires(length > 0);
|
||||
Assert.SdkRequires(Alignment.IsAlignedPow2(length, WriteBufferAlignmentLength));
|
||||
Assert.SdkRequires(Alignment.IsAligned(length, WriteBufferAlignmentLength));
|
||||
|
||||
byte[] oldBuffer = _writeBuffer;
|
||||
_writeBuffer = buffer;
|
||||
|
@ -359,7 +359,7 @@ public ref struct Path
|
|||
if (_writeBufferLength > length)
|
||||
return Result.Success;
|
||||
|
||||
int alignedLength = Alignment.AlignUpPow2(length, WriteBufferAlignmentLength);
|
||||
int alignedLength = Alignment.AlignUp(length, WriteBufferAlignmentLength);
|
||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(alignedLength);
|
||||
SetModifiableBuffer(buffer, alignedLength);
|
||||
|
||||
|
@ -1134,7 +1134,7 @@ public ref struct Path
|
|||
if (flags.IsWindowsPathAllowed() && WindowsPath.IsWindowsPath(_string, true))
|
||||
bufferLength += 1;
|
||||
|
||||
int alignedBufferLength = Alignment.AlignUpPow2(bufferLength, WriteBufferAlignmentLength);
|
||||
int alignedBufferLength = Alignment.AlignUp(bufferLength, WriteBufferAlignmentLength);
|
||||
|
||||
byte[] rentedArray = null;
|
||||
try
|
||||
|
|
|
@ -39,8 +39,8 @@ public readonly struct FileRegion
|
|||
|
||||
public FileRegion ExpandAndAlign(uint alignment)
|
||||
{
|
||||
long alignedStartOffset = Alignment.AlignDownPow2(Offset, alignment);
|
||||
long alignedEndOffset = Alignment.AlignUpPow2(GetEndOffset(), alignment);
|
||||
long alignedStartOffset = Alignment.AlignDown(Offset, alignment);
|
||||
long alignedEndOffset = Alignment.AlignUp(GetEndOffset(), alignment);
|
||||
long alignedSize = alignedEndOffset - alignedStartOffset;
|
||||
|
||||
return new FileRegion(alignedStartOffset, alignedSize);
|
||||
|
@ -48,8 +48,8 @@ public readonly struct FileRegion
|
|||
|
||||
public FileRegion ShrinkAndAlign(uint alignment)
|
||||
{
|
||||
long alignedStartOffset = Alignment.AlignUpPow2(Offset, alignment);
|
||||
long alignedEndOffset = Alignment.AlignDownPow2(GetEndOffset(), alignment);
|
||||
long alignedStartOffset = Alignment.AlignUp(Offset, alignment);
|
||||
long alignedEndOffset = Alignment.AlignDown(GetEndOffset(), alignment);
|
||||
long alignedSize = alignedEndOffset - alignedStartOffset;
|
||||
|
||||
return new FileRegion(alignedStartOffset, alignedSize);
|
||||
|
|
|
@ -120,10 +120,10 @@ public static class SaveData
|
|||
public static Result EnsureSaveDataImpl(this FileSystemClientImpl fs, UserId userId, long saveDataSize,
|
||||
long saveDataJournalSize, bool extendIfNeeded)
|
||||
{
|
||||
if (!Alignment.IsAlignedPow2(saveDataSize, SaveDataBlockSize))
|
||||
if (!Alignment.IsAligned(saveDataSize, SaveDataBlockSize))
|
||||
return ResultFs.InvalidSize.Log();
|
||||
|
||||
if (!Alignment.IsAlignedPow2(saveDataJournalSize, SaveDataBlockSize))
|
||||
if (!Alignment.IsAligned(saveDataJournalSize, SaveDataBlockSize))
|
||||
return ResultFs.InvalidSize.Log();
|
||||
|
||||
if (saveDataSize + saveDataJournalSize > SaveDataTotalSizeMax)
|
||||
|
|
|
@ -146,7 +146,7 @@ public class AccessControl
|
|||
accessControlData.Slice(data.SaveDataOwnerInfoOffset + sizeof(int), infoCount));
|
||||
|
||||
// The ID list must be 4-byte aligned
|
||||
int idsOffset = Alignment.AlignUpPow2(data.SaveDataOwnerInfoOffset + sizeof(int) + infoCount, 4);
|
||||
int idsOffset = Alignment.AlignUp(data.SaveDataOwnerInfoOffset + sizeof(int) + infoCount, 4);
|
||||
ReadOnlySpan<ulong> ids = MemoryMarshal.Cast<byte, ulong>(
|
||||
accessControlData.Slice(idsOffset, infoCount * sizeof(ulong)));
|
||||
|
||||
|
|
|
@ -358,7 +358,7 @@ public class DeviceOperator : IDeviceOperator
|
|||
|
||||
// Changed: Removed the alignment check for the buffer address
|
||||
|
||||
if (!Alignment.IsAlignedPow2(bufferSize, 0x1000))
|
||||
if (!Alignment.IsAligned(bufferSize, 0x1000))
|
||||
return ResultFs.InvalidAlignment.Log();
|
||||
|
||||
return _fsServer.Storage.WriteToGameCardDirectly(offset, GetSpan(buffer, bufferSize)).Ret();
|
||||
|
|
|
@ -217,10 +217,10 @@ public class AesCtrCounterExtendedStorage : IStorage
|
|||
return Result.Success;
|
||||
|
||||
// Reads cannot contain any partial blocks.
|
||||
if (!Alignment.IsAlignedPow2(offset, (uint)BlockSize))
|
||||
if (!Alignment.IsAligned(offset, (uint)BlockSize))
|
||||
return ResultFs.InvalidOffset.Log();
|
||||
|
||||
if (!Alignment.IsAlignedPow2(destination.Length, (uint)BlockSize))
|
||||
if (!Alignment.IsAligned(destination.Length, (uint)BlockSize))
|
||||
return ResultFs.InvalidSize.Log();
|
||||
|
||||
// Ensure the the requested range is within the bounds of the table.
|
||||
|
@ -244,7 +244,7 @@ public class AesCtrCounterExtendedStorage : IStorage
|
|||
|
||||
// Verify that the entry's offset is aligned to an AES block and within the bounds of the table.
|
||||
long entryOffset = visitor.Get<Entry>().GetOffset();
|
||||
if (!Alignment.IsAlignedPow2(entryOffset, (uint)BlockSize) || entryOffset < 0 ||
|
||||
if (!Alignment.IsAligned(entryOffset, (uint)BlockSize) || entryOffset < 0 ||
|
||||
!offsets.IsInclude(entryOffset))
|
||||
{
|
||||
return ResultFs.InvalidAesCtrCounterExtendedEntryOffset.Log();
|
||||
|
@ -283,7 +283,7 @@ public class AesCtrCounterExtendedStorage : IStorage
|
|||
entryEndOffset = offsets.EndOffset;
|
||||
}
|
||||
|
||||
if (!Alignment.IsAlignedPow2((ulong)entryEndOffset, (uint)BlockSize) || currentOffset >= entryEndOffset)
|
||||
if (!Alignment.IsAligned((ulong)entryEndOffset, (uint)BlockSize) || currentOffset >= entryEndOffset)
|
||||
return ResultFs.InvalidAesCtrCounterExtendedEntryOffset.Log();
|
||||
|
||||
// Get the part of the entry that contains the data we read.
|
||||
|
@ -383,10 +383,10 @@ public class AesCtrCounterExtendedStorage : IStorage
|
|||
return Result.Success;
|
||||
}
|
||||
|
||||
if (!Alignment.IsAlignedPow2(offset, (uint)BlockSize))
|
||||
if (!Alignment.IsAligned(offset, (uint)BlockSize))
|
||||
return ResultFs.InvalidOffset.Log();
|
||||
|
||||
if (!Alignment.IsAlignedPow2(size, (uint)BlockSize))
|
||||
if (!Alignment.IsAligned(size, (uint)BlockSize))
|
||||
return ResultFs.InvalidSize.Log();
|
||||
|
||||
// Ensure the storage contains the provided offset and size.
|
||||
|
|
|
@ -76,10 +76,10 @@ public class AesCtrStorage : IStorage
|
|||
return Result.Success;
|
||||
|
||||
// Reads cannot contain any partial blocks.
|
||||
if (!Alignment.IsAlignedPow2(offset, (uint)BlockSize))
|
||||
if (!Alignment.IsAligned(offset, (uint)BlockSize))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
if (!Alignment.IsAlignedPow2(destination.Length, (uint)BlockSize))
|
||||
if (!Alignment.IsAligned(destination.Length, (uint)BlockSize))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
Result res = _baseStorage.Read(offset, destination);
|
||||
|
@ -103,10 +103,10 @@ public class AesCtrStorage : IStorage
|
|||
return Result.Success;
|
||||
|
||||
// We can only write full, aligned blocks.
|
||||
if (!Alignment.IsAlignedPow2(offset, (uint)BlockSize))
|
||||
if (!Alignment.IsAligned(offset, (uint)BlockSize))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
if (!Alignment.IsAlignedPow2(source.Length, (uint)BlockSize))
|
||||
if (!Alignment.IsAligned(source.Length, (uint)BlockSize))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
// Get a pooled buffer.
|
||||
|
@ -192,10 +192,10 @@ public class AesCtrStorage : IStorage
|
|||
return Result.Success;
|
||||
}
|
||||
|
||||
if (!Alignment.IsAlignedPow2(offset, (uint)BlockSize))
|
||||
if (!Alignment.IsAligned(offset, (uint)BlockSize))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
if (!Alignment.IsAlignedPow2(size, (uint)BlockSize))
|
||||
if (!Alignment.IsAligned(size, (uint)BlockSize))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
|
||||
|
|
|
@ -78,10 +78,10 @@ public class AesXtsStorageExternal : IStorage
|
|||
return ResultFs.NullptrArgument.Log();
|
||||
|
||||
// We can only read at block aligned offsets.
|
||||
if (!Alignment.IsAlignedPow2(offset, AesBlockSize))
|
||||
if (!Alignment.IsAligned(offset, AesBlockSize))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
if (!Alignment.IsAlignedPow2(destination.Length, AesBlockSize))
|
||||
if (!Alignment.IsAligned(destination.Length, AesBlockSize))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
// Read the encrypted data.
|
||||
|
@ -102,7 +102,7 @@ public class AesXtsStorageExternal : IStorage
|
|||
if (offset % _blockSize != 0)
|
||||
{
|
||||
// Determine the size of the pre-data read.
|
||||
int skipSize = (int)(offset - Alignment.AlignDownPow2(offset, _blockSize));
|
||||
int skipSize = (int)(offset - Alignment.AlignDown(offset, _blockSize));
|
||||
int dataSize = (int)Math.Min(destination.Length, _blockSize - skipSize);
|
||||
|
||||
// Decrypt into a pooled buffer.
|
||||
|
@ -159,10 +159,10 @@ public class AesXtsStorageExternal : IStorage
|
|||
return ResultFs.NullptrArgument.Log();
|
||||
|
||||
// We can only write at block aligned offsets.
|
||||
if (!Alignment.IsAlignedPow2(offset, AesBlockSize))
|
||||
if (!Alignment.IsAligned(offset, AesBlockSize))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
if (!Alignment.IsAlignedPow2(source.Length, AesBlockSize))
|
||||
if (!Alignment.IsAligned(source.Length, AesBlockSize))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
// Get a pooled buffer.
|
||||
|
@ -186,7 +186,7 @@ public class AesXtsStorageExternal : IStorage
|
|||
if (offset % _blockSize != 0)
|
||||
{
|
||||
// Determine the size of the pre-data write.
|
||||
int skipSize = (int)(offset - Alignment.AlignDownPow2(offset, _blockSize));
|
||||
int skipSize = (int)(offset - Alignment.AlignDown(offset, _blockSize));
|
||||
int dataSize = (int)Math.Min(source.Length, _blockSize - skipSize);
|
||||
|
||||
// Encrypt into a pooled buffer.
|
||||
|
@ -289,10 +289,10 @@ public class AesXtsStorageExternal : IStorage
|
|||
return Result.Success;
|
||||
|
||||
// Ensure alignment.
|
||||
if (!Alignment.IsAlignedPow2(offset, AesBlockSize))
|
||||
if (!Alignment.IsAligned(offset, AesBlockSize))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
if (!Alignment.IsAlignedPow2(size, AesBlockSize))
|
||||
if (!Alignment.IsAligned(size, AesBlockSize))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ public class AlignmentMatchingStorage<TDataAlignment, TBufferAlignment> : IStora
|
|||
|
||||
public override Result SetSize(long size)
|
||||
{
|
||||
Result res = _baseStorage.SetSize(Alignment.AlignUpPow2(size, DataAlign));
|
||||
Result res = _baseStorage.SetSize(Alignment.AlignUp(size, DataAlign));
|
||||
_isBaseStorageSizeDirty = true;
|
||||
|
||||
return res;
|
||||
|
@ -150,8 +150,8 @@ public class AlignmentMatchingStorage<TDataAlignment, TBufferAlignment> : IStora
|
|||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
long validSize = Math.Min(size, baseStorageSize - offset);
|
||||
long alignedOffset = Alignment.AlignDownPow2(offset, DataAlign);
|
||||
long alignedOffsetEnd = Alignment.AlignUpPow2(offset + validSize, DataAlign);
|
||||
long alignedOffset = Alignment.AlignDown(offset, DataAlign);
|
||||
long alignedOffsetEnd = Alignment.AlignUp(offset + validSize, DataAlign);
|
||||
long alignedSize = alignedOffsetEnd - alignedOffset;
|
||||
|
||||
return _baseStorage.OperateRange(outBuffer, operationId, alignedOffset, alignedSize, inBuffer);
|
||||
|
@ -255,7 +255,7 @@ public class AlignmentMatchingStoragePooledBuffer<TBufferAlignment> : IStorage
|
|||
|
||||
public override Result SetSize(long size)
|
||||
{
|
||||
Result res = _baseStorage.SetSize(Alignment.AlignUpPow2(size, _dataAlignment));
|
||||
Result res = _baseStorage.SetSize(Alignment.AlignUp(size, _dataAlignment));
|
||||
_isBaseStorageSizeDirty = true;
|
||||
|
||||
return res;
|
||||
|
@ -296,8 +296,8 @@ public class AlignmentMatchingStoragePooledBuffer<TBufferAlignment> : IStorage
|
|||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
long validSize = Math.Min(size, baseStorageSize - offset);
|
||||
long alignedOffset = Alignment.AlignDownPow2(offset, _dataAlignment);
|
||||
long alignedOffsetEnd = Alignment.AlignUpPow2(offset + validSize, _dataAlignment);
|
||||
long alignedOffset = Alignment.AlignDown(offset, _dataAlignment);
|
||||
long alignedOffsetEnd = Alignment.AlignUp(offset + validSize, _dataAlignment);
|
||||
long alignedSize = alignedOffsetEnd - alignedOffset;
|
||||
|
||||
return _baseStorage.OperateRange(outBuffer, operationId, alignedOffset, alignedSize, inBuffer);
|
||||
|
@ -367,8 +367,8 @@ public class AlignmentMatchingStorageInBulkRead<TBufferAlignment> : IStorage
|
|||
|
||||
// Calculate the aligned offsets of the requested region.
|
||||
long offsetEnd = offset + destination.Length;
|
||||
long alignedOffset = Alignment.AlignDownPow2(offset, _dataAlignment);
|
||||
long alignedOffsetEnd = Alignment.AlignUpPow2(offsetEnd, _dataAlignment);
|
||||
long alignedOffset = Alignment.AlignDown(offset, _dataAlignment);
|
||||
long alignedOffsetEnd = Alignment.AlignUp(offsetEnd, _dataAlignment);
|
||||
long alignedSize = alignedOffsetEnd - alignedOffset;
|
||||
|
||||
using var pooledBuffer = new PooledBuffer();
|
||||
|
@ -406,8 +406,8 @@ public class AlignmentMatchingStorageInBulkRead<TBufferAlignment> : IStorage
|
|||
}
|
||||
|
||||
// Determine read extents for the aligned portion.
|
||||
long coreOffset = Alignment.AlignUpPow2(offset, _dataAlignment);
|
||||
long coreOffsetEnd = Alignment.AlignDownPow2(offsetEnd, _dataAlignment);
|
||||
long coreOffset = Alignment.AlignUp(offset, _dataAlignment);
|
||||
long coreOffsetEnd = Alignment.AlignDown(offsetEnd, _dataAlignment);
|
||||
|
||||
// Handle any data before the aligned portion.
|
||||
if (offset < coreOffset)
|
||||
|
@ -469,7 +469,7 @@ public class AlignmentMatchingStorageInBulkRead<TBufferAlignment> : IStorage
|
|||
|
||||
public override Result SetSize(long size)
|
||||
{
|
||||
Result res = _baseStorage.SetSize(Alignment.AlignUpPow2(size, _dataAlignment));
|
||||
Result res = _baseStorage.SetSize(Alignment.AlignUp(size, _dataAlignment));
|
||||
_baseStorageSize = -1;
|
||||
|
||||
return res;
|
||||
|
@ -509,8 +509,8 @@ public class AlignmentMatchingStorageInBulkRead<TBufferAlignment> : IStorage
|
|||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
long validSize = Math.Min(size, baseStorageSize - offset);
|
||||
long alignedOffset = Alignment.AlignDownPow2(offset, _dataAlignment);
|
||||
long alignedOffsetEnd = Alignment.AlignUpPow2(offset + validSize, _dataAlignment);
|
||||
long alignedOffset = Alignment.AlignDown(offset, _dataAlignment);
|
||||
long alignedOffsetEnd = Alignment.AlignUp(offset + validSize, _dataAlignment);
|
||||
long alignedSize = alignedOffsetEnd - alignedOffset;
|
||||
|
||||
return _baseStorage.OperateRange(outBuffer, operationId, alignedOffset, alignedSize, inBuffer);
|
||||
|
|
|
@ -15,22 +15,22 @@ public static class AlignmentMatchingStorageImpl
|
|||
{
|
||||
public static uint GetRoundDownDifference(int value, uint alignment)
|
||||
{
|
||||
return (uint)(value - Alignment.AlignDownPow2(value, alignment));
|
||||
return (uint)(value - Alignment.AlignDown(value, alignment));
|
||||
}
|
||||
|
||||
public static uint GetRoundDownDifference(long value, uint alignment)
|
||||
{
|
||||
return (uint)(value - Alignment.AlignDownPow2(value, alignment));
|
||||
return (uint)(value - Alignment.AlignDown(value, alignment));
|
||||
}
|
||||
|
||||
public static uint GetRoundUpDifference(int value, uint alignment)
|
||||
{
|
||||
return (uint)(Alignment.AlignUpPow2(value, alignment) - value);
|
||||
return (uint)(Alignment.AlignUp(value, alignment) - value);
|
||||
}
|
||||
|
||||
private static uint GetRoundUpDifference(long value, uint alignment)
|
||||
{
|
||||
return (uint)(Alignment.AlignUpPow2(value, alignment) - value);
|
||||
return (uint)(Alignment.AlignUp(value, alignment) - value);
|
||||
}
|
||||
|
||||
public static Result Read(in SharedRef<IStorage> storage, Span<byte> workBuffer, uint dataAlignment,
|
||||
|
@ -60,10 +60,10 @@ public static class AlignmentMatchingStorageImpl
|
|||
// Calculate the range that contains only full data blocks.
|
||||
uint offsetRoundUpDifference = GetRoundUpDifference(offset, dataAlignment);
|
||||
|
||||
long coreOffset = Alignment.AlignUpPow2(offset, dataAlignment);
|
||||
long coreOffset = Alignment.AlignUp(offset, dataAlignment);
|
||||
long coreSize = destination.Length < offsetRoundUpDifference
|
||||
? 0
|
||||
: Alignment.AlignDownPow2(destination.Length - offsetRoundUpDifference, dataAlignment);
|
||||
: Alignment.AlignDown(destination.Length - offsetRoundUpDifference, dataAlignment);
|
||||
|
||||
long coveredOffset = coreSize > 0 ? coreOffset : offset;
|
||||
|
||||
|
@ -77,7 +77,7 @@ public static class AlignmentMatchingStorageImpl
|
|||
// Read any partial block at the head of the requested range
|
||||
if (offset < coveredOffset)
|
||||
{
|
||||
long headOffset = Alignment.AlignDownPow2(offset, dataAlignment);
|
||||
long headOffset = Alignment.AlignDown(offset, dataAlignment);
|
||||
int headSize = (int)(coveredOffset - offset);
|
||||
|
||||
Assert.SdkAssert(GetRoundDownDifference(offset, dataAlignment) + headSize <= workBuffer.Length);
|
||||
|
@ -94,7 +94,7 @@ public static class AlignmentMatchingStorageImpl
|
|||
// Read any partial block at the tail of the requested range
|
||||
while (remainingTailSize > 0)
|
||||
{
|
||||
long alignedTailOffset = Alignment.AlignDownPow2(tailOffset, dataAlignment);
|
||||
long alignedTailOffset = Alignment.AlignDown(tailOffset, dataAlignment);
|
||||
long copySize = Math.Min(alignedTailOffset + dataAlignment - tailOffset, remainingTailSize);
|
||||
|
||||
Result res = storage.Read(alignedTailOffset, workBuffer.Slice(0, (int)dataAlignment));
|
||||
|
@ -127,10 +127,10 @@ public static class AlignmentMatchingStorageImpl
|
|||
// Calculate the range that contains only full data blocks.
|
||||
uint offsetRoundUpDifference = GetRoundUpDifference(offset, dataAlignment);
|
||||
|
||||
long coreOffset = Alignment.AlignUpPow2(offset, dataAlignment);
|
||||
long coreOffset = Alignment.AlignUp(offset, dataAlignment);
|
||||
long coreSize = source.Length < offsetRoundUpDifference
|
||||
? 0
|
||||
: Alignment.AlignDownPow2(source.Length - offsetRoundUpDifference, dataAlignment);
|
||||
: Alignment.AlignDown(source.Length - offsetRoundUpDifference, dataAlignment);
|
||||
|
||||
long coveredOffset = coreSize > 0 ? coreOffset : offset;
|
||||
|
||||
|
@ -144,7 +144,7 @@ public static class AlignmentMatchingStorageImpl
|
|||
// Write any partial block at the head of the specified range
|
||||
if (offset < coveredOffset)
|
||||
{
|
||||
long headOffset = Alignment.AlignDownPow2(offset, dataAlignment);
|
||||
long headOffset = Alignment.AlignDown(offset, dataAlignment);
|
||||
int headSize = (int)(coveredOffset - offset);
|
||||
|
||||
Assert.SdkAssert((offset - headOffset) + headSize <= workBuffer.Length);
|
||||
|
@ -168,7 +168,7 @@ public static class AlignmentMatchingStorageImpl
|
|||
{
|
||||
Assert.SdkAssert(tailOffset - offset < source.Length);
|
||||
|
||||
long alignedTailOffset = Alignment.AlignDownPow2(tailOffset, dataAlignment);
|
||||
long alignedTailOffset = Alignment.AlignDown(tailOffset, dataAlignment);
|
||||
long copySize = Math.Min(alignedTailOffset + dataAlignment - tailOffset, remainingTailSize);
|
||||
|
||||
// Read the existing block, copy the partial block to the appropriate portion,
|
||||
|
|
|
@ -77,13 +77,13 @@ public class DefaultAsynchronousAccessSplitter : IAsynchronousAccessSplitter
|
|||
|
||||
public Result QueryAppropriateOffset(out long offsetAppropriate, long startOffset, long accessSize, long alignmentSize)
|
||||
{
|
||||
offsetAppropriate = Alignment.AlignDownPow2(startOffset + accessSize, alignmentSize);
|
||||
offsetAppropriate = Alignment.AlignDown(startOffset + accessSize, alignmentSize);
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result QueryInvocationCount(out long count, long startOffset, long endOffset, long accessSize, long alignmentSize)
|
||||
{
|
||||
long alignedStartOffset = Alignment.AlignDownPow2(startOffset, alignmentSize);
|
||||
long alignedStartOffset = Alignment.AlignDown(startOffset, alignmentSize);
|
||||
count = BitUtil.DivideUp(endOffset - alignedStartOffset, accessSize);
|
||||
return Result.Success;
|
||||
}
|
||||
|
|
|
@ -554,7 +554,7 @@ public class BufferedStorage : IStorage
|
|||
private readonly void CalcFetchParameter(out FetchParameter fetchParam, long offset)
|
||||
{
|
||||
long blockSize = _bufferedStorage._blockSize;
|
||||
long storageOffset = Alignment.AlignDownPow2(offset, (uint)_bufferedStorage._blockSize);
|
||||
long storageOffset = Alignment.AlignDown(offset, (uint)_bufferedStorage._blockSize);
|
||||
long baseSize = _bufferedStorage._baseStorageSize;
|
||||
long remainingSize = baseSize - storageOffset;
|
||||
long cacheSize = Math.Min(blockSize, remainingSize);
|
||||
|
@ -1107,7 +1107,7 @@ public class BufferedStorage : IStorage
|
|||
if (prevSize < size)
|
||||
{
|
||||
// Prepare to expand.
|
||||
if (!Alignment.IsAlignedPow2(prevSize, (uint)_blockSize))
|
||||
if (!Alignment.IsAligned(prevSize, (uint)_blockSize))
|
||||
{
|
||||
using var cache = new SharedCache(this);
|
||||
long invalidateOffset = prevSize;
|
||||
|
@ -1130,7 +1130,7 @@ public class BufferedStorage : IStorage
|
|||
using var cache = new SharedCache(this);
|
||||
long invalidateOffset = prevSize;
|
||||
long invalidateSize = size - prevSize;
|
||||
bool isFragment = Alignment.IsAlignedPow2(size, (uint)_blockSize);
|
||||
bool isFragment = Alignment.IsAligned(size, (uint)_blockSize);
|
||||
|
||||
while (cache.AcquireNextOverlappedCache(invalidateOffset, invalidateSize))
|
||||
{
|
||||
|
@ -1317,7 +1317,7 @@ public class BufferedStorage : IStorage
|
|||
int currentSize;
|
||||
|
||||
// If the offset is in the middle of a block, read the remaining part of that block.
|
||||
if (!Alignment.IsAlignedPow2(currentOffset, (uint)_blockSize))
|
||||
if (!Alignment.IsAligned(currentOffset, (uint)_blockSize))
|
||||
{
|
||||
long alignedSize = _blockSize - (currentOffset & (_blockSize - 1));
|
||||
currentSize = (int)Math.Min(alignedSize, remainingSize);
|
||||
|
@ -1330,7 +1330,7 @@ public class BufferedStorage : IStorage
|
|||
// We have at least one full block to read. Read all the remaining full blocks at once.
|
||||
else
|
||||
{
|
||||
currentSize = (int)Alignment.AlignDownPow2(remainingSize, (uint)_blockSize);
|
||||
currentSize = (int)Alignment.AlignDown(remainingSize, (uint)_blockSize);
|
||||
}
|
||||
|
||||
Span<byte> currentDestination = destination.Slice((int)bufferOffset, currentSize);
|
||||
|
@ -1421,15 +1421,15 @@ public class BufferedStorage : IStorage
|
|||
/// Otherwise, <see langword="false"/>.</returns>
|
||||
private bool ReadHeadCache(ref long offset, Span<byte> buffer, ref long size, ref long bufferOffset)
|
||||
{
|
||||
bool isCacheNeeded = !Alignment.IsAlignedPow2(offset, (uint)_blockSize);
|
||||
bool isCacheNeeded = !Alignment.IsAligned(offset, (uint)_blockSize);
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
long currentSize;
|
||||
|
||||
if (!Alignment.IsAlignedPow2(offset, (uint)_blockSize))
|
||||
if (!Alignment.IsAligned(offset, (uint)_blockSize))
|
||||
{
|
||||
long alignedSize = Alignment.AlignUpPow2(offset, (uint)_blockSize) - offset;
|
||||
long alignedSize = Alignment.AlignUp(offset, (uint)_blockSize) - offset;
|
||||
currentSize = Math.Min(alignedSize, size);
|
||||
}
|
||||
else if (size < _blockSize)
|
||||
|
@ -1458,16 +1458,16 @@ public class BufferedStorage : IStorage
|
|||
|
||||
private bool ReadTailCache(long offset, Span<byte> buffer, ref long size, long bufferOffset)
|
||||
{
|
||||
bool isCacheNeeded = !Alignment.IsAlignedPow2(offset + size, (uint)_blockSize);
|
||||
bool isCacheNeeded = !Alignment.IsAligned(offset + size, (uint)_blockSize);
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
long currentOffsetEnd = offset + size;
|
||||
long currentSize;
|
||||
|
||||
if (!Alignment.IsAlignedPow2(currentOffsetEnd, (uint)_blockSize))
|
||||
if (!Alignment.IsAligned(currentOffsetEnd, (uint)_blockSize))
|
||||
{
|
||||
long alignedSize = currentOffsetEnd - Alignment.AlignDownPow2(currentOffsetEnd, (uint)_blockSize);
|
||||
long alignedSize = currentOffsetEnd - Alignment.AlignDown(currentOffsetEnd, (uint)_blockSize);
|
||||
currentSize = Math.Min(alignedSize, size);
|
||||
}
|
||||
else if (size < _blockSize)
|
||||
|
@ -1511,8 +1511,8 @@ public class BufferedStorage : IStorage
|
|||
Result res;
|
||||
|
||||
// Determine aligned extents.
|
||||
long alignedOffset = Alignment.AlignDownPow2(offset, (uint)_blockSize);
|
||||
long alignedOffsetEnd = Math.Min(Alignment.AlignUpPow2(offset + buffer.Length, (uint)_blockSize),
|
||||
long alignedOffset = Alignment.AlignDown(offset, (uint)_blockSize);
|
||||
long alignedOffsetEnd = Math.Min(Alignment.AlignUp(offset + buffer.Length, (uint)_blockSize),
|
||||
_baseStorageSize);
|
||||
long alignedSize = alignedOffsetEnd - alignedOffset;
|
||||
|
||||
|
@ -1606,7 +1606,7 @@ public class BufferedStorage : IStorage
|
|||
|
||||
if (upgradeResult.wasUpgradeSuccessful)
|
||||
{
|
||||
long tailCacheOffset = Alignment.AlignDownPow2(offset + buffer.Length, (uint)_blockSize);
|
||||
long tailCacheOffset = Alignment.AlignDown(offset + buffer.Length, (uint)_blockSize);
|
||||
long tailCacheSize = alignedSize - tailCacheOffset + alignedOffset;
|
||||
|
||||
res = fetchCache.FetchFromBuffer(tailCacheOffset,
|
||||
|
@ -1649,7 +1649,7 @@ public class BufferedStorage : IStorage
|
|||
ReadOnlySpan<byte> currentSource = source.Slice(bufferOffset);
|
||||
int currentSize;
|
||||
|
||||
if (!Alignment.IsAlignedPow2(currentOffset, (uint)_blockSize))
|
||||
if (!Alignment.IsAligned(currentOffset, (uint)_blockSize))
|
||||
{
|
||||
int alignedSize = (int)(_blockSize - (currentOffset & (_blockSize - 1)));
|
||||
currentSize = Math.Min(alignedSize, remainingSize);
|
||||
|
@ -1660,7 +1660,7 @@ public class BufferedStorage : IStorage
|
|||
}
|
||||
else
|
||||
{
|
||||
currentSize = Alignment.AlignDownPow2(remainingSize, (uint)_blockSize);
|
||||
currentSize = Alignment.AlignDown(remainingSize, (uint)_blockSize);
|
||||
}
|
||||
|
||||
Result res;
|
||||
|
|
|
@ -175,7 +175,7 @@ public unsafe class FileSystemBuddyHeap : IDisposable
|
|||
uint pageListAlignment = (uint)Unsafe.SizeOf<nint>();
|
||||
const uint ulongAlignment = 8;
|
||||
|
||||
return (nuint)Alignment.AlignUpPow2(pageListSize * (orderMax + 1) + pageListAlignment, ulongAlignment);
|
||||
return (nuint)Alignment.AlignUp(pageListSize * (orderMax + 1) + pageListAlignment, ulongAlignment);
|
||||
}
|
||||
|
||||
public static int QueryOrderMax(nuint size, nuint blockSize)
|
||||
|
@ -184,7 +184,7 @@ public unsafe class FileSystemBuddyHeap : IDisposable
|
|||
Assert.SdkRequiresGreaterEqual(blockSize, BlockSizeMin);
|
||||
Assert.SdkRequires(BitUtil.IsPowerOfTwo(blockSize));
|
||||
|
||||
int blockCount = (int)(Alignment.AlignUpPow2(size, (uint)blockSize) / blockSize);
|
||||
int blockCount = (int)(Alignment.AlignUp(size, (uint)blockSize) / blockSize);
|
||||
for (int order = 1; ; order++)
|
||||
{
|
||||
if (blockCount <= GetBlockCountFromOrder(order))
|
||||
|
@ -203,7 +203,7 @@ public unsafe class FileSystemBuddyHeap : IDisposable
|
|||
Assert.SdkRequiresGreaterEqual(workBufferSize, QueryWorkBufferSize(orderMax));
|
||||
|
||||
uint pageListAlignment = (uint)Unsafe.SizeOf<nint>();
|
||||
var alignedWork = (void*)Alignment.AlignUpPow2((ulong)workBuffer, pageListAlignment);
|
||||
var alignedWork = (void*)Alignment.AlignUp((ulong)workBuffer, pageListAlignment);
|
||||
ExternalFreeLists = (PageList*)alignedWork;
|
||||
|
||||
// Note: The original code does not have a buffer size assert after adjusting for alignment.
|
||||
|
@ -531,7 +531,7 @@ public unsafe class FileSystemBuddyHeap : IDisposable
|
|||
private int GetBlockCountFromSize(nuint size)
|
||||
{
|
||||
nuint blockSize = GetBlockSize();
|
||||
return (int)(Alignment.AlignUpPow2(size, (uint)blockSize) / blockSize);
|
||||
return (int)(Alignment.AlignUp(size, (uint)blockSize) / blockSize);
|
||||
}
|
||||
|
||||
private UIntPtr GetAddressFromPageEntry(PageEntry* pageEntry)
|
||||
|
@ -551,7 +551,7 @@ public unsafe class FileSystemBuddyHeap : IDisposable
|
|||
Assert.SdkRequiresLess((nuint)address, HeapStart + HeapSize);
|
||||
|
||||
ulong blockStart = (ulong)HeapStart +
|
||||
Alignment.AlignDownPow2((nuint)address - HeapStart, (uint)GetBlockSize());
|
||||
Alignment.AlignDown((nuint)address - HeapStart, (uint)GetBlockSize());
|
||||
return (PageEntry*)blockStart;
|
||||
}
|
||||
|
||||
|
@ -568,7 +568,7 @@ public unsafe class FileSystemBuddyHeap : IDisposable
|
|||
|
||||
private bool IsAlignedToOrder(PageEntry* pageEntry, int order)
|
||||
{
|
||||
return Alignment.IsAlignedPow2(GetIndexFromPageEntry(pageEntry), (uint)GetBlockCountFromOrder(order));
|
||||
return Alignment.IsAligned(GetIndexFromPageEntry(pageEntry), (uint)GetBlockCountFromOrder(order));
|
||||
}
|
||||
|
||||
// Addition: The below fields and methods allow using Memory<byte> with the class instead
|
||||
|
|
|
@ -98,7 +98,7 @@ public class FileSystemBufferManager : IBufferManager
|
|||
|
||||
int entrySize = Unsafe.SizeOf<Entry>() * maxCacheCount;
|
||||
int attrListSize = Unsafe.SizeOf<AttrInfo>() * 0x100;
|
||||
return (int)Alignment.AlignUpPow2(
|
||||
return (int)Alignment.AlignUp(
|
||||
(ulong)(entrySize + attrListSize + entryAlignment + attrInfoAlignment), 8);
|
||||
}
|
||||
|
||||
|
|
|
@ -137,14 +137,14 @@ public class HierarchicalIntegrityVerificationStorageControlArea : IDisposable
|
|||
Span<long> levelSize = stackalloc long[IntegrityMaxLayerCount];
|
||||
int level = layerCount - 1;
|
||||
|
||||
levelSize[level] = Alignment.AlignUpPow2(dataSize, (uint)inputParam.LevelBlockSizes[level - 1]);
|
||||
levelSize[level] = Alignment.AlignUp(dataSize, (uint)inputParam.LevelBlockSizes[level - 1]);
|
||||
level--;
|
||||
|
||||
for (; level > 0; level--)
|
||||
{
|
||||
// Calculate how much space is needed to store the hashes of the above level, rounding up to the next block size.
|
||||
levelSize[level] =
|
||||
Alignment.AlignUpPow2(levelSize[level + 1] / inputParam.LevelBlockSizes[level] * HashSize,
|
||||
Alignment.AlignUp(levelSize[level + 1] / inputParam.LevelBlockSizes[level] * HashSize,
|
||||
(uint)inputParam.LevelBlockSizes[level - 1]);
|
||||
}
|
||||
|
||||
|
|
|
@ -170,7 +170,7 @@ public class IntegrityVerificationStorage : IStorage
|
|||
if (dataSize < offset)
|
||||
return ResultFs.InvalidOffset.Log();
|
||||
|
||||
long alignedDataSize = Alignment.AlignUpPow2(dataSize, (uint)_verificationBlockSize);
|
||||
long alignedDataSize = Alignment.AlignUp(dataSize, (uint)_verificationBlockSize);
|
||||
res = CheckAccessRange(offset, destination.Length, alignedDataSize);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
|
@ -268,7 +268,7 @@ public class IntegrityVerificationStorage : IStorage
|
|||
if (offset >= dataSize)
|
||||
return ResultFs.InvalidOffset.Log();
|
||||
|
||||
res = CheckAccessRange(offset, source.Length, Alignment.AlignUpPow2(dataSize, (uint)_verificationBlockSize));
|
||||
res = CheckAccessRange(offset, source.Length, Alignment.AlignUp(dataSize, (uint)_verificationBlockSize));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
Assert.SdkRequiresAligned(offset, _verificationBlockSize);
|
||||
|
@ -292,7 +292,7 @@ public class IntegrityVerificationStorage : IStorage
|
|||
return Result.Success;
|
||||
}
|
||||
|
||||
int alignedWriteSize = Alignment.AlignUpPow2(writeSize, (uint)_verificationBlockSize);
|
||||
int alignedWriteSize = Alignment.AlignUp(writeSize, (uint)_verificationBlockSize);
|
||||
|
||||
Result updateResult = Result.Success;
|
||||
int updatedSignatureCount = 0;
|
||||
|
|
|
@ -168,7 +168,7 @@ public class UnionStorage : IStorage
|
|||
|
||||
// Get the start offset of the block containing the requested offset
|
||||
long offsetBuffer = 0;
|
||||
long offsetOriginal = Alignment.AlignDownPow2(offset, _blockSize);
|
||||
long offsetOriginal = Alignment.AlignDown(offset, _blockSize);
|
||||
long sizeSkipBlock = offset - offsetOriginal;
|
||||
|
||||
while (offsetBuffer < destination.Length)
|
||||
|
@ -214,7 +214,7 @@ public class UnionStorage : IStorage
|
|||
|
||||
// Get the start offset of the block containing the requested offset
|
||||
long offsetBuffer = 0;
|
||||
long offsetOriginal = Alignment.AlignDownPow2(offset, _blockSize);
|
||||
long offsetOriginal = Alignment.AlignDown(offset, _blockSize);
|
||||
long sizeSkipBlock = offset - offsetOriginal;
|
||||
|
||||
while (offsetBuffer < source.Length)
|
||||
|
@ -302,7 +302,7 @@ public class UnionStorage : IStorage
|
|||
public override Result OperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
for (long currentOffset = Alignment.AlignDownPow2(offset, _blockSize);
|
||||
for (long currentOffset = Alignment.AlignDown(offset, _blockSize);
|
||||
currentOffset < offset + size;
|
||||
currentOffset += _blockSize)
|
||||
{
|
||||
|
|
|
@ -126,7 +126,7 @@ public class PartitionFileSystemBuilder
|
|||
size += entry.NameLength + 1;
|
||||
}
|
||||
|
||||
int endOffset = Alignment.AlignUpPow2(startOffset + size, GetMetaDataAlignment(type));
|
||||
int endOffset = Alignment.AlignUp(startOffset + size, GetMetaDataAlignment(type));
|
||||
return endOffset - startOffset;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using LibHac.Diag;
|
||||
|
@ -7,58 +8,53 @@ namespace LibHac.Util;
|
|||
|
||||
public static class Alignment
|
||||
{
|
||||
// The alignment functions in this class come from C++ templates that always cast to unsigned types
|
||||
|
||||
public static ulong AlignUpPow2(ulong value, uint alignment)
|
||||
public static T AlignUp<T>(T value, ulong alignment) where T : IBinaryNumber<T>
|
||||
{
|
||||
Assert.SdkRequires(BitUtil.IsPowerOfTwo(alignment));
|
||||
Assert.SdkRequires(BitUtil.IsPowerOfTwo(alignment) || alignment == 0);
|
||||
|
||||
unchecked
|
||||
{
|
||||
ulong invMask = alignment - 1;
|
||||
return ((value + invMask) & ~invMask);
|
||||
return T.CreateTruncating((ulong.CreateTruncating(value) + invMask) & ~invMask);
|
||||
}
|
||||
}
|
||||
|
||||
public static ulong AlignDownPow2(ulong value, uint alignment)
|
||||
public static T AlignDown<T>(T value, ulong alignment) where T : IBinaryNumber<T>
|
||||
{
|
||||
Assert.SdkRequires(BitUtil.IsPowerOfTwo(alignment));
|
||||
Assert.SdkRequires(BitUtil.IsPowerOfTwo(alignment) || alignment == 0);
|
||||
|
||||
unchecked
|
||||
{
|
||||
ulong invMask = alignment - 1;
|
||||
return (value & ~invMask);
|
||||
return T.CreateTruncating(ulong.CreateTruncating(value) & ~invMask);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsAlignedPow2(ulong value, uint alignment)
|
||||
{
|
||||
Assert.SdkRequires(BitUtil.IsPowerOfTwo(alignment));
|
||||
public static T AlignDown<T>(T value, long alignment) where T : IBinaryNumber<T> => AlignDown(value, (ulong)alignment);
|
||||
|
||||
public static bool IsAligned<T>(T value, ulong alignment) where T : IBinaryNumber<T>
|
||||
{
|
||||
Assert.SdkRequires(BitUtil.IsPowerOfTwo(alignment) || alignment == 0);
|
||||
|
||||
unchecked
|
||||
{
|
||||
ulong invMask = alignment - 1;
|
||||
return (value & invMask) == 0;
|
||||
return (ulong.CreateTruncating(value) & invMask) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsAlignedPow2<T>(ReadOnlySpan<T> buffer, uint alignment)
|
||||
public static bool IsAligned<T>(ReadOnlySpan<T> buffer, ulong alignment)
|
||||
{
|
||||
return IsAlignedPow2(ref MemoryMarshal.GetReference(buffer), alignment);
|
||||
return IsAligned(ref MemoryMarshal.GetReference(buffer), alignment);
|
||||
}
|
||||
|
||||
public static unsafe bool IsAlignedPow2<T>(ref T pointer, uint alignment)
|
||||
public static unsafe bool IsAligned<T>(ref T pointer, ulong alignment)
|
||||
{
|
||||
return IsAlignedPow2((ulong)Unsafe.AsPointer(ref pointer), alignment);
|
||||
return IsAligned((ulong)Unsafe.AsPointer(ref pointer), alignment);
|
||||
}
|
||||
|
||||
public static int AlignUpPow2(int value, uint alignment) => (int)AlignUpPow2((ulong)value, alignment);
|
||||
public static long AlignUpPow2(long value, uint alignment) => (long)AlignUpPow2((ulong)value, alignment);
|
||||
public static int AlignDownPow2(int value, uint alignment) => (int)AlignDownPow2((ulong)value, alignment);
|
||||
public static long AlignDownPow2(long value, uint alignment) => (long)AlignDownPow2((ulong)value, alignment);
|
||||
public static long AlignDownPow2(long value, long alignment) => (long)AlignDownPow2((ulong)value, (uint)alignment);
|
||||
public static bool IsAlignedPow2(int value, uint alignment) => IsAlignedPow2((ulong)value, alignment);
|
||||
public static bool IsAlignedPow2(long value, uint alignment) => IsAlignedPow2((ulong)value, alignment);
|
||||
|
||||
public static ulong AlignUp(ulong value, uint alignment) => AlignDown(value + alignment - 1, alignment);
|
||||
public static ulong AlignDown(ulong value, uint alignment) => value - value % alignment;
|
||||
public static bool IsAligned(ulong value, uint alignment) => value % alignment == 0;
|
||||
|
||||
public static int AlignUp(int value, uint alignment) => (int)AlignUp((ulong)value, alignment);
|
||||
public static long AlignUp(long value, uint alignment) => (long)AlignUp((ulong)value, alignment);
|
||||
public static int AlignDown(int value, uint alignment) => (int)AlignDown((ulong)value, alignment);
|
||||
public static long AlignDown(long value, uint alignment) => (long)AlignDown((ulong)value, alignment);
|
||||
public static bool IsAligned(int value, uint alignment) => IsAligned((ulong)value, alignment);
|
||||
public static bool IsAligned(long value, uint alignment) => IsAligned((ulong)value, alignment);
|
||||
public static T GetAlignment<T>(T value) where T : IUnsignedNumber<T>, IBinaryInteger<T>
|
||||
{
|
||||
return unchecked(value & -value);
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
|
102
tests/LibHac.Tests/Util/AlignmentTests.cs
Normal file
102
tests/LibHac.Tests/Util/AlignmentTests.cs
Normal file
|
@ -0,0 +1,102 @@
|
|||
using LibHac.Util;
|
||||
using Xunit;
|
||||
|
||||
namespace LibHac.Tests.Util
|
||||
{
|
||||
public class AlignmentTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(0, 0x40, 0)]
|
||||
[InlineData(0x3F, 0x40, 0x40)]
|
||||
[InlineData(0x40, 0x40, 0x40)]
|
||||
[InlineData(0x41, 0x40, 0x80)]
|
||||
public void AlignUp_Byte(byte value, uint alignment, byte expectedValue)
|
||||
{
|
||||
var actualValue = Alignment.AlignUp(value, alignment);
|
||||
Assert.Equal(expectedValue, actualValue);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0, 0x40, 0)]
|
||||
[InlineData(-0x3F, 0x40, 0)]
|
||||
[InlineData(-0x40, 0x40, -0x40)]
|
||||
[InlineData(-0x41, 0x40, -0x40)]
|
||||
[InlineData(-0x41, 0, 0)]
|
||||
[InlineData(int.MaxValue, 0x40, int.MinValue)]
|
||||
public void AlignUp_Int(int value, uint alignment, int expectedValue)
|
||||
{
|
||||
var actualValue = Alignment.AlignUp(value, alignment);
|
||||
Assert.Equal(expectedValue, actualValue);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0, 0x40, 0)]
|
||||
[InlineData(0x3F, 0x40, 0x40)]
|
||||
[InlineData(0x40, 0x40, 0x40)]
|
||||
[InlineData(0x41, 0x40, 0x80)]
|
||||
[InlineData(0xFFF_FFFF_8000, 0x10000, 0x1000_0000_0000)]
|
||||
public void AlignUp_Ulong(ulong value, uint alignment, ulong expectedValue)
|
||||
{
|
||||
var actualValue = Alignment.AlignUp(value, alignment);
|
||||
Assert.Equal(expectedValue, actualValue);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0, 0x40, 0)]
|
||||
[InlineData(0x3F, 0x40, 0)]
|
||||
[InlineData(0x40, 0x40, 0x40)]
|
||||
[InlineData(0x41, 0x40, 0x40)]
|
||||
public void AlignDown_Byte(byte value, uint alignment, byte expectedValue)
|
||||
{
|
||||
var actualValue = Alignment.AlignDown(value, alignment);
|
||||
Assert.Equal(expectedValue, actualValue);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0, 0x40, 0)]
|
||||
[InlineData(0x3F, 0x40, 0)]
|
||||
[InlineData(0x40, 0x40, 0x40)]
|
||||
[InlineData(0x41, 0x40, 0x40)]
|
||||
public void AlignDown_Long(long value, uint alignment, long expectedValue)
|
||||
{
|
||||
var actualValue = Alignment.AlignDown(value, alignment);
|
||||
Assert.Equal(expectedValue, actualValue);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0, 0x40, true)]
|
||||
[InlineData(0x3F, 0x40, false)]
|
||||
[InlineData(0x40, 0x40, true)]
|
||||
[InlineData(0x41, 0x40, false)]
|
||||
public void IsAligned_Byte(byte value, uint alignment, bool expectedValue)
|
||||
{
|
||||
var actualValue = Alignment.IsAligned(value, alignment);
|
||||
Assert.Equal(expectedValue, actualValue);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0, 0x40, true)]
|
||||
[InlineData(0x3F, 0x40, false)]
|
||||
[InlineData(0x40, 0x40, true)]
|
||||
[InlineData(0x41, 0x40, false)]
|
||||
[InlineData(0xFFF_FFFF_8000, 0x400, true)]
|
||||
public void IsAligned_Long(long value, uint alignment, bool expectedValue)
|
||||
{
|
||||
var actualValue = Alignment.IsAligned(value, alignment);
|
||||
Assert.Equal(expectedValue, actualValue);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0, 0)]
|
||||
[InlineData(0x3F, 1)]
|
||||
[InlineData(0x40, 0x40)]
|
||||
[InlineData(0x41, 1)]
|
||||
[InlineData(0x42, 2)]
|
||||
[InlineData(0xFF900000, 0x100000)]
|
||||
public void GetAlignment_Uint(uint value, long expectedValue)
|
||||
{
|
||||
var actualValue = Alignment.GetAlignment(value);
|
||||
Assert.Equal(expectedValue, actualValue);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue