]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost random_generator.hpp header file ----------------------------------------------// |
2 | ||
3 | // Copyright 2010 Andy Tompkins. | |
4 | // Distributed under the Boost Software License, Version 1.0. (See | |
5 | // accompanying file LICENSE_1_0.txt or copy at | |
6 | // http://www.boost.org/LICENSE_1_0.txt) | |
7 | ||
8 | #ifndef BOOST_UUID_RANDOM_GENERATOR_HPP | |
9 | #define BOOST_UUID_RANDOM_GENERATOR_HPP | |
10 | ||
11 | #include <boost/uuid/uuid.hpp> | |
12 | #include <boost/uuid/seed_rng.hpp> | |
13 | #include <boost/random/uniform_int.hpp> | |
14 | #include <boost/random/variate_generator.hpp> | |
15 | #include <boost/random/mersenne_twister.hpp> | |
16 | #include <boost/assert.hpp> | |
17 | #include <boost/shared_ptr.hpp> | |
18 | #include <limits> | |
19 | ||
20 | namespace boost { | |
21 | namespace uuids { | |
22 | ||
23 | // generate a random-based uuid | |
24 | template <typename UniformRandomNumberGenerator> | |
25 | class basic_random_generator { | |
26 | private: | |
27 | typedef uniform_int<unsigned long> distribution_type; | |
28 | typedef variate_generator<UniformRandomNumberGenerator*, distribution_type> generator_type; | |
29 | ||
30 | struct null_deleter | |
31 | { | |
32 | void operator()(void const *) const {} | |
33 | }; | |
34 | ||
35 | public: | |
36 | typedef uuid result_type; | |
37 | ||
38 | // default constructor creates the random number generator | |
39 | basic_random_generator() | |
40 | : pURNG(new UniformRandomNumberGenerator) | |
41 | , generator | |
42 | ( pURNG.get() | |
43 | , distribution_type | |
44 | ( (std::numeric_limits<unsigned long>::min)() | |
45 | , (std::numeric_limits<unsigned long>::max)() | |
46 | ) | |
47 | ) | |
48 | { | |
49 | // seed the random number generator | |
50 | detail::seed(*pURNG); | |
51 | } | |
52 | ||
53 | // keep a reference to a random number generator | |
54 | // don't seed a given random number generator | |
55 | explicit basic_random_generator(UniformRandomNumberGenerator& gen) | |
56 | : pURNG(&gen, null_deleter()) | |
57 | , generator | |
58 | ( pURNG.get() | |
59 | , distribution_type | |
60 | ( (std::numeric_limits<unsigned long>::min)() | |
61 | , (std::numeric_limits<unsigned long>::max)() | |
62 | ) | |
63 | ) | |
64 | {} | |
65 | ||
66 | // keep a pointer to a random number generator | |
67 | // don't seed a given random number generator | |
68 | explicit basic_random_generator(UniformRandomNumberGenerator* pGen) | |
69 | : pURNG(pGen, null_deleter()) | |
70 | , generator | |
71 | ( pURNG.get() | |
72 | , distribution_type | |
73 | ( (std::numeric_limits<unsigned long>::min)() | |
74 | , (std::numeric_limits<unsigned long>::max)() | |
75 | ) | |
76 | ) | |
77 | { | |
78 | BOOST_ASSERT(pURNG); | |
79 | } | |
80 | ||
81 | uuid operator()() | |
82 | { | |
83 | uuid u; | |
84 | ||
85 | int i=0; | |
86 | unsigned long random_value = generator(); | |
87 | for (uuid::iterator it=u.begin(); it!=u.end(); ++it, ++i) { | |
88 | if (i==sizeof(unsigned long)) { | |
89 | random_value = generator(); | |
90 | i = 0; | |
91 | } | |
92 | ||
93 | // static_cast gets rid of warnings of converting unsigned long to boost::uint8_t | |
94 | *it = static_cast<uuid::value_type>((random_value >> (i*8)) & 0xFF); | |
95 | } | |
96 | ||
97 | // set variant | |
98 | // must be 0b10xxxxxx | |
99 | *(u.begin()+8) &= 0xBF; | |
100 | *(u.begin()+8) |= 0x80; | |
101 | ||
102 | // set version | |
103 | // must be 0b0100xxxx | |
104 | *(u.begin()+6) &= 0x4F; //0b01001111 | |
105 | *(u.begin()+6) |= 0x40; //0b01000000 | |
106 | ||
107 | return u; | |
108 | } | |
109 | ||
110 | private: | |
111 | shared_ptr<UniformRandomNumberGenerator> pURNG; | |
112 | generator_type generator; | |
113 | }; | |
114 | ||
115 | typedef basic_random_generator<mt19937> random_generator; | |
116 | ||
117 | }} // namespace boost::uuids | |
118 | ||
119 | #endif //BOOST_UUID_RANDOM_GENERATOR_HPP |