Converting a ubyte[] to a struct with respect to endianness?
Ali Çehreli via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Fri Jun 23 23:06:56 PDT 2017
On 06/23/2017 10:18 PM, H. S. Teoh via Digitalmars-d-learn wrote:
> On Fri, Jun 23, 2017 at 10:10:22PM -0700, Ali Çehreli via Digitalmars-d-learn wrote:
>> On 06/23/2017 09:26 PM, Felix wrote:
>>> That works, thanks!
>>
>> I've just tried this, which seems cleaner:
>>
>> import std.stdio;
>> import std.system;
>> import std.bitmanip;
>>
>> void ensureBigEndian(T)(ref T value) {
>> if (endian == Endian.littleEndian) {
>> value = *cast(T*)nativeToBigEndian(value).ptr;
>> }
>
> This is wrong, you should be detecting the endianness of the input and
> use {big,little}EndianToNative instead. For example, if the input is
> big endian, you should use bigEndianToNative. Internally, if native is
> already big endian, it will do nothing; otherwise it will swap the
> endianness. This way you don't have to check the current machine's
> endianness yourself; you can just recompile on a machine of different
> endianness and it will Just Work.
>
>
> T
>
Thanks. Something like this:
import std.stdio;
import std.system;
import std.bitmanip;
void ensureCorrectFromBigEndian(T)(ref T value) {
value = bigEndianToNative!(T, T.sizeof)(*cast(ubyte[T.sizeof]*)&value);
}
struct S {
uint u;
}
void main() {
// Bytes on the wire
ubyte[] bytes = [ 0, 0, 0, 13 ];
// Overlaying an object on those bytes
S s = *cast(S*)bytes.ptr;
void checkValue(uint expectedOnLE, uint expectedOnBE) {
if (endian == Endian.littleEndian) {
assert(s.u == expectedOnLE);
} else if (endian == Endian.bigEndian) {
assert(s.u == expectedOnBE);
} else {
assert(false, "What is this?");
}
}
// The value should be wrong no a little-endian system
checkValue(218103808, 13);
s.u.ensureCorrectFromBigEndian;
// No matter what, now the result will be correct on any system
checkValue(13, 13);
}
Ali
More information about the Digitalmars-d-learn
mailing list