summaryrefslogtreecommitdiffstats
path: root/contrib/src/boost/uuid/random_generator.hpp
blob: 0aa7e0d95280feee419a0e18e5bec4044b5958df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Boost random_generator.hpp header file  ----------------------------------------------//


// Copyright 2010 Andy Tompkins.

// 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)


#ifndef BOOST_UUID_RANDOM_GENERATOR_HPP

#define BOOST_UUID_RANDOM_GENERATOR_HPP


#include <boost/uuid/uuid.hpp>

#include <boost/uuid/seed_rng.hpp>

#include <boost/random/uniform_int.hpp>

#include <boost/random/variate_generator.hpp>

#include <boost/random/mersenne_twister.hpp>

#include <boost/assert.hpp>

#include <boost/shared_ptr.hpp>

#include <limits>


namespace boost {
namespace uuids {

// generate a random-based uuid

template <typename UniformRandomNumberGenerator>
class basic_random_generator {
private:
    typedef uniform_int<unsigned long> distribution_type;
    typedef variate_generator<UniformRandomNumberGenerator*, distribution_type> generator_type;

    struct null_deleter
    {
        void operator()(void const *) const {}
    };

public:
    typedef uuid result_type;

    // default constructor creates the random number generator

    basic_random_generator()
        : pURNG(new UniformRandomNumberGenerator)
        , generator
          ( pURNG.get()
          , distribution_type
            ( (std::numeric_limits<unsigned long>::min)()
            , (std::numeric_limits<unsigned long>::max)()
            )
          )
    {
        // seed the random number generator

        detail::seed(*pURNG);
    }

    // keep a reference to a random number generator

    // don't seed a given random number generator

    explicit basic_random_generator(UniformRandomNumberGenerator& gen)
        : pURNG(&gen, null_deleter())
        , generator
          ( pURNG.get()
          , distribution_type
            ( (std::numeric_limits<unsigned long>::min)()
            , (std::numeric_limits<unsigned long>::max)()
            )
          )
    {}

    // keep a pointer to a random number generator

    // don't seed a given random number generator

    explicit basic_random_generator(UniformRandomNumberGenerator* pGen)
        : pURNG(pGen, null_deleter())
        , generator
          ( pURNG.get()
          , distribution_type
            ( (std::numeric_limits<unsigned long>::min)()
            , (std::numeric_limits<unsigned long>::max)()
            )
          )
    {
        BOOST_ASSERT(pURNG);
    }

    uuid operator()()
    {
        uuid u;

        int i=0;
        unsigned long random_value = generator();
        for (uuid::iterator it=u.begin(); it!=u.end(); ++it, ++i) {
            if (i==sizeof(unsigned long)) {
                random_value = generator();
                i = 0;
            }

            // static_cast gets rid of warnings of converting unsigned long to boost::uint8_t

            *it = static_cast<uuid::value_type>((random_value >> (i*8)) & 0xFF);
        }

        // 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;
    }

private:
    shared_ptr<UniformRandomNumberGenerator> pURNG;
    generator_type generator;
};

typedef basic_random_generator<mt19937> random_generator;

}} // namespace boost::uuids


#endif //BOOST_UUID_RANDOM_GENERATOR_HPP