I have an array of unsigned char that represents a 128 bit number in network byte order. How would I go about converting this to host byte order efficiently (in this case x86_64)?
There don't seem to be any macros available in endian.h and my attempt at converting the upper 64 bits and lower 64 bits independently didn't work. The only method I've found that definitely works is a loop like so:
unsigned __int128 num = 0;
for (int i = 0; i < 16; i++) {
num = (num << 8) | byte[i];
}
I ended up doing the follow:
union {
unsigned char b[MD5_DIGEST_LENGTH];
uint64_t d[2];
unsigned __int128 q;
} digest;
MD5((const unsigned char *)str, length, digest.b);
uint64_t tmp = digest.d[0];
digest.d[0] = be64toh(digest.d[1]);
digest.d[1] = be64toh(tmp);
/* digest.q is now in native byte order */
If you can easily get the high and low __int64
s, then you can reverse and swap them. Otherwise, you'll probably have to look at every byte individually.
union _128_as_32 {
unsigned __int128 v;
unsigned __int32 d[4];
} u1, u2;
u1.v = num;
u2.d[3] = ntohl(u1.d[0]);
u2.d[2] = ntohl(u1.d[1]);
u2.d[1] = ntohl(u1.d[2]);
u2.d[0] = ntohl(u1.d[3]);
// do something with u2.v
If your environment has betoh64/be64toh (linux/bsd endian.h), you can use
union _128_as_64 {
unsigned __int128 v;
unsigned __int64 q[2];
} u1, u2;
u1.v = num;
u2.q[1] = betoh64(u1.q[0]);
u2.q[0] = betoh64(u1.q[1]);
// do something with u2.v
Seeing as you're likely dealing with IN6 addresses, you should have the ntohl family of functions already available.
H.T.H.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With