diff options
Diffstat (limited to 'boost/uuid/random_generator.hpp')
-rw-r--r-- | boost/uuid/random_generator.hpp | 105 |
1 files changed, 83 insertions, 22 deletions
diff --git a/boost/uuid/random_generator.hpp b/boost/uuid/random_generator.hpp index a635ef03f7..c84fc5472c 100644 --- a/boost/uuid/random_generator.hpp +++ b/boost/uuid/random_generator.hpp @@ -1,6 +1,7 @@ // Boost random_generator.hpp header file ----------------------------------------------// // Copyright 2010 Andy Tompkins. +// Copyright 2017 James E. King III // 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) @@ -8,20 +9,43 @@ #ifndef BOOST_UUID_RANDOM_GENERATOR_HPP #define BOOST_UUID_RANDOM_GENERATOR_HPP -#include <boost/uuid/uuid.hpp> -#include <boost/uuid/detail/seed_rng.hpp> +#include <boost/assert.hpp> +#include <boost/core/enable_if.hpp> +#include <boost/core/null_deleter.hpp> +#include <boost/random/mersenne_twister.hpp> #include <boost/random/uniform_int.hpp> #include <boost/random/variate_generator.hpp> -#include <boost/random/mersenne_twister.hpp> -#include <boost/core/null_deleter.hpp> -#include <boost/assert.hpp> #include <boost/shared_ptr.hpp> +#include <boost/tti/has_member_function.hpp> +#include <boost/uuid/detail/random_provider.hpp> +#include <boost/uuid/uuid.hpp> #include <limits> namespace boost { namespace uuids { -// generate a random-based uuid +namespace detail { + template<class U> + U& set_uuid_random_vv(U& u) + { + // 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; + } + + BOOST_TTI_HAS_MEMBER_FUNCTION(seed) +} + +//! generate a random-based uuid +//! \param[in] UniformRandomNumberGenerator see Boost.Random documentation template <typename UniformRandomNumberGenerator> class basic_random_generator { private: @@ -31,7 +55,9 @@ private: public: typedef uuid result_type; - // default constructor creates the random number generator + // default constructor creates the random number generator and + // if the UniformRandomNumberGenerator is a PseudoRandomNumberGenerator + // then it gets seeded by a random_provider. basic_random_generator() : pURNG(new UniformRandomNumberGenerator) , generator @@ -42,8 +68,8 @@ public: ) ) { - // seed the random number generator - detail::seed(*pURNG); + // seed the random number generator if it is capable + seed(*pURNG); } // keep a reference to a random number generator @@ -74,9 +100,9 @@ public: BOOST_ASSERT(pURNG); } - uuid operator()() + result_type operator()() { - uuid u; + result_type u; int i=0; unsigned long random_value = generator(); @@ -90,26 +116,61 @@ public: *it = static_cast<uuid::value_type>((random_value >> (i*8)) & 0xFF); } - // set variant - // must be 0b10xxxxxx - *(u.begin()+8) &= 0xBF; - *(u.begin()+8) |= 0x80; + return detail::set_uuid_random_vv(u); + } - // set version - // must be 0b0100xxxx - *(u.begin()+6) &= 0x4F; //0b01001111 - *(u.begin()+6) |= 0x40; //0b01000000 +private: + // Detect whether UniformRandomNumberGenerator has a seed() method which indicates that + // it is a PseudoRandomNumberGenerator and needs a seed to initialize it. This allows + // basic_random_generator to take any type of UniformRandomNumberGenerator and still + // meet the post-conditions for the default constructor. + + template<class MaybePseudoRandomNumberGenerator> + typename boost::enable_if<detail::has_member_function_seed<MaybePseudoRandomNumberGenerator, void> >::type + seed(MaybePseudoRandomNumberGenerator& rng) + { + detail::random_provider seeder; + rng.seed(seeder); + } - return u; + template<class MaybePseudoRandomNumberGenerator> + typename boost::disable_if<detail::has_member_function_seed<MaybePseudoRandomNumberGenerator, void> >::type + seed(MaybePseudoRandomNumberGenerator&) + { } -private: shared_ptr<UniformRandomNumberGenerator> pURNG; generator_type generator; }; +//! \brief a far less complex random generator that uses +//! operating system provided entropy which will +//! satisfy the majority of use cases +class random_generator_pure +{ +public: + typedef uuid result_type; + + //! \returns a random, valid uuid + //! \throws entropy_error + result_type operator()() + { + result_type result; + prov_.get_random_bytes(&result, sizeof(result_type)); + return detail::set_uuid_random_vv(result); + } + +private: + detail::random_provider prov_; +}; + +#if defined(BOOST_UUID_RANDOM_GENERATOR_COMPAT) typedef basic_random_generator<mt19937> random_generator; +#else +typedef random_generator_pure random_generator; +typedef basic_random_generator<mt19937> random_generator_mt19937; +#endif }} // namespace boost::uuids -#endif //BOOST_UUID_RANDOM_GENERATOR_HPP +#endif // BOOST_UUID_RANDOM_GENERATOR_HPP |