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