annotate DEPENDENCIES/generic/include/boost/uuid/seed_rng.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 // Boost seed_rng.hpp header file ----------------------------------------------//
Chris@16 2
Chris@16 3 // Copyright 2007 Andy Tompkins.
Chris@16 4 // Distributed under the Boost Software License, Version 1.0. (See
Chris@16 5 // accompanying file LICENSE_1_0.txt or copy at
Chris@16 6 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 7
Chris@16 8 // Revision History
Chris@16 9 // 09 Nov 2007 - Initial Revision
Chris@16 10 // 25 Feb 2008 - moved to namespace boost::uuids::detail
Chris@16 11 // 28 Nov 2009 - disabled deprecated warnings for MSVC
Chris@16 12
Chris@16 13 // seed_rng models a UniformRandomNumberGenerator (see Boost.Random).
Chris@16 14 // Random number generators are hard to seed well. This is intended to provide
Chris@16 15 // good seed values for random number generators.
Chris@16 16 // It creates random numbers from a sha1 hash of data from a variary of sources,
Chris@16 17 // all of which are standard function calls. It produces random numbers slowly.
Chris@16 18 // Peter Dimov provided the details of sha1_random_digest_().
Chris@16 19 // see http://archives.free.net.ph/message/20070507.175609.4c4f503a.en.html
Chris@16 20
Chris@16 21 #ifndef BOOST_UUID_SEED_RNG_HPP
Chris@16 22 #define BOOST_UUID_SEED_RNG_HPP
Chris@16 23
Chris@16 24 #include <boost/config.hpp>
Chris@16 25 #include <cstring> // for memcpy
Chris@16 26 #include <limits>
Chris@16 27 #include <ctime> // for time_t, time, clock_t, clock
Chris@16 28 #include <cstdlib> // for rand
Chris@16 29 #include <cstdio> // for FILE, fopen, fread, fclose
Chris@16 30 #include <boost/uuid/sha1.hpp>
Chris@16 31 //#include <boost/nondet_random.hpp> //forward declare boost::random::random_device
Chris@16 32
Chris@16 33 // can't use boost::generator_iterator since boost::random number seed(Iter&, Iter)
Chris@16 34 // functions need a last iterator
Chris@16 35 //#include <boost/generator_iterator.hpp>
Chris@16 36 # include <boost/iterator/iterator_facade.hpp>
Chris@16 37
Chris@16 38 #if defined(_MSC_VER)
Chris@16 39 #pragma warning(push) // Save warning settings.
Chris@16 40 #pragma warning(disable : 4996) // Disable deprecated std::fopen
Chris@16 41 #endif
Chris@16 42
Chris@16 43 #ifdef BOOST_NO_STDC_NAMESPACE
Chris@16 44 namespace std {
Chris@16 45 using ::memcpy;
Chris@16 46 using ::time_t;
Chris@16 47 using ::time;
Chris@16 48 using ::clock_t;
Chris@16 49 using ::clock;
Chris@16 50 using ::rand;
Chris@16 51 using ::FILE;
Chris@16 52 using ::fopen;
Chris@16 53 using ::fread;
Chris@16 54 using ::fclose;
Chris@16 55 } //namespace std
Chris@16 56 #endif
Chris@16 57
Chris@16 58 // forward declare random number generators
Chris@16 59 namespace boost { namespace random {
Chris@16 60 class random_device;
Chris@16 61 }} //namespace boost::random
Chris@16 62
Chris@16 63 namespace boost {
Chris@16 64 namespace uuids {
Chris@16 65 namespace detail {
Chris@16 66
Chris@16 67 // should this be part of Boost.Random?
Chris@16 68 class seed_rng
Chris@16 69 {
Chris@16 70 public:
Chris@16 71 typedef unsigned int result_type;
Chris@16 72 BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
Chris@16 73 //BOOST_STATIC_CONSTANT(unsigned int, min_value = 0);
Chris@16 74 //BOOST_STATIC_CONSTANT(unsigned int, max_value = UINT_MAX);
Chris@16 75
Chris@16 76 public:
Chris@16 77 // note: rd_ intentionally left uninitialized
Chris@16 78 seed_rng()
Chris@16 79 : rd_index_(5)
Chris@16 80 , random_(std::fopen( "/dev/urandom", "rb" ))
Chris@16 81 {}
Chris@16 82
Chris@16 83 ~seed_rng()
Chris@16 84 {
Chris@16 85 if (random_) {
Chris@16 86 std::fclose(random_);
Chris@16 87 }
Chris@16 88 }
Chris@16 89
Chris@16 90 result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const
Chris@16 91 {
Chris@16 92 return (std::numeric_limits<result_type>::min)();
Chris@16 93 }
Chris@16 94 result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const
Chris@16 95 {
Chris@16 96 return (std::numeric_limits<result_type>::max)();
Chris@16 97 }
Chris@16 98
Chris@16 99 result_type operator()()
Chris@16 100 {
Chris@16 101 if (rd_index_ >= 5) {
Chris@16 102 //get new digest
Chris@16 103 sha1_random_digest_();
Chris@16 104
Chris@16 105 rd_index_ = 0;
Chris@16 106 }
Chris@16 107
Chris@16 108 return rd_[rd_index_++];
Chris@16 109 }
Chris@16 110
Chris@16 111 private:
Chris@16 112 inline void ignore_size(size_t) {}
Chris@16 113
Chris@16 114 static unsigned int * sha1_random_digest_state_()
Chris@16 115 {
Chris@16 116 static unsigned int state[ 5 ];
Chris@16 117 return state;
Chris@16 118 }
Chris@16 119
Chris@16 120 void sha1_random_digest_()
Chris@16 121 {
Chris@16 122 boost::uuids::detail::sha1 sha;
Chris@16 123
Chris@16 124 unsigned int * ps = sha1_random_digest_state_();
Chris@16 125
Chris@16 126 unsigned int state[ 5 ];
Chris@16 127 std::memcpy( state, ps, sizeof( state ) ); // harmless data race
Chris@16 128
Chris@16 129 sha.process_bytes( (unsigned char const*)state, sizeof( state ) );
Chris@16 130 sha.process_bytes( (unsigned char const*)&ps, sizeof( ps ) );
Chris@16 131
Chris@16 132 {
Chris@16 133 std::time_t tm = std::time( 0 );
Chris@16 134 sha.process_bytes( (unsigned char const*)&tm, sizeof( tm ) );
Chris@16 135 }
Chris@16 136
Chris@16 137 {
Chris@16 138 std::clock_t ck = std::clock();
Chris@16 139 sha.process_bytes( (unsigned char const*)&ck, sizeof( ck ) );
Chris@16 140 }
Chris@16 141
Chris@16 142 {
Chris@16 143 unsigned int rn[] =
Chris@16 144 { static_cast<unsigned int>(std::rand())
Chris@16 145 , static_cast<unsigned int>(std::rand())
Chris@16 146 , static_cast<unsigned int>(std::rand())
Chris@16 147 };
Chris@16 148 sha.process_bytes( (unsigned char const*)rn, sizeof( rn ) );
Chris@16 149 }
Chris@16 150
Chris@16 151 {
Chris@16 152 // intentionally left uninitialized
Chris@16 153 unsigned char buffer[ 20 ];
Chris@16 154
Chris@16 155 if(random_)
Chris@16 156 {
Chris@16 157 ignore_size(std::fread( buffer, 1, 20, random_ ));
Chris@16 158 }
Chris@16 159
Chris@16 160 // using an uninitialized buffer[] if fopen fails
Chris@16 161 // intentional, we rely on its contents being random
Chris@16 162 sha.process_bytes( buffer, sizeof( buffer ) );
Chris@16 163 }
Chris@16 164
Chris@16 165 {
Chris@16 166 // *p is intentionally left uninitialized
Chris@16 167 unsigned int * p = new unsigned int;
Chris@16 168
Chris@16 169 sha.process_bytes( (unsigned char const*)p, sizeof( *p ) );
Chris@16 170 sha.process_bytes( (unsigned char const*)&p, sizeof( p ) );
Chris@16 171
Chris@16 172 delete p;
Chris@16 173 }
Chris@16 174
Chris@16 175 sha.process_bytes( (unsigned char const*)rd_, sizeof( rd_ ) );
Chris@16 176
Chris@16 177 unsigned int digest[ 5 ];
Chris@16 178 sha.get_digest( digest );
Chris@16 179
Chris@16 180 for( int i = 0; i < 5; ++i )
Chris@16 181 {
Chris@16 182 // harmless data race
Chris@16 183 ps[ i ] ^= digest[ i ];
Chris@16 184 rd_[ i ] ^= digest[ i ];
Chris@16 185 }
Chris@16 186 }
Chris@16 187
Chris@16 188 private:
Chris@16 189 unsigned int rd_[5];
Chris@16 190 int rd_index_;
Chris@16 191 std::FILE * random_;
Chris@16 192
Chris@16 193 private: // make seed_rng noncopyable
Chris@16 194 seed_rng(seed_rng const&);
Chris@16 195 seed_rng& operator=(seed_rng const&);
Chris@16 196 };
Chris@16 197
Chris@16 198 // almost a copy of boost::generator_iterator
Chris@16 199 // but default constructor sets m_g to NULL
Chris@16 200 template <class Generator>
Chris@16 201 class generator_iterator
Chris@16 202 : public iterator_facade<
Chris@16 203 generator_iterator<Generator>
Chris@16 204 , typename Generator::result_type
Chris@16 205 , single_pass_traversal_tag
Chris@16 206 , typename Generator::result_type const&
Chris@16 207 >
Chris@16 208 {
Chris@16 209 typedef iterator_facade<
Chris@16 210 generator_iterator<Generator>
Chris@16 211 , typename Generator::result_type
Chris@16 212 , single_pass_traversal_tag
Chris@16 213 , typename Generator::result_type const&
Chris@16 214 > super_t;
Chris@16 215
Chris@16 216 public:
Chris@16 217 generator_iterator() : m_g(NULL), m_value(0) {}
Chris@16 218 generator_iterator(Generator* g) : m_g(g), m_value((*m_g)()) {}
Chris@16 219
Chris@16 220 void increment()
Chris@16 221 {
Chris@16 222 m_value = (*m_g)();
Chris@16 223 }
Chris@16 224
Chris@16 225 const typename Generator::result_type&
Chris@16 226 dereference() const
Chris@16 227 {
Chris@16 228 return m_value;
Chris@16 229 }
Chris@16 230
Chris@16 231 bool equal(generator_iterator const& y) const
Chris@16 232 {
Chris@16 233 return this->m_g == y.m_g && this->m_value == y.m_value;
Chris@16 234 }
Chris@16 235
Chris@16 236 private:
Chris@16 237 Generator* m_g;
Chris@16 238 typename Generator::result_type m_value;
Chris@16 239 };
Chris@16 240
Chris@16 241 // seed() seeds a random number generator with good seed values
Chris@16 242
Chris@16 243 template <typename UniformRandomNumberGenerator>
Chris@16 244 inline void seed(UniformRandomNumberGenerator& rng)
Chris@16 245 {
Chris@16 246 seed_rng seed_gen;
Chris@16 247 generator_iterator<seed_rng> begin(&seed_gen);
Chris@16 248 generator_iterator<seed_rng> end;
Chris@16 249 rng.seed(begin, end);
Chris@16 250 }
Chris@16 251
Chris@16 252 // random_device does not / can not be seeded
Chris@16 253 template <>
Chris@16 254 inline void seed<boost::random::random_device>(boost::random::random_device&) {}
Chris@16 255
Chris@16 256 // random_device does not / can not be seeded
Chris@16 257 template <>
Chris@16 258 inline void seed<seed_rng>(seed_rng&) {}
Chris@16 259
Chris@16 260 }}} //namespace boost::uuids::detail
Chris@16 261
Chris@16 262 #if defined(_MSC_VER)
Chris@16 263 #pragma warning(pop) // Restore warnings to previous state.
Chris@16 264 #endif
Chris@16 265
Chris@16 266 #endif