ICE 3.4.2
[php5-ice-freebsdport.git] / cpp / src / IceUtil / UUID.cpp
blobfbff5d7b3bd2184aa2fd3a39bea681ca5a9945e7
1 // **********************************************************************
2 //
3 // Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
4 //
5 // This copy of Ice is licensed to you under the terms described in the
6 // ICE_LICENSE file included in this distribution.
7 //
8 // **********************************************************************
10 #include <IceUtil/UUID.h>
12 // On Windows, we use Windows's RPC UUID generator.
13 // On other platforms, we use a high quality random number generator
14 // (/dev/random) to generate "version 4" UUIDs, as described in
15 // http://www.ietf.org/internet-drafts/draft-mealling-uuid-urn-00.txt
17 #ifdef _WIN32
18 # include <rpc.h>
19 #else
20 # include <IceUtil/Random.h>
21 # include <sys/types.h>
22 # include <unistd.h>
23 #endif
25 using namespace std;
27 #ifndef _WIN32
29 namespace
32 char myPid[2];
36 namespace IceUtilInternal
40 // Initialize the pid.
42 class PidInitializer
44 public:
46 PidInitializer()
48 pid_t p = getpid();
49 myPid[0] = (p >> 8) & 0x7F;
50 myPid[1] = p & 0xFF;
54 PidInitializer pidInitializer;
57 #endif
59 namespace
62 // Helper char to hex functions
64 inline void halfByteToHex(unsigned char hb, char*& hexBuffer)
66 if(hb < 10)
68 *hexBuffer++ = '0' + hb;
70 else
72 *hexBuffer++ = 'A' + (hb - 10);
76 inline void bytesToHex(unsigned char* bytes, size_t len, char*& hexBuffer)
78 for(size_t i = 0; i < len; i++)
80 halfByteToHex((bytes[i] & 0xF0) >> 4, hexBuffer);
81 halfByteToHex((bytes[i] & 0x0F), hexBuffer);
87 string
88 IceUtil::generateUUID()
90 #ifdef _WIN32
92 UUID uuid;
93 UuidCreate(&uuid);
95 unsigned char* str;
97 UuidToString(&uuid, &str);
99 string result = reinterpret_cast<char*>(str);
101 RpcStringFree(&str);
102 return result;
104 #else
105 struct UUID
107 unsigned char timeLow[4];
108 unsigned char timeMid[2];
109 unsigned char timeHighAndVersion[2];
110 unsigned char clockSeqHiAndReserved;
111 unsigned char clockSeqLow;
112 unsigned char node[6];
114 UUID uuid;
116 assert(sizeof(UUID) == 16);
119 // Get a random sequence of bytes. Instead of using 122 random
120 // bits that could be duplicated (because of a bug with some Linux
121 // kernels and potentially other Unix platforms -- see comment in
122 // Random.cpp), we replace the last 15 bits of all "random"
123 // Randoms by the last 15 bits of the process id.
125 char* buffer = reinterpret_cast<char*>(&uuid);
126 IceUtilInternal::generateRandom(buffer, static_cast<int>(sizeof(UUID)));
129 // Adjust the bits that say "version 4" UUID
131 uuid.timeHighAndVersion[0] &= 0x0F;
132 uuid.timeHighAndVersion[0] |= (4 << 4);
133 uuid.clockSeqHiAndReserved &= 0x3F;
134 uuid.clockSeqHiAndReserved |= 0x80;
137 // Replace the end of the node by myPid (15 bits)
139 uuid.node[4] = (uuid.node[4] & 0x80) | myPid[0];
140 uuid.node[5] = myPid[1];
143 // Convert to a UUID string
145 char uuidString[16 * 2 + 4 + 1]; // 16 bytes, 4 '-' and a final '\0'
146 char* uuidIndex = uuidString;
147 bytesToHex(uuid.timeLow, sizeof(uuid.timeLow), uuidIndex);
148 *uuidIndex++ = '-';
149 bytesToHex(uuid.timeMid, sizeof(uuid.timeMid), uuidIndex);
150 *uuidIndex++ = '-';
151 bytesToHex(uuid.timeHighAndVersion, sizeof(uuid.timeHighAndVersion), uuidIndex);
152 *uuidIndex++ = '-';
153 bytesToHex(&uuid.clockSeqHiAndReserved, sizeof(uuid.clockSeqHiAndReserved), uuidIndex);
154 bytesToHex(&uuid.clockSeqLow, sizeof(uuid.clockSeqLow), uuidIndex);
155 *uuidIndex++ = '-';
156 bytesToHex(uuid.node, sizeof(uuid.node), uuidIndex);
157 *uuidIndex = '\0';
159 return uuidString;
161 #endif