| // Boost random_generator.hpp header file ----------------------------------------------// |
| |
| // Copyright 2010 Andy Tompkins. |
| // Distributed under the Boost Software License, Version 1.0. (See |
| // accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| |
| #ifndef BOOST_UUID_RANDOM_GENERATOR_HPP |
| #define BOOST_UUID_RANDOM_GENERATOR_HPP |
| |
| #include <boost/uuid/uuid.hpp> |
| #include <boost/uuid/seed_rng.hpp> |
| #include <boost/random/uniform_int.hpp> |
| #include <boost/random/variate_generator.hpp> |
| #include <boost/random/mersenne_twister.hpp> |
| #include <boost/assert.hpp> |
| #include <boost/shared_ptr.hpp> |
| #include <limits> |
| |
| namespace boost { |
| namespace uuids { |
| |
| // generate a random-based uuid |
| template <typename UniformRandomNumberGenerator> |
| class basic_random_generator { |
| private: |
| typedef uniform_int<unsigned long> distribution_type; |
| typedef variate_generator<UniformRandomNumberGenerator*, distribution_type> generator_type; |
| |
| struct null_deleter |
| { |
| void operator()(void const *) const {} |
| }; |
| |
| public: |
| typedef uuid result_type; |
| |
| // default constructor creates the random number generator |
| basic_random_generator() |
| : pURNG(new UniformRandomNumberGenerator) |
| , generator |
| ( pURNG.get() |
| , distribution_type |
| ( (std::numeric_limits<unsigned long>::min)() |
| , (std::numeric_limits<unsigned long>::max)() |
| ) |
| ) |
| { |
| // seed the random number generator |
| detail::seed(*pURNG); |
| } |
| |
| // keep a reference to a random number generator |
| // don't seed a given random number generator |
| explicit basic_random_generator(UniformRandomNumberGenerator& gen) |
| : pURNG(&gen, null_deleter()) |
| , generator |
| ( pURNG.get() |
| , distribution_type |
| ( (std::numeric_limits<unsigned long>::min)() |
| , (std::numeric_limits<unsigned long>::max)() |
| ) |
| ) |
| {} |
| |
| // keep a pointer to a random number generator |
| // don't seed a given random number generator |
| explicit basic_random_generator(UniformRandomNumberGenerator* pGen) |
| : pURNG(pGen, null_deleter()) |
| , generator |
| ( pURNG.get() |
| , distribution_type |
| ( (std::numeric_limits<unsigned long>::min)() |
| , (std::numeric_limits<unsigned long>::max)() |
| ) |
| ) |
| { |
| BOOST_ASSERT(pURNG); |
| } |
| |
| uuid operator()() |
| { |
| uuid u; |
| |
| int i=0; |
| unsigned long random_value = generator(); |
| for (uuid::iterator it=u.begin(); it!=u.end(); ++it, ++i) { |
| if (i==sizeof(unsigned long)) { |
| random_value = generator(); |
| i = 0; |
| } |
| |
| *it = ((random_value >> (i*8)) & 0xFF); |
| } |
| |
| // set variant |
| // must be 0b10xxxxxx |
| *(u.begin()+8) &= 0xBF; |
| *(u.begin()+8) |= 0x80; |
| |
| // set version |
| // must be 0b0100xxxx |
| *(u.begin()+6) &= 0x4F; //0b01001111 |
| *(u.begin()+6) |= 0x40; //0b01000000 |
| |
| return u; |
| } |
| |
| private: |
| shared_ptr<UniformRandomNumberGenerator> pURNG; |
| generator_type generator; |
| }; |
| |
| typedef basic_random_generator<mt19937> random_generator; |
| |
| }} // namespace boost::uuids |
| |
| #endif //BOOST_UUID_RANDOM_GENERATOR_HPP |