Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert UUID to big endian?

My UUID is structured like this:

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 along 32 bit boundaries and a swap function that swaps along 16 bit boundaries. I have tried calling swap32() on time_low and swap16() on time_mid and time_hi_and_version. I do not believe I need to swap bytes for the rest of the fields because two of them are 8 bit fields and I have read that the node part of a uuid does not change. Here is a link for that reference.

The problem is when I complete the swaps the uuid that is printed does not match the one that was in little endian before being converted.

What is the correct way to convert a uuid following RFC-4122 standard from little endian to big endian. And when converted should the uuids match?

like image 496
sebenalern Avatar asked Jun 08 '16 19:06

sebenalern


2 Answers

Re:

Update: Starting uuid in little endian:

446831D3-FBA1-477B-BB07-CB067B00E86B

Result from correctly swapping necessary fields:

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

This looks horribly wrong. We can deduce that if the swaps are correct and affect only the 32 and 16 bit fields, then without swapping the necessary fields, it would be this:

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

What you seem to have have going on here is byte swapping within 64 bit units somewhere in your pipeline. Even the array of bytes is being reversed, suggesting that it might be loaded somewhere as part of a 64 bit load, which is subject to a swap64 operation.

like image 167
Kaz Avatar answered Sep 17 '22 15:09

Kaz


Have you tried accessing the 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. Doesn't require any knowledge how the value is stored.

Explanation:
Let packet be a buffer or memory destination for a uint32_t that needs to be stored into the buffer in Big Endian format (Most Significant Byte First).

The expression (value >> 24) shifts the most significant byte to the least significant (byte) position. The expression "& 0xff" truncates, chops off, any extraneous values, resulting in an unsigned 8-bit value. The value is then stored in the Most Significant position in the buffer at the first location.

Likewise for the remaining bytes.

like image 31
Thomas Matthews Avatar answered Sep 18 '22 15:09

Thomas Matthews