如何将 UUID 转换为大端?
How to convert UUID to big endian?
我的 UUID 结构如下:
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];
};
我有一些函数 swap
沿 32 位边界和一个 swap function
沿 16 位边界交换。我试过在 time_low
上调用 swap32()
,在 time_mid
和 time_hi_and_version
上调用 swap16()
。我认为我不需要为其余字段交换字节,因为其中两个是 8 位字段,而且我已经读到 uuid 的节点部分不会改变。 Here is a link for that reference.
问题是当我完成交换时,打印的 uuid 与转换前的 little endian 不匹配。
将遵循 RFC-4122 标准 的 uuid 从 little endian
转换为 big endian
的正确方法是什么?转换后 uuid 应该匹配吗?
您是否尝试过访问单个字节?
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;
可能比调用函数更有效。 :-)
注意:以上方法与平台无关。不需要知道 value
的存储方式。
解释:
设 packet
为需要以 Big Endian 格式(最高有效字节优先)存储到缓冲区中的 uint32_t
的缓冲区或内存目标。
表达式 (value >> 24
) 将最高有效字节移动到最低有效(字节)位置。表达式“& 0xff”截断、砍掉任何无关的值,从而产生一个无符号的 8 位值。然后将该值存储在缓冲区中第一个位置的最高有效位置。
其余字节也是如此。
推荐的方法是使用函数htonl
(htons
for 16 bit integers) to convert from host byte order to network byte order, and ntohl
(ntohs
for 16 bit integers)将网络字节序转换为主机字节序
给定以下结构:
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];
};
序列化和反序列化的代码可能如下:
std::string serialize(UUID_FIELDS fields) {
std::string buffer(sizeof(fields), '[=11=]');
// 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;
}
请注意,您必须同意远程端点中的 receiver/sender,即你们都是 sending/receiving 大端数字。
回复:
Update:
Starting uuid in little endian:
446831D3-FBA1-477B-BB07-CB067B00E86B
Result from correctly swapping necessary fields:
FBA1477B-31D3-4468-6BE8-007B06CB07BB
这看起来非常错误。我们可以推断,如果交换是正确的并且只影响 32 位和 16 位字段,那么在不交换必要字段的情况下,它会是这样的:
Original: 446831D3-FBA1-477B-BB07-CB067B00E86B
| _______/ | _______/
\____ /_______ \____ /______
_____/ \ _____/ \
/ | / |
Received: 7B47A1FB-D331-6844-6BE8-007B06CB07BB # "de-swapped".
您似乎在这里进行的是管道中某处 64 位单元内的字节交换。甚至字节数组也被颠倒了,这表明它可能作为 64 位加载的一部分被加载到某个地方,这受 swap64 操作的影响。
我的 UUID 结构如下:
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];
};
我有一些函数 swap
沿 32 位边界和一个 swap function
沿 16 位边界交换。我试过在 time_low
上调用 swap32()
,在 time_mid
和 time_hi_and_version
上调用 swap16()
。我认为我不需要为其余字段交换字节,因为其中两个是 8 位字段,而且我已经读到 uuid 的节点部分不会改变。 Here is a link for that reference.
问题是当我完成交换时,打印的 uuid 与转换前的 little endian 不匹配。
将遵循 RFC-4122 标准 的 uuid 从 little endian
转换为 big endian
的正确方法是什么?转换后 uuid 应该匹配吗?
您是否尝试过访问单个字节?
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;
可能比调用函数更有效。 :-)
注意:以上方法与平台无关。不需要知道 value
的存储方式。
解释:
设 packet
为需要以 Big Endian 格式(最高有效字节优先)存储到缓冲区中的 uint32_t
的缓冲区或内存目标。
表达式 (value >> 24
) 将最高有效字节移动到最低有效(字节)位置。表达式“& 0xff”截断、砍掉任何无关的值,从而产生一个无符号的 8 位值。然后将该值存储在缓冲区中第一个位置的最高有效位置。
其余字节也是如此。
推荐的方法是使用函数htonl
(htons
for 16 bit integers) to convert from host byte order to network byte order, and ntohl
(ntohs
for 16 bit integers)将网络字节序转换为主机字节序
给定以下结构:
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];
};
序列化和反序列化的代码可能如下:
std::string serialize(UUID_FIELDS fields) {
std::string buffer(sizeof(fields), '[=11=]');
// 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;
}
请注意,您必须同意远程端点中的 receiver/sender,即你们都是 sending/receiving 大端数字。
回复:
Update: Starting uuid in little endian:
446831D3-FBA1-477B-BB07-CB067B00E86B
Result from correctly swapping necessary fields:
FBA1477B-31D3-4468-6BE8-007B06CB07BB
这看起来非常错误。我们可以推断,如果交换是正确的并且只影响 32 位和 16 位字段,那么在不交换必要字段的情况下,它会是这样的:
Original: 446831D3-FBA1-477B-BB07-CB067B00E86B
| _______/ | _______/
\____ /_______ \____ /______
_____/ \ _____/ \
/ | / |
Received: 7B47A1FB-D331-6844-6BE8-007B06CB07BB # "de-swapped".
您似乎在这里进行的是管道中某处 64 位单元内的字节交换。甚至字节数组也被颠倒了,这表明它可能作为 64 位加载的一部分被加载到某个地方,这受 swap64 操作的影响。