1 /*
2  * Copyright (C) 2009 Tommi Maekitalo
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
11  * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
12  * NON-INFRINGEMENT.  See the GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
17  *
18  */
19 
20 #include <zim/uuid.h>
21 #include <iostream>
22 #include <time.h>
23 #include <zim/zim.h> // necessary to have the new types
24 #include "log.h"
25 #include "md5.h"
26 
27 #ifdef _WIN32
28 
29 #  include <time.h>
30 #  include <windows.h>
gettimeofday(struct timeval * tp,void * tzp)31 int gettimeofday(struct timeval* tp, void* tzp) {
32     DWORD t;
33     t = timeGetTime();
34     tp->tv_sec = t / 1000;
35     tp->tv_usec = t % 1000;
36     return 0;
37 }
38 
39 #define getpid GetCurrentProcessId
40 
41 #else
42 #  include <sys/time.h>
43 #endif
44 
45 log_define("zim.uuid")
46 
47 namespace zim
48 {
49   namespace
50   {
51     char hex[] = "0123456789abcdef";
hi(char v)52     inline char hi(char v)
53     { return hex[(v >> 4) & 0xf]; }
54 
lo(char v)55     inline char lo(char v)
56     { return hex[v & 0xf]; }
57   }
58 
generate(std::string value)59   Uuid Uuid::generate(std::string value)
60   {
61     Uuid ret;
62     struct zim_MD5_CTX md5ctx;
63     zim_MD5Init(&md5ctx);
64 
65     if ( value.empty() ) {
66       struct timeval tv;
67       gettimeofday(&tv, 0);
68 
69       clock_t c = clock();
70 
71       zim_MD5Update(&md5ctx, reinterpret_cast<const uint8_t*>(&c), sizeof(clock_t));
72       zim_MD5Update(&md5ctx, reinterpret_cast<const uint8_t*>(&tv), sizeof(struct timeval));
73     } else {
74       zim_MD5Update(&md5ctx, reinterpret_cast<const uint8_t*>(value.data()), value.size());
75     }
76     zim_MD5Final(reinterpret_cast<uint8_t*>(&ret.data[0]), &md5ctx);
77 
78     log_debug("generated uuid: " << ret.data);
79 
80     return ret;
81   }
82 
operator <<(std::ostream & out,const Uuid & uuid)83   std::ostream& operator<< (std::ostream& out, const Uuid& uuid)
84   {
85     for (unsigned n = 0; n < 4; ++n)
86       out << hi(uuid.data[n]) << lo(uuid.data[n]);
87     out << '-';
88     for (unsigned n = 4; n < 6; ++n)
89       out << hi(uuid.data[n]) << lo(uuid.data[n]);
90     out << '-';
91     for (unsigned n = 6; n < 8; ++n)
92       out << hi(uuid.data[n]) << lo(uuid.data[n]);
93     out << '-';
94     for (unsigned n = 8; n < 10; ++n)
95       out << hi(uuid.data[n]) << lo(uuid.data[n]);
96     out << '-';
97     for (unsigned n = 10; n < 16; ++n)
98       out << hi(uuid.data[n]) << lo(uuid.data[n]);
99     return out;
100   }
101 
102 }
103