diff options
| author | Clifford Allan Jansen <cliffjansen@apache.org> | 2013-05-02 18:18:00 +0000 |
|---|---|---|
| committer | Clifford Allan Jansen <cliffjansen@apache.org> | 2013-05-02 18:18:00 +0000 |
| commit | cac08af3dc5cf09bc5c19eb55c7785bfc4db4f74 (patch) | |
| tree | 791c987e6a4771ead25cf2f23e9af725448b5407 /qpid/cpp/src | |
| parent | 72c99c7f4621ddda3d2b02cabc9ab12d36d7dd66 (diff) | |
| download | qpid-python-cac08af3dc5cf09bc5c19eb55c7785bfc4db4f74.tar.gz | |
QPID-4792: convert between UUIDs and GUIDs as needed for Microsoft APIs
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1478471 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/cpp/src')
| -rw-r--r-- | qpid/cpp/src/qpid/sys/windows/uuid.cpp | 96 |
1 files changed, 83 insertions, 13 deletions
diff --git a/qpid/cpp/src/qpid/sys/windows/uuid.cpp b/qpid/cpp/src/qpid/sys/windows/uuid.cpp index 3316ecbc00..d4f57fcab6 100644 --- a/qpid/cpp/src/qpid/sys/windows/uuid.cpp +++ b/qpid/cpp/src/qpid/sys/windows/uuid.cpp @@ -19,6 +19,14 @@ * */ +/* + * UUIDs and GUIDs (both RFC 4122) differ on byte positions of the + * internal representation. This matters when encoding to the wire + * and adhering to versioning info. Microsoft APIs used here operate + * on GUIDs even if the name implies UUIDs. AMQP expects the UUID 128 + * bit format which is used here unless otherwise noted. + */ + #include <rpc.h> #ifdef uuid_t /* Done in rpcdce.h */ # undef uuid_t @@ -28,7 +36,37 @@ #include <string.h> +namespace { +inline void iswap (char *p1, char *p2) { + char t = *p1; + *p1 = *p2; + *p2 = t; +} + +void toUuid (const UUID *guid, uuid_t uuid) { + // copy then swap bytes + memcpy ((char *) uuid, (char *) guid, qpid::sys::UuidSize); + char *p = (char *) uuid; + iswap (p, p+3); + iswap (p+1, p+2); + iswap (p+4, p+5); + iswap (p+6, p+7); +} + +void printHex (const unsigned char *bytes, char *buf, int n) { + static char hexrep[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f'}; + for (;n ; n--) { + unsigned char b = *bytes++; + *buf++ = hexrep[b >> 4]; + *buf++ = hexrep[b & 0xf]; + } +} +} // namespace + + void uuid_clear (uuid_t uu) { + // all zeros, no change between GUID and UUID UuidCreateNil (reinterpret_cast<UUID*>(uu)); } @@ -37,7 +75,10 @@ void uuid_copy (uuid_t dst, const uuid_t src) { } void uuid_generate (uuid_t out) { - UuidCreate (reinterpret_cast<UUID*>(out)); + UUID guid; + UuidCreate (&guid); + // Version 4 GUID, convert to UUID + toUuid (&guid, out); } int uuid_is_null (const uuid_t uu) { @@ -46,22 +87,51 @@ int uuid_is_null (const uuid_t uu) { } int uuid_parse (const char *in, uuid_t uu) { - return UuidFromString ((unsigned char*)in, (UUID*)uu) == RPC_S_OK ? 0 : -1; + UUID guid; + if (UuidFromString ((unsigned char*)in, &guid) != RPC_S_OK) + return -1; + toUuid (&guid, uu); + return 0; } void uuid_unparse (const uuid_t uu, char *out) { - unsigned char *formatted; - if (UuidToString((UUID*)uu, &formatted) == RPC_S_OK) { -#ifdef _MSC_VER - strncpy_s (out, 36+1, (char*)formatted, _TRUNCATE); -#else - strncpy (out, (char*)formatted, 36+1); -#endif - RpcStringFree(&formatted); - } + const uint8_t *in = uu; + out[8] = out[13] = out[18] = out[23] = '-'; + printHex (in, out, 4); + printHex (in+4, out+9, 2); + printHex (in+6, out+14, 2); + printHex (in+8, out+19, 2); + printHex (in+10, out+24, 6); + out[36] = '\0'; +} + +namespace { + +typedef struct { + 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]; +} rfc_uuid_t; + +#undef RFC_CMP +#define RFC_CMP(a, b) if (a != b) return (a < b) ? -1 : 1 + } int uuid_compare (const uuid_t a, const uuid_t b) { - RPC_STATUS unused; - return !UuidEqual((UUID*)a, (UUID*)b, &unused); + // Could convert each to a GUID and then use UuidEqual(), + // but RFC test is straight forward + rfc_uuid_t* u1 = (rfc_uuid_t *) a; + rfc_uuid_t* u2 = (rfc_uuid_t *) b; + RFC_CMP (u1->time_low, u2->time_low); + RFC_CMP (u1->time_mid, u2->time_mid); + RFC_CMP (u1->time_hi_and_version, u2->time_hi_and_version); + RFC_CMP (u1->clock_seq_hi_and_reserved, u2->clock_seq_hi_and_reserved); + RFC_CMP (u1->clock_seq_low, u2->clock_seq_low); + for (int i = 0; i < 6; i++) + RFC_CMP (u1->node[i], u2->node[i]); + return 0; } |
