Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
UUID.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5 Multimediale Systeme der Informationsverarbeitung
6 Institut fuer Informatik
7 Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 
26 #include "UUID.hh"
27 
28 #include <sstream>
29 
30 #include <limits>
31 
32 #ifndef WIN32
33 #include <unistd.h> // for usleep
34 #endif
35 
36 using namespace BIAS;
37 using namespace std;
38 
39 // static initialization
41 #ifdef WIN32
42  0,0
43 #else
44  numeric_limits<time_t>::min(),
45  numeric_limits<suseconds_t>::min()
46 #endif
47 };
49 
50 
51 // jw
53 
54 
55 // TODO: discuss change from bool isValid to IsNUL comparison ?
57 {
58  this->clear();
59 }
60 
61 
62 // copy ctor
64 {
65  (*this) = id;
66 }
67 
68 
69 BIAS::UUID::UUID(const uuid_t &id) {
70  // TOOD: use uuid_copy instead on Linux (jw)
71  memcpy(
72  (void*)&theID_,
73  (void*)&id,
74  sizeof(uuid_t)
75  );
76  IsValid_ = true;
77 }
78 
79 
80 // very slow. JW
81 BIAS::UUID::UUID(const std::string &sID){
82  SetFromString(sID);
83 }
84 
85 
86 BIAS::UUID::UUID(const unsigned long & n)
87 {
88  SetFromLong(n);
89 }
90 
91 
92 // jw
94 {
95 #ifdef WIN32
96  // does not take significant performace. (1.000.000 =16 msec) JW
97  UuidCreateNil( &(this->theID_) );
98 #else //WIN32
99  uuid_clear(this->theID_);
100 #endif //WIN32
101 
102  // invalidate because NULL UID is not unique in general.
103  IsValid_ = false;
104 }
105 
106 
107 // jw
108 bool BIAS::UUID::IsNil() const
109 {
110  if (IsConsecutive()){
111  return !IsValid_;
112  }
113  // the following does not work for consecutive ids...
114  bool result=false;
115 #ifdef WIN32
116  RPC_STATUS status=RPC_S_OK;
117  result = (TRUE==UuidIsNil(
118  (uuid_t * )(&theID_),
119  &status )
120  );
121  BIASASSERT(status==RPC_S_OK);
122 #else //WIN32
123  result = (1==uuid_is_null(theID_));
124 #endif //WIN32
125  return result;
126 }
127 
128 
129 
130 bool BIAS::UUID::SetFromString(const std::string &sID) {
131 #ifdef WIN32
132  char *tmp = const_cast<char *>(sID.c_str());
133  unsigned char * cUUIDwin = reinterpret_cast<unsigned char *>(tmp);
134  // jw: WIN system func from rpcdce.h
135  // maps to UuidFromStringA for ASCII (standard for us )
136  // and UuidFromStringW for UNICODE build (untested)
137  if (UuidFromString(cUUIDwin, &theID_)!=RPC_S_OK) {
138  BIASERR("UUID could not be read!");
139  IsValid_ = false;
140  }
141  else IsValid_ = true;
142  // std::cout <<"After Parser: "<<std::hex<<theID_.Data1<<"-"
143  // <<theID_.Data2<<std::dec<<std::endl;
144 #else
145  if (sID.length()!=36)
146  BIASERR("Wrong size of string to construct from: "<<sID);
147  if (uuid_parse(sID.c_str(), theID_)!=0) {
148  BIASERR("UUID could not be read!");
149  IsValid_ = false;
150  }
151  else IsValid_ = true;
152 #endif
153  return IsValid_;
154 }
155 
156 
157 // jw
158 bool BIAS::UUID::SetFromLong(const unsigned long & n) {
159  clear();
160  this->IsValid_ = true;
161 
162 #ifdef WIN32
163  theID_.Data1=n; // unsigned long
164  // distinguish sequential 0 ID from NIL ID by setting exactly one more element to one:
165  theID_.Data2=1; // unsigned short
166  // keep a copy for future consistency checks:
167  //BIASASSERT(sizeof(n) <= 8);
168  memcpy(
169  (void*)(&(theID_.Data4[8-sizeof(n)])), // dest ptr
170  (void*)(&n), // src ptr
171  sizeof(n) );
172  return true;
173 #else // WIN32
174  // TODO: inefficient, store the unsigned long directly in the unsigned char[16] JW
175  std::stringstream ss;
176  // unused prefix:
177  ss<<"00000000-0000-0000-0000-";
178  // 12 digit hex format with leading zeroes
179  ss<<setfill('0')<<setw(12)<<noshowbase<<hex<<n;
180  return SetFromString( ss.str() );
181 #endif // WIN32
182 }
183 
184 // jw
185 unsigned long BIAS::UUID::GetLong() const
186 {
187  if ( !IsConsecutive() ){
188  // uuid is not consecutive and the call to GetLong is not allowed
189  BIASERR("cannot extract non-consecutive uuid into long");
190  BIASABORT;
191  }
192 
193  unsigned long n=0;
194 #ifdef WIN32
195 # ifdef BIAS_DEBUG
196  // compare values to reserved pattern for consecutive ID`s
197  if (
198  (theID_.Data2 !=1) ||
199  (theID_.Data3 !=0) ||
200  (theID_.Data4[0]!=0) ||
201  (theID_.Data4[1]!=0)
202  )
203  {
204  BIASWARNONCE("you are trying to GetLong a consecutive ID "<<endl
205  <<(*this)<<endl
206  <<"with data fields that dont match the reserved consecutive pattern: \"<longID>-0001-0000-0000-*"
207  <<"This is inconsistent !");
208  //BIASBREAK;
209  return n;
210  };
211 # endif // BIAS_DEBUG
212  n=theID_.Data1;
213 #else //WIN32
214  // TODO: efficient
215  std::string s;
216  std::istringstream iss;
217  GetString(s);
218  // parse result and extract least significat value (12 hex Bytes)
219  // to be compatible with SetFromLong
220  // find last numerical part:
221  std::string::size_type pos = s.rfind('-');
222  if (pos != string::npos){
223  // found, extract last 12 hex Bytes
224  iss.str( s.substr(pos+1, 12) );
225  iss>>hex>> n;
226  }
227 #endif //WIN32
228  return n;
229 }
230 
231 
232 
233 // static
234 BIAS::UUID
235 BIAS::UUID::GenerateUUID(const bool & consecutively)
236 {
237  BIAS::UUID id;
238  id.AssignUUID(consecutively);
239  return id;
240 }
241 
242 
243 // static
244 BIAS::UUID
246 {
247  BIAS::UUID id;
249  return id;
250 }
251 
252 // static
253 BIAS::UUID
255 {
256  BIAS::UUID id;
257  id.AssignUUID_Global();
258  return id;
259 }
260 
261 
262 // jw
263 void
264 BIAS::UUID::AssignUUID(const bool & consecutively)
265 {
266  if (consecutively)
267  return AssignUUID_Consecutive();
268  else
269  return AssignUUID_Global();
270 }
271 
272 
273 
274 // TODO: thread safe increase of g_uniqueCounter? (JW)
275 // JW
276 void
278 {
279  this->SetFromLong(g_uniqueCounter);
280  g_uniqueCounter++;
281 
282  // set the valid flag for backward compatibillty
283  this->IsValid_ = true;
284 }
285 
286 
287 // jw
288 void
290 {
291  //uuid_t id;
292 #ifdef WIN32
293  //JW details: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/rpc/rpc/uuid_1.asp
294  // creation uses ethernet/token ring addresses; UUID is guaranteed to be unique for the network
295  HRESULT hr = UuidCreate( &theID_);
296  switch (hr)
297  {
298  case RPC_S_UUID_LOCAL_ONLY:
299  BIASERR("UUID_LOCAL_ONLY guaranteed uniqueness for the generating machine, only!");
300  case RPC_S_OK:
301  break;
302  default:
303  BIASERR("Could not create UUID!");
304  } // of switch
305 
306 #else // WIN32
307  uuid_generate_time(theID_);
308  timeval CurTime;
309  uuid_time(theID_, &CurTime);
310  if ((CurTime.tv_sec < LastGenerationTime_.tv_sec) ||
311  ((CurTime.tv_sec == LastGenerationTime_.tv_sec) &&
312  (CurTime.tv_usec <= LastGenerationTime_.tv_usec))) {
313  // BIASERR("There is a system clock problem ! The last time used for UUID"
314  // <<" generation lies in the future ! Maybe someone has turned"
315  // <<" back the clock (NTP ?). UUIDs may not be unique anymore."
316  // <<" CurTime="<<CurTime.tv_sec<<":"<<CurTime.tv_usec
317  // <<" LastTime="<<LastGenerationTime_.tv_sec<<":"
318  // <<LastGenerationTime_.tv_usec);
319  // sleeping a little and retry
320  usleep(1);
321  uuid_generate_time(theID_);
322  timeval CurTime;
323 # ifdef __APPLE__
324  uuid_generate_time(theID_);
325 # else
326  uuid_time(theID_, &CurTime);
327 # endif // APPLE
328  if ((CurTime.tv_sec < LastGenerationTime_.tv_sec) ||
329  ((CurTime.tv_sec == LastGenerationTime_.tv_sec) &&
330  (CurTime.tv_usec <= LastGenerationTime_.tv_usec))) {
331 // BIASERR("There is a system clock problem ! The last time used for UUID"
332 // <<" generation lies in the future ! Maybe someone has turned"
333 // <<" back the clock (NTP ?). UUIDs may not be unique anymore."
334 // <<" CurTime="<<CurTime.tv_sec<<":"<<CurTime.tv_usec
335 // <<" LastTime="<<LastGenerationTime_.tv_sec<<":"
336 // <<LastGenerationTime_.tv_usec);
337  // sleeping a little and retry
338  usleep(1);
339  uuid_generate_time(theID_);
340 # ifndef __APPLE__
341  timeval CurTime;
342  uuid_time(theID_, &CurTime);
343 # endif //__APPLE__
344  if ((CurTime.tv_sec < LastGenerationTime_.tv_sec) ||
345  ((CurTime.tv_sec == LastGenerationTime_.tv_sec) &&
346  (CurTime.tv_usec <= LastGenerationTime_.tv_usec))) {
347 // BIASERR("There is a system clock problem ! The last time used for UUID"
348 // <<" generation lies in the future ! Maybe someone has turned"
349 // <<" back the clock (NTP ?). UUIDs may not be unique anymore."
350 // <<" CurTime="<<CurTime.tv_sec<<":"<<CurTime.tv_usec
351 // <<" LastTime="<<LastGenerationTime_.tv_sec<<":"
352 // <<LastGenerationTime_.tv_usec);
353  }
354  }
355  }
356  LastGenerationTime_.tv_sec = CurTime.tv_sec;
357  LastGenerationTime_.tv_usec = CurTime.tv_usec;
358 #endif // WIN32
359 
360  // set the valid flag for backward compatibillty
361  this->IsValid_ = true;
362 }
363 
364 
365 
366 void BIAS::UUID::GetString(std::string& sUUID) const {
367 #ifdef WIN32
368  unsigned char * cUUIDwin;
369  UuidToString (const_cast<uuid_t*>(&theID_), &cUUIDwin);
370  sUUID = (char *)cUUIDwin;
371 #else
372  char cUUID[37];
373  uuid_unparse(theID_, cUUID);
374  sUUID = cUUID;
375 #endif
376 }
377 
378 // jw
379 std::string BIAS::UUID::GetString() const {
380  std::string str;
381  GetString(str);
382  return str;
383 }
384 
385 
387 #ifdef WIN32
388  BIASERR("Not yet implemented!");
389  return time_t();
390 #else
391 
392  time_t thetime;
393 # ifdef __APPLE__
394  BIAS::UUID *t = const_cast<BIAS::UUID *>(this);
395  uuid_generate_time(t->theID_);
396 # else
397  timeval CreationTime;
398  thetime = uuid_time(theID_, &CreationTime);
399 # endif
400  return thetime;
401 #endif
402 }
403 
405 #ifdef WIN32
406  BIASERR("Not yet implemented!");
407  return timeval();
408 #else
409 
410  timeval CreationTime;
411  uuid_time(theID_, &CreationTime);
412 
413  return CreationTime;
414 #endif
415 }
416 
417 std::ostream& BIAS::operator<<(std::ostream & os, const UUID& id)
418 {
419  std::string suid;
420  id.GetString(suid);
421  os << suid;
422  return os;
423 }
424 
425 
426 std::istream& BIAS::operator>>(std::istream & is, UUID& id)
427 {
428  std::string suid;
429  is >> suid;
430 
431  id.IsValid_ = true;
432  // call libuuid function to get id out of string:
433 #ifdef WIN32
434  GUID tmpGUID = ((GUID)id.theID_);
435  if (UuidFromString((unsigned char*)suid.c_str(), &tmpGUID)!=RPC_S_OK)
436 #else
437  if (uuid_parse(suid.c_str(), id.theID_)!=0)
438 #endif
439  {
440  BIASERR("UUID could not be read from \""<<suid<<"\"");
441  id.IsValid_ = false;
442  is.setstate(std::ios_base::failbit | std::ios_base::badbit);
443  // BIASABORT;
444  }
445 
446  return is;
447 }
448 
449 
451 {
452  static const BIAS::UUID max_consecutive =
453 #if defined(__x86_64__) || defined(__sparc64__) || \
454  defined(__arch64__) || defined(__powerpc64__) || defined (__s390x__)
455  BIAS::UUID(0xffffffffffff);
456 #else
457  BIAS::UUID(0xffffffff);
458 #endif
459  static const string mc= max_consecutive.GetString();
460  return (this->GetString()<=mc);
461 }
462 
463 
464 const unsigned char *BIAS::UUID::GetUUIDRaw() const
465 {
466 #ifdef WIN32
467  return NULL;
468 #else
469  return (unsigned char *)theID_;
470 #endif
471 }
472 
473 
474 void BIAS::UUID::SetUUIDRaw(const unsigned char *rawid)
475 {
476 #ifdef WIN32
477  BIASASSERT(rawid!=NULL);
478 #else
479  memcpy((unsigned char *)theID_, rawid, 16);
480  if (IsConsecutive()) {
481  IsValid_ = true;
482  } else {
483  IsValid_ = !IsNil();
484  }
485 #endif
486 }
void GetString(std::string &sUUID) const
writes the UUID into a string object
Definition: UUID.cpp:366
time_t GetUUIDCreationTime() const
returns the time used to create the uuid (just seconds)
Definition: UUID.cpp:386
static UUID GenerateUUID_Consecutive()
jw
Definition: UUID.cpp:245
timeval GetUUIDCreationTimeStruct() const
returns the time used to create the uuid (seconds and usecs)
Definition: UUID.cpp:404
UUID()
default constructor does NOT create a valid UUID to avoid performance decrease in case someone wants ...
Definition: UUID.cpp:56
void AssignUUID_Consecutive()
jw
Definition: UUID.cpp:277
void AssignUUID(const bool &consecutively=DEFAULT_UUID_CONSECUTIVELY)
function to assign a fresh, unique ID.
Definition: UUID.cpp:264
bool IsNil() const
Definition: UUID.cpp:108
bool IsConsecutive() const
undefined behaviour if uuid is invalid
Definition: UUID.cpp:450
static long g_uniqueCounter
global counter to create next unique consecutive program run-unique ID.
Definition: UUID.hh:246
bool SetFromString(const std::string &sID)
construct from string containing ascii uuid.
Definition: UUID.cpp:130
bool SetFromLong(const unsigned long &n)
construct from a unique long.
Definition: UUID.cpp:158
virtual ~UUID()
Definition: UUID.cpp:52
void clear()
NULLS the class members, invalidates this UID ( not unique anymore).
Definition: UUID.cpp:93
static timeval LastGenerationTime_
when creating a uuid, current time is compared against the time saved during the last uuid generation...
Definition: UUID.hh:243
const unsigned char * GetUUIDRaw() const
get the pointer to the Uc[16] array with the raw uuid
Definition: UUID.cpp:464
std::string GetString() const
Definition: UUID.cpp:379
std::ostream & operator<<(std::ostream &os, const Array2D< T > &arg)
Definition: Array2D.hh:260
unsigned long GetLong() const
get least significant value of UID as long value.
Definition: UUID.cpp:185
class BIASImageBase_EXPORT UUID
forward declaration for stream operators
Definition: UUID.hh:64
interface class for producing/storing Universally Unique IDentifiers
Definition: UUID.hh:98
uuid_t theID_
the data fields of the uuid
Definition: UUID.hh:233
static UUID GenerateUUID(const bool &consecutively=DEFAULT_UUID_CONSECUTIVELY)
static function which simply produces a uuid and returns
Definition: UUID.cpp:235
void AssignUUID_Global()
jw
Definition: UUID.cpp:289
BIASCommon_EXPORT std::istream & operator>>(std::istream &is, BIAS::TimeStamp &ts)
Standard input operator for TimeStamps.
Definition: TimeStamp.cpp:157
void SetUUIDRaw(const unsigned char *rawid)
Definition: UUID.cpp:474
static UUID GenerateUUID_Global()
jw
Definition: UUID.cpp:254