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