Initial Patch of Auction House bot rev. 135
[auctionmangos.git] / dep / ACE_wrappers / ace / UUID.cpp
blob4ce2bcd0a4bc9d4c4e178c71277c55617a581a2e
1 //$Id: UUID.cpp 81541 2008-04-30 13:56:12Z shuston $
3 #include "ace/UUID.h"
4 #include "ace/Guard_T.h"
6 #if !defined (__ACE_INLINE__)
7 #include "ace/UUID.inl"
8 #endif /* __ACE_INLINE__ */
10 #include "ace/Log_Msg.h"
11 #include "ace/OS_NS_stdio.h"
12 #include "ace/OS_NS_string.h"
13 #include "ace/OS_NS_sys_time.h"
14 #include "ace/OS_NS_netdb.h"
15 #include "ace/OS_NS_unistd.h"
16 #include "ace/ACE.h"
18 ACE_RCSID (ace,
19 UUID,
20 "$Id: UUID.cpp 81541 2008-04-30 13:56:12Z shuston $")
23 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
25 namespace ACE_Utils
27 UUID_Node::UUID_Node (void)
29 for (int i = 0; i < UUID_Node::NODE_ID_SIZE; ++i)
30 node_ID_[i] = 0;
33 UUID_Node::Node_ID&
34 UUID_Node::node_ID (void)
36 return node_ID_;
39 void
40 UUID_Node::node_ID (Node_ID& node_ID)
42 for (int i = 0; i < UUID_Node::NODE_ID_SIZE; ++i)
43 node_ID_[i] = node_ID[i];
46 UUID UUID::NIL_UUID;
48 /// Construct a nil UUID. Such a UUID has every one of it's data
49 /// elements set to zero.
50 UUID::UUID (void)
51 : time_low_ (0),
52 time_mid_ (0),
53 time_hi_and_version_ (0),
54 clock_seq_hi_and_reserved_ (0),
55 clock_seq_low_ (0),
56 node_ (0),
57 node_release_ (true),
58 as_string_ (0)
60 ACE_NEW (node_,
61 UUID_Node);
64 /// Construct a UUID from a string representation of an UUID.
65 UUID::UUID (const ACE_CString& uuid_string)
66 : time_low_ (0),
67 time_mid_ (0),
68 time_hi_and_version_ (0),
69 clock_seq_hi_and_reserved_ (0),
70 clock_seq_low_ (0),
71 node_ (0),
72 node_release_ (true),
73 as_string_ (0)
75 ACE_NEW (node_,
76 UUID_Node);
78 this->from_string_i (uuid_string);
81 UUID::UUID (const UUID &right)
82 : time_low_ (right.time_low_),
83 time_mid_ (right.time_mid_),
84 time_hi_and_version_ (right.time_hi_and_version_),
85 clock_seq_hi_and_reserved_ (right.clock_seq_hi_and_reserved_),
86 clock_seq_low_ (right.clock_seq_low_),
87 as_string_ (0)
89 ACE_NEW (node_,
90 UUID_Node (*right.node_));
93 UUID::~UUID (void)
95 if (node_release_)
96 delete node_;
98 if (as_string_ != 0)
99 delete as_string_;
102 const ACE_CString*
103 UUID::to_string (void)
105 /// Only compute the string representation once.
106 if (as_string_ == 0)
108 // Get a buffer exactly the correct size. Use the nil UUID as a
109 // gauge. Don't forget the trailing nul.
110 size_t UUID_STRING_LENGTH = 36 + thr_id_.length () + pid_.length ();
111 char *buf = 0;
113 if ((thr_id_.length () != 0) && (pid_.length () != 0))
115 UUID_STRING_LENGTH += 2; //for '-'
116 ACE_NEW_RETURN (buf,
117 char[UUID_STRING_LENGTH + 1],
120 ACE_OS::sprintf (buf,
121 "%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x-%s-%s",
122 this->time_low_,
123 this->time_mid_,
124 this->time_hi_and_version_,
125 this->clock_seq_hi_and_reserved_,
126 this->clock_seq_low_,
127 (this->node_->node_ID ()) [0],
128 (this->node_->node_ID ()) [1],
129 (this->node_->node_ID ()) [2],
130 (this->node_->node_ID ()) [3],
131 (this->node_->node_ID ()) [4],
132 (this->node_->node_ID ()) [5],
133 thr_id_.c_str (),
134 pid_.c_str ()
137 else
139 ACE_NEW_RETURN (buf,
140 char[UUID_STRING_LENGTH + 1],
143 ACE_OS::sprintf (buf,
144 "%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
145 this->time_low_,
146 this->time_mid_,
147 this->time_hi_and_version_,
148 this->clock_seq_hi_and_reserved_,
149 this->clock_seq_low_,
150 (this->node_->node_ID ()) [0],
151 (this->node_->node_ID ()) [1],
152 (this->node_->node_ID ()) [2],
153 (this->node_->node_ID ()) [3],
154 (this->node_->node_ID ()) [4],
155 (this->node_->node_ID ()) [5]
159 // We allocated 'buf' above dynamically, so we shouldn't use
160 // ACE_NEW_RETURN here to avoid a possible memory leak.
161 ACE_NEW_NORETURN (this->as_string_,
162 ACE_CString (buf, UUID_STRING_LENGTH));
164 // we first free the dynamically allocated 'buf'.
165 delete [] buf;
167 // then we test that ACE_NEW succeded for 'as_string_'
168 // if not, we return 0 (NULL) to indicate failure.
169 if (this->as_string_ == 0 )
170 return 0;
173 return as_string_;
176 void
177 UUID::from_string_i (const ACE_CString& uuid_string)
179 if (uuid_string.length () < NIL_UUID.to_string ()->length ())
181 ACE_ERROR ((LM_ERROR,
182 "%N ACE_UUID::from_string_i - "
183 "IllegalArgument (incorrect string length)\n"));
184 return;
187 /// Special case for the nil UUID.
188 if (uuid_string == *NIL_UUID.to_string ())
190 bool copy_constructor_not_supported = false;
191 ACE_ASSERT (copy_constructor_not_supported);
192 //*this = NIL_UUID;
193 ACE_UNUSED_ARG (copy_constructor_not_supported);
194 return;
197 unsigned int time_low;
198 unsigned int time_mid;
199 unsigned int time_hi_and_version;
200 unsigned int clock_seq_hi_and_reserved;
201 unsigned int clock_seq_low;
202 unsigned int node [UUID_Node::NODE_ID_SIZE];
203 char thr_pid_buf [BUFSIZ];
205 if (uuid_string.length () == NIL_UUID.to_string ()->length ())
207 // This might seem quite strange this being in ACE, but it
208 // seems to be a bit difficult to write a facade for ::sscanf
209 // because some compilers dont support vsscanf, including
210 // MSVC. It appears that most platforms support sscanf though
211 // so we need to use it directly.
212 const int nScanned =
213 #if defined (ACE_HAS_TR24731_2005_CRT)
214 sscanf_s (
215 #else
216 ::sscanf (
217 #endif /* ACE_HAS_TR24731_2005_CRT */
218 uuid_string.c_str (),
219 "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x",
220 &time_low,
221 &time_mid,
222 &time_hi_and_version,
223 &clock_seq_hi_and_reserved,
224 &clock_seq_low,
225 &node[0],
226 &node[1],
227 &node[2],
228 &node[3],
229 &node[4],
230 &node[5]
233 if (nScanned != 11)
235 ACE_DEBUG ((LM_DEBUG,
236 "UUID::from_string_i - "
237 "IllegalArgument (invalid string representation)\n"));
238 return;
241 else
243 const int nScanned =
244 #if defined (ACE_HAS_TR24731_2005_CRT)
245 sscanf_s (uuid_string.c_str (),
246 "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x-%s",
247 &time_low,
248 &time_mid,
249 &time_hi_and_version,
250 &clock_seq_hi_and_reserved,
251 &clock_seq_low,
252 &node[0],
253 &node[1],
254 &node[2],
255 &node[3],
256 &node[4],
257 &node[5],
258 thr_pid_buf,
259 BUFSIZ
261 #else
262 ::sscanf (uuid_string.c_str (),
263 "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x-%s",
264 &time_low,
265 &time_mid,
266 &time_hi_and_version,
267 &clock_seq_hi_and_reserved,
268 &clock_seq_low,
269 &node[0],
270 &node[1],
271 &node[2],
272 &node[3],
273 &node[4],
274 &node[5],
275 thr_pid_buf
277 #endif /* ACE_HAS_TR24731_2005_CRT */
279 if (nScanned != 12)
281 ACE_DEBUG ((LM_DEBUG,
282 "ACE_UUID::from_string_i - "
283 "IllegalArgument (invalid string representation)\n"));
284 return;
288 this->time_low_ = static_cast<ACE_UINT32> (time_low);
289 this->time_mid_ = static_cast<ACE_UINT16> (time_mid);
290 this->time_hi_and_version_ = static_cast<ACE_UINT16> (time_hi_and_version);
291 this->clock_seq_hi_and_reserved_ = static_cast<u_char> (clock_seq_hi_and_reserved);
292 this->clock_seq_low_ = static_cast<u_char> (clock_seq_low);
294 UUID_Node::Node_ID node_id;
295 for (int i = 0; i < UUID_Node::NODE_ID_SIZE; ++i)
296 node_id [i] = static_cast<u_char> (node[i]);
298 this->node_->node_ID (node_id);
300 // Support varient 10- only
301 if ((this->clock_seq_hi_and_reserved_ & 0xc0) != 0x80 && (this->clock_seq_hi_and_reserved_ & 0xc0) != 0xc0)
303 ACE_DEBUG ((LM_DEBUG,
304 "ACE_UUID::from_string_i - "
305 "IllegalArgument (unsupported variant)\n"));
306 return;
309 /// Support versions 1, 3, and 4 only
310 ACE_UINT16 V1 = this->time_hi_and_version_;
312 if ((V1 & 0xF000) != 0x1000 &&
313 (V1 & 0xF000) != 0x3000 &&
314 (V1 & 0xF000) != 0x4000)
316 ACE_DEBUG ((LM_DEBUG,
317 "ACE_UUID::from_string_i - "
318 "IllegalArgument (unsupported version)\n"));
319 return;
322 if ((this->clock_seq_hi_and_reserved_ & 0xc0) == 0xc0)
324 if (uuid_string.length () == NIL_UUID.to_string ()->length ())
326 ACE_DEBUG ((LM_DEBUG,
327 "ACE_UUID::from_string_i - "
328 "IllegalArgument (Missing Thread and Process Id)\n"));
329 return;
331 ACE_CString thr_pid_str (thr_pid_buf);
332 ssize_t pos = static_cast<ssize_t> (thr_pid_str.find ('-'));
333 if (pos == -1)
334 ACE_DEBUG ((LM_DEBUG,
335 "ACE_UUID::from_string_i - "
336 "IllegalArgument (Thread and Process Id format incorrect)\n"));
338 this->thr_id_ = thr_pid_str.substr (0, pos);
339 this->pid_ = thr_pid_str.substr (pos+1, thr_pid_str.length ()-pos-1);
343 UUID_Generator::UUID_Generator ()
344 : time_last_ (0),
345 destroy_lock_ (true)
347 ACE_NEW (lock_,
348 ACE_SYNCH_MUTEX);
351 UUID_Generator::~UUID_Generator ()
353 if (destroy_lock_)
354 delete lock_;
357 void
358 UUID_Generator::init (void)
360 ACE_OS::macaddr_node_t macaddress;
361 int result = ACE_OS::getmacaddress (&macaddress);
363 UUID_Node::Node_ID node_id;
364 if (result != -1)
366 // ACE_DEBUG ((LM_DEBUG,
367 // "%02X-%02X-%02X-%02X-%02X-%02X\n",
368 // macaddress.node [0],
369 // macaddress.node [1],
370 // macaddress.node [2],
371 // macaddress.node [3],
372 // macaddress.node [4],
373 // macaddress.node [5]));
375 ACE_OS::memcpy (&node_id,
376 macaddress.node,
377 sizeof (node_id));
379 else
381 node_id [0] = static_cast<u_char> (ACE_OS::rand ());
382 node_id [1] = static_cast<u_char> (ACE_OS::rand ());
383 node_id [2] = static_cast<u_char> (ACE_OS::rand ());
384 node_id [3] = static_cast<u_char> (ACE_OS::rand ());
385 node_id [4] = static_cast<u_char> (ACE_OS::rand ());
386 node_id [5] = static_cast<u_char> (ACE_OS::rand ());
389 this->get_timestamp (time_last_);
392 ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, *lock_);
393 uuid_state_.timestamp = time_last_;
394 uuid_state_.node.node_ID (node_id);
398 void
399 UUID_Generator::generate_UUID (UUID& uuid,ACE_UINT16 version,
400 u_char variant)
402 UUID_Time timestamp;
403 ACE_UINT16 clock_sequence;
405 this->get_timestamp_and_clocksequence (timestamp,
406 clock_sequence);
408 // Construct a Version 1 UUID with the information in the arguements.
409 uuid.time_low (static_cast<ACE_UINT32> (timestamp & 0xFFFFFFFF));
410 uuid.time_mid (static_cast<ACE_UINT16> ((timestamp >> 32) & 0xFFFF));
412 ACE_UINT16 tHAV = static_cast<ACE_UINT16> ((timestamp >> 48) & 0xFFFF);
413 tHAV |= (version << 12);
414 uuid.time_hi_and_version (tHAV);
416 u_char cseqHAV;
417 uuid.clock_seq_low (static_cast<u_char> (clock_sequence & 0xFF));
418 cseqHAV = static_cast<u_char> ((clock_sequence & 0x3f00) >> 8);
419 uuid_state_.timestamp = timestamp;
421 cseqHAV |= variant;
422 uuid.clock_seq_hi_and_reserved (cseqHAV);
423 uuid.node (& (uuid_state_.node));
425 if (variant == 0xc0)
427 ACE_Thread_ID thread_id;
428 char buf [BUFSIZ];
429 thread_id.to_string (buf);
430 uuid.thr_id (buf);
432 ACE_OS::sprintf (buf,
433 "%d",
434 static_cast<int> (ACE_OS::getpid ()));
435 uuid.pid (buf);
439 UUID*
440 UUID_Generator::generate_UUID (ACE_UINT16 version, u_char variant)
442 UUID* uuid;
443 ACE_NEW_RETURN (uuid,
444 UUID,
447 this->generate_UUID (*uuid, version, variant);
448 return uuid;
451 /// Obtain a new timestamp. If UUID's are being generated too quickly
452 /// the clock sequence will be incremented
453 void
454 UUID_Generator::get_timestamp (UUID_Time& timestamp)
456 ACE_GUARD (ACE_SYNCH_MUTEX, mon, *lock_);
458 this->get_systemtime (timestamp);
460 // Account for the clock being set back. Increment the clock /
461 // sequence.
462 if (timestamp <= time_last_)
464 uuid_state_.clock_sequence = static_cast<ACE_UINT16>
465 ((uuid_state_.clock_sequence + 1) & ACE_UUID_CLOCK_SEQ_MASK);
467 // If the system time ticked since the last UUID was
468 // generated. Set / the clock sequence back.
469 else if (timestamp > time_last_)
471 uuid_state_.clock_sequence = 0;
474 time_last_ = timestamp;
477 void
478 UUID_Generator::get_timestamp_and_clocksequence (UUID_Time& timestamp,
479 ACE_UINT16& clock_sequence)
481 ACE_GUARD (ACE_SYNCH_MUTEX, mon, *lock_);
483 this->get_systemtime (timestamp);
485 // Account for the clock being set back. Increment the clock /
486 // sequence.
487 if (timestamp <= time_last_)
488 uuid_state_.clock_sequence = static_cast<ACE_UINT16> ((uuid_state_.clock_sequence + 1) & ACE_UUID_CLOCK_SEQ_MASK);
490 // If the system time ticked since the last UUID was
491 // generated. Set / the clock sequence back.
492 else if (timestamp > time_last_)
493 uuid_state_.clock_sequence = 0;
495 time_last_ = timestamp;
496 clock_sequence = uuid_state_.clock_sequence;
500 * ACE_Time_Value is in POSIX time, seconds since Jan 1, 1970. UUIDs use
501 * time in 100ns ticks since 15 October 1582. The difference is:
502 * 15 Oct 1582 - 1 Jan 1600: 17 days in Oct, 30 in Nov, 31 in Dec +
503 * 17 years and 4 leap days (1584, 88, 92 and 96)
504 * 1 Jan 1600 - 1 Jan 1900: 3 centuries + 73 leap days ( 25 in 17th cent.
505 * and 24 each in 18th and 19th centuries)
506 * 1 Jan 1900 - 1 Jan 1970: 70 years + 17 leap days.
507 * This adds up, in days: (17+30+31+365*17+4)+ (365*300+73)+ (365*70+17) or
508 * 122192928000000000U (0x1B21DD213814000) 100 ns ticks.
510 void
511 UUID_Generator::get_systemtime (UUID_Time & timestamp)
513 const UUID_Time timeOffset =
514 #if defined (ACE_LACKS_UNSIGNEDLONGLONG_T)
515 ACE_U_LongLong (ACE_INT64_LITERAL (0x1B21DD213814000));
516 #elif defined (ACE_LACKS_LONGLONG_T)
517 ACE_U_LongLong (0x13814000u, 0x1B21DD2u);
518 #else
519 ACE_UINT64_LITERAL (0x1B21DD213814000);
520 #endif /* ACE_LACKS_UNSIGNEDLONGLONG_T */
522 /// Get the time of day, convert to 100ns ticks then add the offset.
523 ACE_Time_Value now = ACE_OS::gettimeofday ();
524 ACE_UINT64 time;
525 now.to_usec (time);
526 time = time * 10;
527 timestamp = time + timeOffset;
530 ACE_SYNCH_MUTEX*
531 UUID_Generator::lock (void)
533 return this->lock_;
536 void
537 UUID_Generator::lock (ACE_SYNCH_MUTEX* lock,
538 bool release_lock)
540 if (this->destroy_lock_)
541 delete this->lock_;
543 this->lock_ = lock;
544 this->destroy_lock_ = release_lock;
549 #if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
550 template ACE_Singleton<ACE_Utils::UUID_Generator, ACE_SYNCH_MUTEX> *
551 ACE_Singleton<ACE_Utils::UUID_Generator, ACE_SYNCH_MUTEX>::singleton_;
552 #endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
554 ACE_END_VERSIONED_NAMESPACE_DECL