I have a method to convert Span<byte>
to int
:
int ConvertToInt32(Span<byte> buffer)
{
if (buffer.Length != 4)
{
// add zero-padding to the buffer
}
return BitConverter.ToInt32(buffer);
// or MemoryMarshal....
}
If the input parameter (buffer
) length is 4, so the conversion works, but if it has less than 4 bytes it doesn't.
I'm looking for a non-allocating method to do this.
So how can I add zero-padding to the buffer
before conversion, or is there any other solution?
CodePudding user response:
You can allocate on stack with stackalloc
which should be cheaper then allocating on the heap and is usual approach in high-performance scenarios AFAIK:
Span<byte> buffer = stackalloc byte[3] {0,0,1};
if (buffer.Length != 4)
{
Span<byte> interimBuffer = stackalloc byte[4];
// ..
}
Note that you can just convert to type with corresponding size and then cast to int
:
if (buffer.Length == 2)
{
var int16 = (int)BitConverter.ToInt16(buffer);
}
But due to branching it can have worse performance.
Also do not forget about endianness computer's architecture as written in the docs.
CodePudding user response:
You could waste four bytes on a static buffer:
// buffer used for converting fewer than 4 bytes
private static byte convertBuffer[] = new byte[4];
int ConvertToInt32(Span<byte> buffer)
{
if (buffer.Length != 4)
{
// copy the bytes from buffer to convertBuffer
// and then . . .
return BitConverter.ToInt32(buffer);
}
return BitConverter.ToInt32(buffer);
// or MemoryMarshal....
}
The question here will be where to copy the bytes. Do you pad left or pad right? As the documentation says:
The order of bytes in the array must reflect the endianness of the computer system's architecture. For more information, see the Remarks section of BitConverter.
In truth, that 4-byte buffer will likely require more than 4 bytes, what with allocation overhead and such. I'd figure somewhere between 12 and 24 bytes, depending on if you're running on the 32-bit or 64-bit runtime. Still, it prevents having to do a memory allocation every time you use it.
The only other way I can think of is to write a loop that'll do the conversion: basically, re-create the logic of BitConverter.ToInt32()
, but modified to handle fewer than 4 bytes. That's not too tough, but again you need to make allowances for the endianness of the computer. If you're interested in how BitConverter
works, take a look at the source.