basic_random_generator.hpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #ifndef BOOST_UUID_BASIC_RANDOM_GENERATOR_HPP_INCLUDED
  2. #define BOOST_UUID_BASIC_RANDOM_GENERATOR_HPP_INCLUDED
  3. // Copyright 2010 Andy Tompkins
  4. // Copyright 2017 James E. King III
  5. // Copyright 2024 Peter Dimov
  6. // Distributed under the Boost Software License, Version 1.0.
  7. // https://www.boost.org/LICENSE_1_0.txt
  8. #include <boost/uuid/uuid.hpp>
  9. #include <boost/uuid/detail/random_provider.hpp>
  10. #include <boost/uuid/detail/endian.hpp>
  11. #include <boost/assert.hpp>
  12. #include <type_traits>
  13. #include <random>
  14. #include <cstdint>
  15. namespace boost {
  16. namespace uuids {
  17. template<class UniformRandomNumberGenerator>
  18. class basic_random_generator
  19. {
  20. private:
  21. UniformRandomNumberGenerator* p_;
  22. UniformRandomNumberGenerator g_;
  23. public:
  24. using result_type = uuid;
  25. // default constructor creates the random number generator and
  26. // if the UniformRandomNumberGenerator is a PseudoRandomNumberGenerator
  27. // then it gets seeded by a random_provider.
  28. basic_random_generator(): p_( 0 ), g_()
  29. {
  30. // seed the random number generator if it is capable
  31. seed( g_, 0 );
  32. }
  33. // keep a reference to a random number generator
  34. // don't seed a given random number generator
  35. explicit basic_random_generator( UniformRandomNumberGenerator& gen ): p_( &gen )
  36. {
  37. }
  38. // keep a pointer to a random number generator
  39. // don't seed a given random number generator
  40. explicit basic_random_generator( UniformRandomNumberGenerator* gen ): p_( gen )
  41. {
  42. BOOST_ASSERT( gen != 0 );
  43. }
  44. result_type operator()()
  45. {
  46. UniformRandomNumberGenerator& gen = p_? *p_: g_;
  47. std::uniform_int_distribution<std::uint32_t> dist;
  48. result_type u;
  49. detail::store_native_u32( u.data + 0, dist( gen ) );
  50. detail::store_native_u32( u.data + 4, dist( gen ) );
  51. detail::store_native_u32( u.data + 8, dist( gen ) );
  52. detail::store_native_u32( u.data + 12, dist( gen ) );
  53. // set variant
  54. // must be 0b10xxxxxx
  55. *(u.begin() + 8) &= 0x3F;
  56. *(u.begin() + 8) |= 0x80;
  57. // set version
  58. // must be 0b0100xxxx
  59. *(u.begin() + 6) &= 0x0F; //0b00001111
  60. *(u.begin() + 6) |= 0x40; //0b01000000
  61. return u;
  62. }
  63. private:
  64. // Detect whether UniformRandomNumberGenerator has a seed() method which indicates that
  65. // it is a PseudoRandomNumberGenerator and needs a seed to initialize it. This allows
  66. // basic_random_generator to take any type of UniformRandomNumberGenerator and still
  67. // meet the post-conditions for the default constructor.
  68. template<class MaybePseudoRandomNumberGenerator, class En = decltype( std::declval<MaybePseudoRandomNumberGenerator&>().seed() )>
  69. void seed( MaybePseudoRandomNumberGenerator& rng, int )
  70. {
  71. detail::random_provider seeder;
  72. rng.seed(seeder);
  73. }
  74. template<class MaybePseudoRandomNumberGenerator>
  75. void seed( MaybePseudoRandomNumberGenerator&, long )
  76. {
  77. }
  78. };
  79. }} // namespace boost::uuids
  80. #endif // BOOST_UUID_BASIC_RANDOM_GENERATOR_HPP_INCLUDED