1 ////////////////////////////////////////////////////////////////////////////
3 // Copyright 2017 Realm Inc.
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
17 ////////////////////////////////////////////////////////////////////////////
19 #include "util/uuid.hpp"
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>
32 T create_and_seed_engine()
34 constexpr auto bytes_needed = T::state_size * sizeof(typename T::result_type);
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));
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));
50 } // unnamed namespace
55 std::string uuid_string()
57 static auto engine = create_and_seed_engine<std::mt19937>();
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); });
64 uuid_bytes[6] = (uuid_bytes[6] & 0x0f) | 0x40;
66 uuid_bytes[8] = (uuid_bytes[8] & 0x3f) | 0x80;
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]);
76 return std::string(uuid_formatted.data(), uuid_formatted.size() - 1);