Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -352,67 +352,61 @@ public BigInteger(ReadOnlySpan<byte> value, bool isUnsigned = false, bool isBigE
}
else
{
int unalignedBytes = byteCount % 4;
int dwordCount = byteCount / 4 + (unalignedBytes == 0 ? 0 : 1);
uint[] val = new uint[dwordCount];
int byteCountMinus1 = byteCount - 1;

// Copy all dwords, except don't do the last one if it's not a full four bytes
int curDword, curByte;
int wholeUInt32Count = Math.DivRem(byteCount, 4, out int unalignedBytes);
uint[] val = new uint[wholeUInt32Count + (unalignedBytes == 0 ? 0 : 1)];

// Copy the bytes to the uint array, apart from those which represent the
// most significant uint if it's not a full four bytes.
// The uints are stored in 'least significant first' order.
if (isBigEndian)
{
curByte = byteCount - sizeof(int);
for (curDword = 0; curDword < dwordCount - (unalignedBytes == 0 ? 0 : 1); curDword++)
{
for (int byteInDword = 0; byteInDword < 4; byteInDword++)
{
byte curByteValue = value[curByte];
val[curDword] = (val[curDword] << 8) | curByteValue;
curByte++;
}
// The bytes parameter is in big-endian byte order.
// We need to read the uints out in reverse.

curByte -= 8;
}
Span<byte> uintBytes = MemoryMarshal.AsBytes(val.AsSpan(0, wholeUInt32Count));

// We need to slice off the remainder from the beginning.
value.Slice(unalignedBytes).CopyTo(uintBytes);

uintBytes.Reverse();
}
else
{
curByte = sizeof(int) - 1;
for (curDword = 0; curDword < dwordCount - (unalignedBytes == 0 ? 0 : 1); curDword++)
{
for (int byteInDword = 0; byteInDword < 4; byteInDword++)
{
byte curByteValue = value[curByte];
val[curDword] = (val[curDword] << 8) | curByteValue;
curByte--;
}
// The bytes parameter is in little-endian byte order.
// We can just copy the bytes directly into the uint array.

curByte += 8;
}
value.Slice(0, wholeUInt32Count * 4).CopyTo(MemoryMarshal.AsBytes<uint>(val));
}

// In both of the above cases on big-endian architecture, we need to perform
// an endianness swap on the resulting uints.
if (!BitConverter.IsLittleEndian)
{
BinaryPrimitives.ReverseEndianness(val.AsSpan(0, wholeUInt32Count), val);
}

// Copy the last dword specially if it's not aligned
// Copy the last uint specially if it's not aligned
if (unalignedBytes != 0)
{
if (isNegative)
{
val[dwordCount - 1] = 0xffffffff;
val[wholeUInt32Count] = 0xffffffff;
}

if (isBigEndian)
{
for (curByte = 0; curByte < unalignedBytes; curByte++)
for (int curByte = 0; curByte < unalignedBytes; curByte++)
{
byte curByteValue = value[curByte];
val[curDword] = (val[curDword] << 8) | curByteValue;
val[wholeUInt32Count] = (val[wholeUInt32Count] << 8) | curByteValue;
}
}
else
{
for (curByte = byteCountMinus1; curByte >= byteCount - unalignedBytes; curByte--)
for (int curByte = byteCount - 1; curByte >= byteCount - unalignedBytes; curByte--)
{
byte curByteValue = value[curByte];
val[curDword] = (val[curDword] << 8) | curByteValue;
val[wholeUInt32Count] = (val[wholeUInt32Count] << 8) | curByteValue;
}
}
}
Expand Down