zhangmeng
2024-04-09 2561a007b8d8999a4750046d0cfb3b1ad5af50ac
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
120
121
122
123
124
125
#include "sole.h"
 
#define SOLE_BUILD_DEMO
 
#ifdef SOLE_BUILD_DEMO
// g++ users: `g++ demo.cc -std=c++11 -lrt -o sample`
// visual studio: `cl.exe demo.cc sole.cpp`
 
#include <iostream>
 
int main() {
    sole::uuid u0 = sole::uuid0(), u1 = sole::uuid1(), u4 = sole::uuid4();
 
    std::cout << "uuid v0 string : " << u0 << std::endl;
    std::cout << "uuid v0 base62 : " << u0.base62() << std::endl;
    std::cout << "uuid v0 pretty : " << u0.pretty() << std::endl << std::endl;
 
    std::cout << "uuid v1 string : " << u1 << std::endl;
    std::cout << "uuid v1 base62 : " << u1.base62() << std::endl;
    std::cout << "uuid v1 pretty : " << u1.pretty() << std::endl << std::endl;
 
    std::cout << "uuid v4 string : " << u4 << std::endl;
    std::cout << "uuid v4 base62 : " << u4.base62() << std::endl;
    std::cout << "uuid v4 pretty : " << u4.pretty() << std::endl << std::endl;
 
    std::cout << "uuid v4 length : " << u4.str().length() << std::endl;
 
    std::string test("123");
    std::cout << "test length : " << test.length() << std::endl;
    u1 = sole::rebuild("F81D4FAE-7DEC-11D0-A765-00A0C91E6BF6");
    u4 = sole::rebuild("GITheR4tLlg-BagIW20DGja");
 
    std::cout << "uuid v1 rebuilt : " << u1 << " -> " << u1.pretty() << std::endl;
    std::cout << "uuid v4 rebuilt : " << u4 << " -> " << u4.pretty() << std::endl;
}
 
#endif
 
#ifdef SOLE_BUILD_TESTS
// g++ users: `g++ sole.cxx -std=c++11 -lrt -o tests`
// visual studio: `cl.exe sole.cxx`
 
#include <cassert>
#include <set>
#include <ratio>
#include <chrono>
#include <iostream>
 
using namespace sole;
 
namespace run
{
    auto epoch = [](){
        return std::chrono::system_clock::to_time_t( std::chrono::system_clock::now() );
    };
 
    template<typename FN>
    void benchmark( const FN &fn, const std::string &name ) {
        std::cout << "Benchmarking " << name << "... " << std::flush;
 
        auto then = epoch();
 
        while( epoch() == then );
        then = epoch();
 
        unsigned c = 0;
        while( epoch() == then ) c = ( fn(), ++c );
 
        std::cout << (c) << " uuids/sec" << std::endl;
    }
 
    template<typename FN>
    void tests( const FN &fn ) {
        unsigned numtests = ~0;
        std::cout << "Testing for " << numtests << " collisions... " << std::endl;
 
        auto then = epoch();
 
        std::set<uuid> all;
        for( unsigned i = 0; i < numtests; ++i ) {
            auto now = epoch();
            if( now != then ) {
                then = now;
                double pct6digs = ( int( ( double(i) / (unsigned)(~0) ) * 1e4 ) / double(1e4) );
                std::cout << '\r' << i << " uuids generated, no collision (" << pct6digs << "%)" << std::flush;
            }
            sole::uuid my_uuid = fn();
            assert( all.find(my_uuid) == all.end() && "error: UUIDs just collided! is std::random_device a real random generator?" );
            all.insert( my_uuid );
        }
    }
 
    template<typename FN>
    void verify( const FN &fn ) {
        std::cout << "Verifying serialization of 1 million UUIDs... " << std::flush;
 
        for( unsigned i = 0; i < 1000000; ++i ) {
            sole::uuid uuid = fn();
            sole::uuid rebuilt1 = sole::rebuild( uuid.str() );
            sole::uuid rebuilt2 = sole::rebuild( uuid.base62() );
            assert( rebuilt1 == uuid && "error: rebuild() or .str() failed" );
            assert( rebuilt2 == uuid && "error: rebuild() or .base62() failed" );
        }
 
        std::cout << "ok" << std::endl;
    }
}
 
int main() {
    assert( sizeof(sole::uuid      )  * 8 == 128 );
    assert( sizeof(sole::uuid0().ab)  * 8 ==  64 );
    assert( sizeof(sole::uuid0().cd)  * 8 ==  64 );
 
    run::benchmark(uuid0, "v0");
    run::benchmark(uuid1, "v1");
    run::benchmark(uuid4, "v4");
 
    run::verify(uuid4);             // use fastest implementation
 
//  run::tests(uuid0);              // not applicable
//  run::tests(uuid1);              // not applicable
    run::tests(uuid4);
}
 
#endif