random_provider.hpp 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. //
  2. // Copyright (c) 2017 James E. King III
  3. //
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt or copy at
  6. // https://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // Platform-specific random entropy provider
  9. //
  10. #ifndef BOOST_UUID_DETAIL_RANDOM_PROVIDER_HPP
  11. #define BOOST_UUID_DETAIL_RANDOM_PROVIDER_HPP
  12. #include <boost/config.hpp>
  13. #include <boost/cstdint.hpp>
  14. #include <boost/limits.hpp>
  15. #include <boost/static_assert.hpp>
  16. #include <boost/move/core.hpp>
  17. #include <boost/move/utility_core.hpp>
  18. #include <boost/type_traits/is_integral.hpp>
  19. #include <boost/type_traits/is_unsigned.hpp>
  20. #include <boost/uuid/entropy_error.hpp>
  21. #include <climits>
  22. #include <iterator>
  23. // Detection of the platform is separated from inclusion of the correct
  24. // header to facilitate mock testing of the provider implementations.
  25. #include <boost/uuid/detail/random_provider_detect_platform.hpp>
  26. #include <boost/uuid/detail/random_provider_include_platform.hpp>
  27. namespace boost {
  28. namespace uuids {
  29. namespace detail {
  30. //! \brief Contains code common to all random_provider implementations.
  31. //! \note random_provider_base is required to provide this method:
  32. //! void get_random_bytes(void *buf, size_t siz);
  33. //! \note noncopyable because of some base implementations so
  34. //! this makes it uniform across platforms to avoid any
  35. //! porting surprises
  36. class random_provider :
  37. public detail::random_provider_base
  38. {
  39. BOOST_MOVABLE_BUT_NOT_COPYABLE(random_provider)
  40. public:
  41. BOOST_DEFAULTED_FUNCTION(random_provider(), {})
  42. random_provider(BOOST_RV_REF(random_provider) that) BOOST_NOEXCEPT :
  43. detail::random_provider_base(boost::move(static_cast< detail::random_provider_base& >(that)))
  44. {
  45. }
  46. random_provider& operator= (BOOST_RV_REF(random_provider) that) BOOST_NOEXCEPT
  47. {
  48. static_cast< detail::random_provider_base& >(*this) = boost::move(static_cast< detail::random_provider_base& >(that));
  49. return *this;
  50. }
  51. //! Leverage the provider as a SeedSeq for
  52. //! PseudoRandomNumberGeneration seeing.
  53. //! \note: See Boost.Random documentation for more details
  54. template<class Iter>
  55. void generate(Iter first, Iter last)
  56. {
  57. typedef typename std::iterator_traits<Iter>::value_type value_type;
  58. BOOST_STATIC_ASSERT(is_integral<value_type>::value);
  59. BOOST_STATIC_ASSERT(is_unsigned<value_type>::value);
  60. BOOST_STATIC_ASSERT(sizeof(value_type) * CHAR_BIT >= 32);
  61. for (; first != last; ++first)
  62. {
  63. get_random_bytes(&*first, sizeof(*first));
  64. *first &= (std::numeric_limits<boost::uint32_t>::max)();
  65. }
  66. }
  67. //! Return the name of the selected provider
  68. const char * name() const
  69. {
  70. return BOOST_UUID_RANDOM_PROVIDER_STRINGIFY(BOOST_UUID_RANDOM_PROVIDER_NAME);
  71. }
  72. };
  73. } // detail
  74. } // uuids
  75. } // boost
  76. #endif // BOOST_UUID_DETAIL_RANDOM_PROVIDER_HPP