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 |
120 | |