Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:53:32

0001 // Boost random_generator.hpp header file  ----------------------------------------------//
0002 
0003 // Copyright 2010 Andy Tompkins.
0004 // Copyright 2017 James E. King III
0005 // Distributed under the Boost Software License, Version 1.0. (See
0006 // accompanying file LICENSE_1_0.txt or copy at
0007 // https://www.boost.org/LICENSE_1_0.txt)
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         // set variant
0033         // must be 0b10xxxxxx
0034         *(u.begin() + 8) &= 0xBF;
0035         *(u.begin() + 8) |= 0x80;
0036 
0037         // set version
0038         // must be 0b0100xxxx
0039         *(u.begin() + 6) &= 0x4F; //0b01001111
0040         *(u.begin() + 6) |= 0x40; //0b01000000
0041 
0042         return u;
0043     }
0044 
0045     BOOST_TTI_HAS_MEMBER_FUNCTION(seed)
0046 }
0047 
0048 //! generate a random-based uuid
0049 //! \param[in]  UniformRandomNumberGenerator  see Boost.Random documentation
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 // 'this' : used in base member initializer list
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     // default constructor creates the random number generator and
0102     // if the UniformRandomNumberGenerator is a PseudoRandomNumberGenerator
0103     // then it gets seeded by a random_provider.
0104     basic_random_generator() : m_impl(new self_contained_impl())
0105     {
0106         // seed the random number generator if it is capable
0107         seed(static_cast< self_contained_impl* >(m_impl)->urng);
0108     }
0109 
0110     // keep a reference to a random number generator
0111     // don't seed a given random number generator
0112     explicit basic_random_generator(UniformRandomNumberGenerator& gen) : m_impl(new impl(&gen))
0113     {
0114     }
0115 
0116     // keep a pointer to a random number generator
0117     // don't seed a given random number generator
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             // static_cast gets rid of warnings of converting unsigned long to boost::uint8_t
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     // Detect whether UniformRandomNumberGenerator has a seed() method which indicates that
0162     // it is a PseudoRandomNumberGenerator and needs a seed to initialize it.  This allows
0163     // basic_random_generator to take any type of UniformRandomNumberGenerator and still
0164     // meet the post-conditions for the default constructor.
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 //! \brief a far less complex random generator that uses
0184 //!        operating system provided entropy which will
0185 //!        satisfy the majority of use cases
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     //! \returns a random, valid uuid
0207     //! \throws entropy_error
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 }} // namespace boost::uuids
0227 
0228 #endif // BOOST_UUID_RANDOM_GENERATOR_HPP