Fix bugs in previous commit that caused FTBFS in synfig and ETL FTBFS with older...
[synfig.git] / synfig-core / tags / synfig_0_61_05 / synfig-core / src / synfig / guid.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file guid.cpp
3 **      \brief Template File
4 **
5 **      $Id: guid.cpp,v 1.4 2005/01/13 06:48:39 darco Exp $
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **
10 **      This package is free software; you can redistribute it and/or
11 **      modify it under the terms of the GNU General Public License as
12 **      published by the Free Software Foundation; either version 2 of
13 **      the License, or (at your option) any later version.
14 **
15 **      This package 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 GNU
18 **      General Public License for more details.
19 **      \endlegal
20 */
21 /* ========================================================================= */
22
23 /* === H E A D E R S ======================================================= */
24
25 #define HASH_MAP_H <ext/hash_map>
26 #define SUBTRACT_RNG_H <ext/functional>
27
28 #ifdef USING_PCH
29 #       include "pch.h"
30 #else
31 #ifdef HAVE_CONFIG_H
32 #       include <config.h>
33 #endif
34
35 #include "guid.h"
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #include <unistd.h>
40 #include <ETL/stringf>
41 #include <functional>
42
43 #ifdef _DEBUG
44 #include "general.h"
45 #endif
46
47 #ifdef HASH_MAP_H
48 #include HASH_MAP_H
49 using namespace __gnu_cxx;
50 #endif
51
52 #ifdef SUBTRACT_RNG_H
53 #include SUBTRACT_RNG_H
54 using namespace __gnu_cxx;
55 #endif
56
57 #ifdef _WIN32
58 #include <windows.h>
59 #endif
60
61 #endif
62
63 /* === U S I N G =========================================================== */
64
65 using namespace std;
66 using namespace etl;
67 using namespace synfig;
68
69 /* === M A C R O S ========================================================= */
70
71 #define MANUAL_GUID_CALC
72
73 /* === G L O B A L S ======================================================= */
74
75 /* === P R O C E D U R E S ================================================= */
76
77 /* === M E T H O D S ======================================================= */
78
79 // A fast 32-bit linear congruential random number generator
80 class quick_rng
81 {
82         unsigned long next;
83 public:
84         quick_rng(unsigned long seed=0):next(seed) { }
85
86         void set_seed(unsigned long x)
87         {
88                 next=x;
89         }
90         
91         unsigned long i32()
92         {
93                 static const unsigned long a(1664525);
94                 static const unsigned long c(1013904223);
95                 
96                 return next=next*a+c;
97         }
98
99         unsigned long i16()
100         {
101                 return i32()>>16;
102         }
103
104         float f()
105         {
106                 static const float m(int(65535));
107                 
108                 return float(i16())/m;
109         }
110         
111         unsigned long operator()(const unsigned long& m)
112         {
113                 if(m==65536)
114                         return i16();
115                 else
116                 if(m<=65536)
117                         return i16()%m;
118                 else
119                         return i32()%m;
120         }
121 };
122
123 #define GUID_RNG quick_rng
124 //#define GUID_RNG subtractive_rng
125
126
127
128 #ifdef MANUAL_GUID_CALC
129 #include <time.h>
130 static GUID_RNG _a, _b;
131 static void _set_up_rand_long_long(uint64_t &x);
132 static void _get_rand_long_long(uint64_t &x);
133 static void (*get_rand_long_long)(uint64_t&)=_set_up_rand_long_long;
134 static void _set_up_rand_long_long(uint64_t &x)
135 {
136 #ifdef _DEBUG
137         synfig::info("Starting up GUID system...");
138 #endif
139         _a=GUID_RNG(time(0)+clock());
140         _b=GUID_RNG(clock());
141         get_rand_long_long=_get_rand_long_long;
142         _get_rand_long_long(x);
143 }
144
145 static void _get_rand_long_long(uint64_t &x)
146 {
147         //subtractive_rng _c(clock());
148         unsigned short* data(reinterpret_cast<unsigned short *>(&x));
149         data[0]=_a(65536);      
150         data[1]=_a(65536);      
151         data[2]=_a(65536);      
152         data[3]=_a(65536);      
153 }
154
155 #else
156 // Use OS-Dependent method
157
158 #ifdef _WIN32
159 // Win32
160 static void get_rand_long_long(uint64_t &x)
161 {
162         _GUID* guid(reinterpret_cast<_GUID*>(&x));
163         CoCreateGuid(guid);     
164 }
165
166 #else
167 // Unix
168 static int rand_fd;
169 static void _set_up_rand_long_long(uint64_t &x);
170 static void _get_rand_long_long(uint64_t &x);
171 static void (*get_rand_long_long)(uint64_t&)=_set_up_rand_long_long;
172 static void _set_up_rand_long_long(uint64_t &x)
173 {
174 #ifdef _DEBUG
175         synfig::info("Starting up GUID system...");
176 #endif
177         rand_fd=open("/dev/urandom",O_RDONLY);
178         get_rand_long_long=_get_rand_long_long;
179         _get_rand_long_long(x);
180 }
181
182 static void _get_rand_long_long(uint64_t &x){   read(rand_fd,&x,sizeof(x));}
183
184 #endif
185 #endif
186
187
188
189 void
190 synfig::GUID::make_unique()
191 {
192         get_rand_long_long(data.u_64.a);
193         get_rand_long_long(data.u_64.b);
194 }
195
196 synfig::GUID
197 synfig::GUID::hasher(const String& str)
198 {       
199 #ifdef HASH_MAP_H
200         hash<const char*> string_hash_;
201         const unsigned int seed(
202                 string_hash_(
203                         str.c_str()
204                 )
205         );
206 #else
207         const unsigned int seed(0x3B642879);
208         for(int i=0;i<str.size();i++)
209         {
210                 seed^=(seed*str[i])*i
211                 seed=(seed>>(32-(i%24)))^(seed<<(i%24))
212         }
213 #endif
214         
215         GUID_RNG random(seed);
216         GUID ret(0);
217         ret.data.u_32.a=random(~(unsigned int)0);
218         ret.data.u_32.b=random(~(unsigned int)0);
219         ret.data.u_32.c=random(~(unsigned int)0);
220         ret.data.u_32.d=random(~(unsigned int)0);
221         return ret;
222 }
223
224 synfig::GUID
225 synfig::GUID::hasher(int i)
226 {
227         GUID ret(0);
228         GUID_RNG random(i);
229         ret.data.u_32.a=random(~(unsigned int)0);
230         ret.data.u_32.b=random(~(unsigned int)0);
231         ret.data.u_32.c=random(~(unsigned int)0);
232         ret.data.u_32.d=random(~(unsigned int)0);
233         return ret;
234 }
235
236 String
237 synfig::GUID::get_string()const
238 {
239         return strprintf("%08X%08X%08X%08X",data.u_32.a,data.u_32.b,data.u_32.c,data.u_32.d);
240 }
241
242 synfig::GUID::GUID(const String &str)
243 {
244         strscanf(str,"%08X%08X%08X%08X",&data.u_32.a,&data.u_32.b,&data.u_32.c,&data.u_32.d);
245 }