How to convert UUID to large endian?

My UUID is structured as follows:

struct UUID_FIELDS { uint32_t time_low; uint16_t time_mid; uint16_t time_hi_and_version; uint8_t clock_seq_hi_and_reserved; uint8_t clock_seq_low; uint8_t node[6]; }; 

I have functions that swap at 32-bit boundaries and swap function that change at 16-bit boundaries. I tried calling swap32() on time_low and swap16() on time_mid and time_hi_and_version . I don’t think I need to change the bytes for the rest of the fields, because two of them are 8-bit fields, and I read that the wuid part does not matter. Here is the link for this link.

The problem is when I fill out the swaps, the printed uuid does not match the one that was in the end before the conversion.

What is the correct way to convert uuid after RFC-4122 from little endian to big endian . And when should the converted ones coincide with uuids?

+7
c ++ uuid endianness
source share
3 answers

Re:

Update: Running uuid in little endian:

 446831D3-FBA1-477B-BB07-CB067B00E86B 

The result of the correct replacement of the required fields:

 FBA1477B-31D3-4468-6BE8-007B06CB07BB 

It looks terribly wrong. We can conclude that if the swaps are correct and affect only 32 and 16 bit fields, then without replacing the necessary fields, this will be as follows:

 Original: 446831D3-FBA1-477B-BB07-CB067B00E86B | _______/ | _______/ \____ /_______ \____ /______ _____/ \ _____/ \ / | / | Received: 7B47A1FB-D331-6844-6BE8-007B06CB07BB # "de-swapped". 

What you seem to be already here is a byte exchange in 64-bit units somewhere in your pipeline. Even the byte array is reversed, suggesting that it can be loaded somewhere as part of the 64-bit load, which is subject to swap64 operation.

+4
source share

Have you tried to access individual bytes?

 uint8_t packet[4]; uint32_t value; packet[0] = (value >> 24) & 0xFF; packet[1] = (value >> 16) & 0xFF; packet[2] = (value >> 8) & 0xFF; packet[3] = value & 0xFF; 

Probably more efficient than calling a function. :-)

Note: the above method is platform independent. It does not require knowledge of how value is stored.

Explanation:
Let packet be the buffer or memory location for uint32_t , which must be saved in the buffer in Big Endian format (the most significant byte).

The expression ( value >> 24 ) shifts the most significant byte to the least significant (byte) position. The expression "& 0xff" truncates, discards, any extraneous values, which leads to an 8-bit unsigned value. Then the value is stored in the most significant position in the buffer in the first place.

Similarly for the remaining bytes.

+3
source share

The recommended way is to use the htonl ( htons for 16-bit integers) function to convert byte order from the host byte to the network and ntohl ( ntohs for 16-bit integers) to convert from the network byte to the host byte order

Given the following structure:

 struct UUID_FIELDS { uint32_t time_low; uint16_t time_mid; uint16_t time_hi_and_version; uint8_t clock_seq_hi_and_reserved; uint8_t clock_seq_low; uint8_t node[6]; }; 

The code for serialization and deserialization can be as follows:

 std::string serialize(UUID_FIELDS fields) { std::string buffer(sizeof(fields), '\0'); // convert all fields with size > 1 byte to big endian (network byte order) fields.time_low = htonl(fields.time_low); fields.time_mid = htons(fields.time_mid); fields.time_hi_and_version = htons(fields.time_hi_and_version); memcpy(&buffer[0], &fields, sizeof(fields)); return buffer; } UUID_FIELDS deserialize(const std::string& buffer) { UUID_FIELDS fields; assert(buffer.size() == sizeof(fields)); memcpy(&fields, &buffer[0], sizeof(fields)); // convert all fields with size > 1 byte to little endian (maybe) (host byte order) fields.time_low = ntohl(fields.time_low); fields.time_mid = ntohs(fields.time_mid); fields.time_hi_and_version = ntohs(fields.time_hi_and_version); return fields; } 

Note that you must agree with the receiver / sender at the remote endpoint that you both send / receive numbers at the big end.

0
source share

All Articles