File indexing completed on 2025-01-18 09:53:32
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_UUID_RANDOM_GENERATOR_HPP
0010 #define BOOST_UUID_RANDOM_GENERATOR_HPP
0011
0012 #include <boost/config.hpp>
0013 #include <boost/assert.hpp>
0014 #include <boost/move/core.hpp>
0015 #include <boost/move/utility_core.hpp>
0016 #include <boost/core/enable_if.hpp>
0017 #include <boost/random/mersenne_twister.hpp>
0018 #include <boost/random/uniform_int.hpp>
0019 #include <boost/random/variate_generator.hpp>
0020 #include <boost/tti/has_member_function.hpp>
0021 #include <boost/uuid/detail/random_provider.hpp>
0022 #include <boost/uuid/uuid.hpp>
0023 #include <limits>
0024
0025 namespace boost {
0026 namespace uuids {
0027
0028 namespace detail {
0029 template<class U>
0030 U& set_uuid_random_vv(U& u)
0031 {
0032
0033
0034 *(u.begin() + 8) &= 0xBF;
0035 *(u.begin() + 8) |= 0x80;
0036
0037
0038
0039 *(u.begin() + 6) &= 0x4F;
0040 *(u.begin() + 6) |= 0x40;
0041
0042 return u;
0043 }
0044
0045 BOOST_TTI_HAS_MEMBER_FUNCTION(seed)
0046 }
0047
0048
0049
0050 template <typename UniformRandomNumberGenerator>
0051 class basic_random_generator
0052 {
0053 BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_random_generator)
0054
0055 private:
0056 typedef uniform_int<unsigned long> distribution_type;
0057 typedef variate_generator<UniformRandomNumberGenerator*, distribution_type> generator_type;
0058
0059 struct impl
0060 {
0061 generator_type generator;
0062
0063 explicit impl(UniformRandomNumberGenerator* purng_arg) :
0064 generator(purng_arg, distribution_type((std::numeric_limits<unsigned long>::min)(), (std::numeric_limits<unsigned long>::max)()))
0065 {
0066 }
0067
0068 virtual ~impl() {}
0069
0070 BOOST_DELETED_FUNCTION(impl(impl const&))
0071 BOOST_DELETED_FUNCTION(impl& operator= (impl const&))
0072 };
0073
0074 struct urng_holder
0075 {
0076 UniformRandomNumberGenerator urng;
0077 };
0078
0079 #if defined(BOOST_MSVC)
0080 #pragma warning(push)
0081
0082 #pragma warning(disable: 4355)
0083 #endif
0084
0085 struct self_contained_impl :
0086 public urng_holder,
0087 public impl
0088 {
0089 self_contained_impl() : impl(&this->urng_holder::urng)
0090 {
0091 }
0092 };
0093
0094 #if defined(BOOST_MSVC)
0095 #pragma warning(pop)
0096 #endif
0097
0098 public:
0099 typedef uuid result_type;
0100
0101
0102
0103
0104 basic_random_generator() : m_impl(new self_contained_impl())
0105 {
0106
0107 seed(static_cast< self_contained_impl* >(m_impl)->urng);
0108 }
0109
0110
0111
0112 explicit basic_random_generator(UniformRandomNumberGenerator& gen) : m_impl(new impl(&gen))
0113 {
0114 }
0115
0116
0117
0118 explicit basic_random_generator(UniformRandomNumberGenerator* gen) : m_impl(new impl(gen))
0119 {
0120 BOOST_ASSERT(!!gen);
0121 }
0122
0123 basic_random_generator(BOOST_RV_REF(basic_random_generator) that) BOOST_NOEXCEPT : m_impl(that.m_impl)
0124 {
0125 that.m_impl = 0;
0126 }
0127
0128 basic_random_generator& operator= (BOOST_RV_REF(basic_random_generator) that) BOOST_NOEXCEPT
0129 {
0130 delete m_impl;
0131 m_impl = that.m_impl;
0132 that.m_impl = 0;
0133 return *this;
0134 }
0135
0136 ~basic_random_generator()
0137 {
0138 delete m_impl;
0139 }
0140
0141 result_type operator()()
0142 {
0143 result_type u;
0144
0145 int i=0;
0146 unsigned long random_value = m_impl->generator();
0147 for (uuid::iterator it = u.begin(), end = u.end(); it != end; ++it, ++i) {
0148 if (i==sizeof(unsigned long)) {
0149 random_value = m_impl->generator();
0150 i = 0;
0151 }
0152
0153
0154 *it = static_cast<uuid::value_type>((random_value >> (i*8)) & 0xFF);
0155 }
0156
0157 return detail::set_uuid_random_vv(u);
0158 }
0159
0160 private:
0161
0162
0163
0164
0165
0166 template<class MaybePseudoRandomNumberGenerator>
0167 typename boost::enable_if<detail::has_member_function_seed<MaybePseudoRandomNumberGenerator, void> >::type
0168 seed(MaybePseudoRandomNumberGenerator& rng)
0169 {
0170 detail::random_provider seeder;
0171 rng.seed(seeder);
0172 }
0173
0174 template<class MaybePseudoRandomNumberGenerator>
0175 typename boost::disable_if<detail::has_member_function_seed<MaybePseudoRandomNumberGenerator, void> >::type
0176 seed(MaybePseudoRandomNumberGenerator&)
0177 {
0178 }
0179
0180 impl* m_impl;
0181 };
0182
0183
0184
0185
0186 class random_generator_pure
0187 {
0188 BOOST_MOVABLE_BUT_NOT_COPYABLE(random_generator_pure)
0189
0190 public:
0191 typedef uuid result_type;
0192
0193 BOOST_DEFAULTED_FUNCTION(random_generator_pure(), {})
0194
0195 random_generator_pure(BOOST_RV_REF(random_generator_pure) that) BOOST_NOEXCEPT :
0196 prov_(boost::move(that.prov_))
0197 {
0198 }
0199
0200 random_generator_pure& operator= (BOOST_RV_REF(random_generator_pure) that) BOOST_NOEXCEPT
0201 {
0202 prov_ = boost::move(that.prov_);
0203 return *this;
0204 }
0205
0206
0207
0208 result_type operator()()
0209 {
0210 result_type result;
0211 prov_.get_random_bytes(&result, sizeof(result_type));
0212 return detail::set_uuid_random_vv(result);
0213 }
0214
0215 private:
0216 detail::random_provider prov_;
0217 };
0218
0219 #if defined(BOOST_UUID_RANDOM_GENERATOR_COMPAT)
0220 typedef basic_random_generator<mt19937> random_generator;
0221 #else
0222 typedef random_generator_pure random_generator;
0223 typedef basic_random_generator<mt19937> random_generator_mt19937;
0224 #endif
0225
0226 }}
0227
0228 #endif