added iOS source code
[wl-app.git] / iOS / Pods / Realm / Realm / ObjectStore / src / util / uuid.cpp
1 ////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright 2017 Realm Inc.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 ////////////////////////////////////////////////////////////////////////////
18
19 #include "util/uuid.hpp"
20
21 #include <algorithm>
22 #include <array>
23 #include <functional>
24 #include <random>
25 #include <stdio.h>
26
27 namespace {
28
29 // Seed `engine` with as much random state as it requires, based on the approach outlined in P0205R0.
30 // <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0205r0.html>
31 template <typename T>
32 T create_and_seed_engine()
33 {
34     constexpr auto bytes_needed = T::state_size * sizeof(typename T::result_type);
35
36     constexpr auto numbers_needed = sizeof(std::random_device::result_type) < sizeof(std::seed_seq::result_type)
37                                     ? (bytes_needed / sizeof(std::random_device::result_type))
38                                     : (bytes_needed / sizeof(std::seed_seq::result_type));
39
40     std::array<std::random_device::result_type, numbers_needed> state;
41     std::random_device rd;
42     std::generate(begin(state), end(state), std::ref(rd));
43     std::seed_seq seeds(begin(state), end(state));
44
45     T engine;
46     engine.seed(seeds);
47     return engine;
48 }
49
50 } // unnamed namespace
51
52 namespace realm {
53 namespace util {
54
55 std::string uuid_string()
56 {
57     static auto engine = create_and_seed_engine<std::mt19937>();
58
59     std::array<uint8_t, 16> uuid_bytes;
60     std::uniform_int_distribution<unsigned int> distribution(0, std::numeric_limits<uint8_t>::max());
61     std::generate(begin(uuid_bytes), end(uuid_bytes), [&] { return distribution(engine); });
62
63     // Version 4 UUID.
64     uuid_bytes[6] = (uuid_bytes[6] & 0x0f) | 0x40;
65     // IETF variant.
66     uuid_bytes[8] = (uuid_bytes[8] & 0x3f) | 0x80;
67
68     std::array<char, 37> uuid_formatted;
69     snprintf(uuid_formatted.data(), uuid_formatted.size(),
70              "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
71              uuid_bytes[0], uuid_bytes[1], uuid_bytes[2], uuid_bytes[3],
72              uuid_bytes[4], uuid_bytes[5], uuid_bytes[6], uuid_bytes[7],
73              uuid_bytes[8], uuid_bytes[9], uuid_bytes[10], uuid_bytes[11],
74              uuid_bytes[12], uuid_bytes[13], uuid_bytes[14], uuid_bytes[15]);
75
76     return std::string(uuid_formatted.data(), uuid_formatted.size() - 1);
77 }
78
79 } // namespace util
80 } // namespace realm