#ifndef BOOST_UUID_BASIC_RANDOM_GENERATOR_HPP_INCLUDED
#define BOOST_UUID_BASIC_RANDOM_GENERATOR_HPP_INCLUDED
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/detail/random_provider.hpp>
#include <boost/uuid/detail/endian.hpp>
#include <boost/assert.hpp>
#include <type_traits>
#include <random>
#include <cstdint>
namespace boost {
namespace uuids {
template<class UniformRandomNumberGenerator>
class basic_random_generator
{
private:
UniformRandomNumberGenerator* p_;
UniformRandomNumberGenerator g_;
public:
using result_type = uuid;
basic_random_generator(): p_( 0 ), g_()
{
seed( g_, 0 );
}
explicit basic_random_generator( UniformRandomNumberGenerator& gen ): p_( &gen )
{
}
explicit basic_random_generator( UniformRandomNumberGenerator* gen ): p_( gen )
{
BOOST_ASSERT( gen != 0 );
}
result_type operator()()
{
UniformRandomNumberGenerator& gen = p_? *p_: g_;
result_type u;
fill_data( gen, u );
*(u.begin() + 8) &= 0x3F;
*(u.begin() + 8) |= 0x80;
*(u.begin() + 6) &= 0x0F; *(u.begin() + 6) |= 0x40;
return u;
}
private:
template<class URNG> static void fill_data_impl( URNG& gen, uuid& u, std::false_type, std::false_type )
{
std::uniform_int_distribution<std::uint32_t> dist;
detail::store_little_u32( u.data + 0, dist( gen ) );
detail::store_little_u32( u.data + 4, dist( gen ) );
detail::store_little_u32( u.data + 8, dist( gen ) );
detail::store_little_u32( u.data + 12, dist( gen ) );
}
template<class URNG> static void fill_data_impl( URNG& gen, uuid& u, std::true_type, std::false_type )
{
detail::store_little_u32( u.data + 0, static_cast<std::uint32_t>( gen() ) );
detail::store_little_u32( u.data + 4, static_cast<std::uint32_t>( gen() ) );
detail::store_little_u32( u.data + 8, static_cast<std::uint32_t>( gen() ) );
detail::store_little_u32( u.data + 12, static_cast<std::uint32_t>( gen() ) );
}
template<class URNG> static void fill_data_impl( URNG& gen, uuid& u, std::false_type, std::true_type )
{
detail::store_little_u64( u.data + 0, static_cast<std::uint64_t>( gen() ) );
detail::store_little_u64( u.data + 8, static_cast<std::uint64_t>( gen() ) );
}
template<class URNG> static void fill_data( URNG& gen, uuid& u )
{
fill_data_impl( gen, u,
std::integral_constant<bool, (URNG::min)() == 0 && (URNG::max)() == static_cast<std::uint32_t>( -1 )>(),
std::integral_constant<bool, (URNG::min)() == 0 && (URNG::max)() == static_cast<std::uint64_t>( -1 )>()
);
}
template<class MaybePseudoRandomNumberGenerator, class En = decltype( std::declval<MaybePseudoRandomNumberGenerator&>().seed() )>
void seed( MaybePseudoRandomNumberGenerator& rng, int )
{
detail::random_provider seeder;
rng.seed(seeder);
}
template<class MaybePseudoRandomNumberGenerator>
void seed( MaybePseudoRandomNumberGenerator&, long )
{
}
};
}}
#endif