1 // Boost random_generator.hpp header file ----------------------------------------------//
3 // Copyright 2010 Andy Tompkins.
4 // Copyright 2017 James E. King III
5 // Distributed under the Boost Software License, Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // https://www.boost.org/LICENSE_1_0.txt)
9 #ifndef BOOST_UUID_RANDOM_GENERATOR_HPP
10 #define BOOST_UUID_RANDOM_GENERATOR_HPP
12 #include <boost/config.hpp>
13 #include <boost/assert.hpp>
14 #include <boost/move/core.hpp>
15 #include <boost/move/utility_core.hpp>
16 #include <boost/core/enable_if.hpp>
17 #include <boost/random/mersenne_twister.hpp>
18 #include <boost/random/uniform_int.hpp>
19 #include <boost/random/variate_generator.hpp>
20 #include <boost/tti/has_member_function.hpp>
21 #include <boost/uuid/detail/random_provider.hpp>
22 #include <boost/uuid/uuid.hpp>
30 U& set_uuid_random_vv(U& u)
34 *(u.begin() + 8) &= 0xBF;
35 *(u.begin() + 8) |= 0x80;
39 *(u.begin() + 6) &= 0x4F; //0b01001111
40 *(u.begin() + 6) |= 0x40; //0b01000000
45 BOOST_TTI_HAS_MEMBER_FUNCTION(seed)
48 //! generate a random-based uuid
49 //! \param[in] UniformRandomNumberGenerator see Boost.Random documentation
50 template <typename UniformRandomNumberGenerator>
51 class basic_random_generator
53 BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_random_generator)
56 typedef uniform_int<unsigned long> distribution_type;
57 typedef variate_generator<UniformRandomNumberGenerator*, distribution_type> generator_type;
61 generator_type generator;
63 explicit impl(UniformRandomNumberGenerator* purng_arg) :
64 generator(purng_arg, distribution_type((std::numeric_limits<unsigned long>::min)(), (std::numeric_limits<unsigned long>::max)()))
70 BOOST_DELETED_FUNCTION(impl(impl const&))
71 BOOST_DELETED_FUNCTION(impl& operator= (impl const&))
76 UniformRandomNumberGenerator urng;
79 #if defined(BOOST_MSVC)
81 // 'this' : used in base member initializer list
82 #pragma warning(disable: 4355)
85 struct self_contained_impl :
89 self_contained_impl() : impl(&this->urng_holder::urng)
94 #if defined(BOOST_MSVC)
99 typedef uuid result_type;
101 // default constructor creates the random number generator and
102 // if the UniformRandomNumberGenerator is a PseudoRandomNumberGenerator
103 // then it gets seeded by a random_provider.
104 basic_random_generator() : m_impl(new self_contained_impl())
106 // seed the random number generator if it is capable
107 seed(static_cast< self_contained_impl* >(m_impl)->urng);
110 // keep a reference to a random number generator
111 // don't seed a given random number generator
112 explicit basic_random_generator(UniformRandomNumberGenerator& gen) : m_impl(new impl(&gen))
116 // keep a pointer to a random number generator
117 // don't seed a given random number generator
118 explicit basic_random_generator(UniformRandomNumberGenerator* gen) : m_impl(new impl(gen))
123 basic_random_generator(BOOST_RV_REF(basic_random_generator) that) BOOST_NOEXCEPT : m_impl(that.m_impl)
128 basic_random_generator& operator= (BOOST_RV_REF(basic_random_generator) that) BOOST_NOEXCEPT
131 m_impl = that.m_impl;
136 ~basic_random_generator()
141 result_type operator()()
146 unsigned long random_value = m_impl->generator();
147 for (uuid::iterator it = u.begin(), end = u.end(); it != end; ++it, ++i) {
148 if (i==sizeof(unsigned long)) {
149 random_value = m_impl->generator();
153 // static_cast gets rid of warnings of converting unsigned long to boost::uint8_t
154 *it = static_cast<uuid::value_type>((random_value >> (i*8)) & 0xFF);
157 return detail::set_uuid_random_vv(u);
161 // Detect whether UniformRandomNumberGenerator has a seed() method which indicates that
162 // it is a PseudoRandomNumberGenerator and needs a seed to initialize it. This allows
163 // basic_random_generator to take any type of UniformRandomNumberGenerator and still
164 // meet the post-conditions for the default constructor.
166 template<class MaybePseudoRandomNumberGenerator>
167 typename boost::enable_if<detail::has_member_function_seed<MaybePseudoRandomNumberGenerator, void> >::type
168 seed(MaybePseudoRandomNumberGenerator& rng)
170 detail::random_provider seeder;
174 template<class MaybePseudoRandomNumberGenerator>
175 typename boost::disable_if<detail::has_member_function_seed<MaybePseudoRandomNumberGenerator, void> >::type
176 seed(MaybePseudoRandomNumberGenerator&)
183 //! \brief a far less complex random generator that uses
184 //! operating system provided entropy which will
185 //! satisfy the majority of use cases
186 class random_generator_pure
188 BOOST_MOVABLE_BUT_NOT_COPYABLE(random_generator_pure)
191 typedef uuid result_type;
193 BOOST_DEFAULTED_FUNCTION(random_generator_pure(), {})
195 random_generator_pure(BOOST_RV_REF(random_generator_pure) that) BOOST_NOEXCEPT :
196 prov_(boost::move(that.prov_))
200 random_generator_pure& operator= (BOOST_RV_REF(random_generator_pure) that) BOOST_NOEXCEPT
202 prov_ = boost::move(that.prov_);
206 //! \returns a random, valid uuid
207 //! \throws entropy_error
208 result_type operator()()
211 prov_.get_random_bytes(&result, sizeof(result_type));
212 return detail::set_uuid_random_vv(result);
216 detail::random_provider prov_;
219 #if defined(BOOST_UUID_RANDOM_GENERATOR_COMPAT)
220 typedef basic_random_generator<mt19937> random_generator;
222 typedef random_generator_pure random_generator;
223 typedef basic_random_generator<mt19937> random_generator_mt19937;
226 }} // namespace boost::uuids
228 #endif // BOOST_UUID_RANDOM_GENERATOR_HPP